indent_size = 8
max_line_length = 109
-[*.sh]
+[*.sh,mkosi.build,mkosi.prepare,mkosi.postinst]
indent_style = space
indent_size = 4
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
- - uses: systemd/mkosi@4be912b0fa4931403fddf649aa242cd4406471c4
+ - uses: systemd/mkosi@1d131062066fe7b5a83b87319b4464b186adbb1c
- name: Configure
run: |
uint8_t reserved[7];
sd_id128_t file_id;
sd_id128_t machine_id;
- sd_id128_t boot_id; /* last writer */
+ sd_id128_t tail_entry_boot_id;
sd_id128_t seqnum_id;
le64_t header_size;
le64_t arena_size;
When journal file is first created the **file_id** is randomly and uniquely
initialized.
-When a writer opens a file it shall initialize the **boot_id** to the current
-boot id of the system.
+When a writer creates a file it shall initialize the **tail_entry_boot_id** to
+the current boot ID of the system. When appending an entry it shall update the
+field to the boot ID of that entry, so that it is guaranteed that the
+**tail_entry_monotonic** field refers to a timestamp of the monotonic clock
+associated with the boot with the ID indicated by the **tail_entry_boot_id**
+field. (Compatibility note: in older versions of the journal, the field was
+also supposed to be updated whenever the file was opened for any form of
+writing, including when opened to mark it as archived. This behaviour has been
+deemed problematic since without an associated boot ID the
+**tail_entry_monotonic** field is useless. To indicate whether the boot ID is
+updated only on append the JOURNAL_COMPATIBLE_TAIL_ENTRY_BOOT_ID is set. If it
+is not set, the **tail_entry_monotonic** field is not usable).
The currently used part of the file is the **header_size** plus the
**arena_size** field of the header. If a writer needs to write to a file where
entry has been written yet.
**tail_entry_monotonic** is the monotonic timestamp of the last entry in the
-file, referring to monotonic time of the boot identified by **boot_id**.
+file, referring to monotonic time of the boot identified by
+**tail_entry_boot_id**, but only if the
+JOURNAL_COMPATIBLE_TAIL_ENTRY_BOOT_ID feature flag is set, see above. If it
+is not set, this field might refer to a different boot then the one in the
+**tail_entry_boot_id** field, for example when the file was ultimately
+archived.
**data_hash_chain_depth** is a counter of the deepest chain in the data hash
table, minus one. This is updated whenever a chain is found that is longer than
};
enum {
- HEADER_COMPATIBLE_SEALED = 1 << 0,
+ HEADER_COMPATIBLE_SEALED = 1 << 0,
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID = 1 << 1,
};
```
HEADER_COMPATIBLE_SEALED indicates that the file includes TAG objects required
for Forward Secure Sealing.
+HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID indicates whether the
+**tail_entry_boot_id** field is strictly updated on initial creation of the
+file and whenever an entry is updated (in which case the flag is set), or also
+when the file is archived (in which case it is unset). New files should always
+set this flag (and thus not update the **tail_entry_boot_id** except when
+creating the file and when appending an entry to it.
## Dirty Detection
<command>systemd-boot</command> being installed.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-R</option></term>
+ <term><option>--print-root-device</option></term>
+
+ <listitem><para>Print the path to the block device node backing the root file system of the local
+ OS. This prints a path such as <filename>/dev/nvme0n1p5</filename>. If the root file system is backed
+ by dm-crypt/LUKS or dm-verity the underlying block device is returned. If the root file system is
+ backed by multiple block devices (as supported by btrfs) the operation will fail. If the switch is
+ specified twice (i.e. <option>-RR</option>) and the discovered block device is a partition device the
+ "whole" block device it belongs to is determined and printed
+ (e.g. <filename>/dev/nvme0n1</filename>). If the root file system is <literal>tmpfs</literal> (or a
+ similar in-memory file system), the block device backing <filename>/usr/</filename> is returned if
+ applicable. If the root file system is a network file system (e.g. NFS, CIFS) the operation will
+ fail.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--no-variables</option></term>
<listitem><para>Do not touch the firmware's boot loader list stored in EFI variables.</para></listitem>
<refsect1>
<title>Exit status</title>
- <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
+ <para>On success, 0 is returned, a non-zero failure code otherwise. <command>bootctl
+ --print-root-device</command> returns exit status 80 in case the root file system is not backed by single
+ block device, and other non-zero exit statusses on other errors.</para>
</refsect1>
<refsect1>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>list-paths</command> <optional><replaceable>PATTERN</replaceable>…</optional></term>
+
+ <listitem>
+ <para>List path units currently in memory, ordered by path. If one or more
+ <replaceable>PATTERN</replaceable>s are specified, only path units matching one of them are shown.
+ Produces output similar to
+ <programlisting>
+PATH CONDITION UNIT ACTIVATES
+/run/systemd/ask-password DirectoryNotEmpty systemd-ask-password-plymouth.path systemd-ask-password-plymouth.service
+/run/systemd/ask-password DirectoryNotEmpty systemd-ask-password-wall.path systemd-ask-password-wall.service
+/var/cache/cups/org.cups.cupsd PathExists cups.path cups.service
+
+3 paths listed.</programlisting>
+ </para>
+
+ <para>Also see <option>--show-types</option>, <option>--all</option>, and <option>--state=</option>.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>list-sockets</command> <optional><replaceable>PATTERN</replaceable>…</optional></term>
After=proxy-to-nginx.socket
[Service]
+Type=notify
ExecStart=/usr/lib/systemd/systemd-socket-proxyd /run/nginx/socket
PrivateTmp=yes
PrivateNetwork=yes]]></programlisting>
JoinsNamespaceOf=nginx.service
[Service]
+Type=notify
ExecStart=/usr/lib/systemd/systemd-socket-proxyd 127.0.0.1:8080
PrivateTmp=yes
PrivateNetwork=yes]]></programlisting>
# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
-ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:disable_coredump=0:use_madv_dontdump=1
-UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
-
-# On Fedora "ld" is (unfortunately — if you ask me) managed via
-# "alternatives". Since we'd like to support building images in environments
-# with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem
-# that /usr/bin/ld is a symlink that points to a non-existing file in
-# /etc/alternative/ in this mode. Let's work around this for now by manually
-# redirect "ld" to "ld.bfd", i.e. circumventing the /usr/bin/ld symlink.
-if [ ! -x /usr/bin/ld ] && [ -x /usr/bin/ld.bfd ]; then
- mkdir -p "$HOME"/bin
- ln -s /usr/bin/ld.bfd "$HOME"/bin/ld
- PATH="$HOME/bin:$PATH"
-fi
-
# If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it
# as out-of-tree build dir. Otherwise, let's make up our own builddir.
[ -z "$BUILDDIR" ] && BUILDDIR="$PWD"/build
PATH="$BUILDDIR:$PATH"
export PATH
-# Meson uses Python 3 and requires a locale with an UTF-8 character map.
-# Not running under UTF-8 makes the `ninja test` step break with a CodecError.
-# So let's ensure we're running under UTF-8.
-#
-# If our current locale already is UTF-8, then we don't need to do anything:
-if [ "$(locale charmap 2>/dev/null)" != "UTF-8" ] ; then
- # Try using C.UTF-8 locale, if available. This locale is not shipped
- # by upstream glibc, so it's not available in all distros.
- # (In particular, it's not available in Arch Linux.)
- if locale -a | grep -q -E "C.UTF-8|C.utf8"; then
- export LC_CTYPE=C.UTF-8
- # Finally, try something like en_US.UTF-8, which should be
- # available in Arch Linux, but is not present in Debian's
- # minimal image in our mkosi config.
- elif locale -a | grep -q en_US.utf8; then
- export LC_CTYPE=en_US.UTF-8
- else
- # If nothing works, fail early.
- echo "*** Could not find a valid locale that supports UTF-8. ***" >&2
- exit 1
- fi
-fi
-
# The bpftool script shipped by Ubuntu tries to find the actual program to run via querying `uname -r` and
# using the current kernel version. This obviously doesn't work in containers. As a workaround, we override
# the ubuntu script with a symlink to the first bpftool program we can find.
for bpftool in /usr/lib/linux-tools/*/bpftool; do
- [ -x "$bpftool" ] || continue
- ln -sf "$bpftool" "$BUILDDIR"/bpftool
- break
+ [ -x "$bpftool" ] || continue
+ ln -sf "$bpftool" "$BUILDDIR"/bpftool
+ break
done
# CentOS Stream 8 includes bpftool 4.18.0 which is lower than what we need. However, they've backported the
# specific feature we need ("gen skeleton") to this version, so we replace bpftool with a script that reports
# version 5.6.0 to satisfy meson which makes bpf work on CentOS Stream 8 as well.
if [ "$(grep '^ID=' /etc/os-release)" = "ID=\"centos\"" ] && [ "$(grep '^VERSION=' /etc/os-release)" = "VERSION=\"8\"" ]; then
- cat >"$BUILDDIR"/bpftool <<EOF
+ cat >"$BUILDDIR"/bpftool <<EOF
#!/bin/sh
if [ "\$1" = --version ]; then
- echo 5.6.0
+ echo 5.6.0
else
- exec /usr/sbin/bpftool \$@
+ exec /usr/sbin/bpftool \$@
fi
EOF
- chmod +x "$BUILDDIR"/bpftool
+ chmod +x "$BUILDDIR"/bpftool
fi
if [ ! -f "$BUILDDIR"/build.ninja ] ; then
- sysvinit_path=$(realpath /etc/init.d)
-
- init_path=$(realpath /sbin/init 2>/dev/null)
- if [ -z "$init_path" ] ; then
- rootprefix=""
- else
- rootprefix=${init_path%/lib/systemd/systemd}
- rootprefix=/${rootprefix#/}
- fi
-
- # On debian-like systems the library directory is not /usr/lib64 but /usr/lib/<arch-triplet>/.
- # It is important to use the right one especially for cryptsetup plugins, otherwise they will be
- # installed in the wrong directory and not be found by cryptsetup. Assume native build.
- if grep -q -e "ID=debian" -e "ID_LIKE=debian" /etc/os-release && command -v dpkg 2>/dev/null; then
- LIBDIR="-Drootlibdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
- PAMDIR="-Dpamlibdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security"
- fi
-
- # Cannot quote $LIBDIR and $PAMDIR, because they may be empty, and meson will fail.
- # shellcheck disable=SC2086
- meson setup "$BUILDDIR" \
- ${LIBDIR:-} \
- ${PAMDIR:-} \
- -D "sysvinit-path=$sysvinit_path" \
- -D "rootprefix=$rootprefix" \
- -D man=false \
- -D translations=false \
- -D version-tag="${VERSION_TAG}" \
- -D mode=developer \
- -D b_sanitize="${SANITIZERS:-none}" \
- -D install-tests=true \
- -D tests=unsafe \
- -D slow-tests=true \
- -D utmp=true \
- -D hibernate=true \
- -D ldconfig=true \
- -D resolve=true \
- -D efi=true \
- -D tpm=true \
- -D environment-d=true \
- -D binfmt=true \
- -D repart=true \
- -D sysupdate=true \
- -D coredump=true \
- -D pstore=true \
- -D oomd=true \
- -D logind=true \
- -D hostnamed=true \
- -D localed=true \
- -D machined=true \
- -D portabled=true \
- -D sysext=true \
- -D userdb=true \
- -D homed=true \
- -D networkd=true \
- -D timedated=true \
- -D timesyncd=true \
- -D remote=true \
- -D nss-myhostname=true \
- -D nss-mymachines=true \
- -D nss-resolve=true \
- -D nss-systemd=true \
- -D firstboot=true \
- -D randomseed=true \
- -D backlight=true \
- -D vconsole=true \
- -D quotacheck=true \
- -D sysusers=true \
- -D tmpfiles=true \
- -D importd=true \
- -D hwdb=true \
- -D rfkill=true \
- -D xdg-autostart=true \
- -D translations=true \
- -D polkit=true \
- -D acl=true \
- -D audit=true \
- -D blkid=true \
- -D fdisk=true \
- -D kmod=true \
- -D pam=true \
- -D pwquality=true \
- -D microhttpd=true \
- -D libcryptsetup=true \
- -D libcurl=true \
- -D idn=true \
- -D libidn2=true \
- -D qrencode=true \
- -D gcrypt=true \
- -D gnutls=true \
- -D openssl=true \
- -D cryptolib=openssl \
- -D p11kit=true \
- -D libfido2=true \
- -D tpm2=true \
- -D elfutils=true \
- -D zstd=true \
- -D xkbcommon=true \
- -D pcre2=true \
- -D glib=true \
- -D dbus=true \
- -D gnu-efi=true \
- -D kernel-install=true \
- -D analyze=true \
- -D bpf-framework=true \
- -D ukify=true
+ sysvinit_path=$(realpath /etc/init.d)
+
+ init_path=$(realpath /sbin/init 2>/dev/null)
+ if [ -z "$init_path" ] ; then
+ rootprefix=""
+ else
+ rootprefix=${init_path%/lib/systemd/systemd}
+ rootprefix=/${rootprefix#/}
+ fi
+
+ # On debian-like systems the library directory is not /usr/lib64 but /usr/lib/<arch-triplet>/.
+ # It is important to use the right one especially for cryptsetup plugins, otherwise they will be
+ # installed in the wrong directory and not be found by cryptsetup. Assume native build.
+ if grep -q -e "ID=debian" -e "ID_LIKE=debian" /etc/os-release && command -v dpkg 2>/dev/null; then
+ LIBDIR="-Drootlibdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
+ PAMDIR="-Dpamlibdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security"
+ fi
+
+ # Cannot quote $LIBDIR and $PAMDIR, because they may be empty, and meson will fail.
+ # shellcheck disable=SC2086
+ meson setup "$BUILDDIR" \
+ ${LIBDIR:-} \
+ ${PAMDIR:-} \
+ -D "sysvinit-path=$sysvinit_path" \
+ -D "rootprefix=$rootprefix" \
+ -D man=false \
+ -D translations=false \
+ -D version-tag="${VERSION_TAG}" \
+ -D mode=developer \
+ -D b_sanitize="${SANITIZERS:-none}" \
+ -D install-tests=true \
+ -D tests=unsafe \
+ -D slow-tests=true \
+ -D utmp=true \
+ -D hibernate=true \
+ -D ldconfig=true \
+ -D resolve=true \
+ -D efi=true \
+ -D tpm=true \
+ -D environment-d=true \
+ -D binfmt=true \
+ -D repart=true \
+ -D sysupdate=true \
+ -D coredump=true \
+ -D pstore=true \
+ -D oomd=true \
+ -D logind=true \
+ -D hostnamed=true \
+ -D localed=true \
+ -D machined=true \
+ -D portabled=true \
+ -D sysext=true \
+ -D userdb=true \
+ -D homed=true \
+ -D networkd=true \
+ -D timedated=true \
+ -D timesyncd=true \
+ -D remote=true \
+ -D nss-myhostname=true \
+ -D nss-mymachines=true \
+ -D nss-resolve=true \
+ -D nss-systemd=true \
+ -D firstboot=true \
+ -D randomseed=true \
+ -D backlight=true \
+ -D vconsole=true \
+ -D quotacheck=true \
+ -D sysusers=true \
+ -D tmpfiles=true \
+ -D importd=true \
+ -D hwdb=true \
+ -D rfkill=true \
+ -D xdg-autostart=true \
+ -D translations=true \
+ -D polkit=true \
+ -D acl=true \
+ -D audit=true \
+ -D blkid=true \
+ -D fdisk=true \
+ -D kmod=true \
+ -D pam=true \
+ -D pwquality=true \
+ -D microhttpd=true \
+ -D libcryptsetup=true \
+ -D libcurl=true \
+ -D idn=true \
+ -D libidn2=true \
+ -D qrencode=true \
+ -D gcrypt=true \
+ -D gnutls=true \
+ -D openssl=true \
+ -D cryptolib=openssl \
+ -D p11kit=true \
+ -D libfido2=true \
+ -D tpm2=true \
+ -D elfutils=true \
+ -D zstd=true \
+ -D xkbcommon=true \
+ -D pcre2=true \
+ -D glib=true \
+ -D dbus=true \
+ -D gnu-efi=true \
+ -D kernel-install=true \
+ -D analyze=true \
+ -D bpf-framework=true \
+ -D ukify=true
fi
-cd "$BUILDDIR"
-ninja "$@"
+ninja -C "$BUILDDIR" "$@"
if [ "$WITH_TESTS" = 1 ] ; then
- if [ -n "$SANITIZERS" ]; then
- export ASAN_OPTIONS="$ASAN_OPTIONS"
- export UBSAN_OPTIONS="$UBSAN_OPTIONS"
- TIMEOUT_MULTIPLIER=3
- else
- TIMEOUT_MULTIPLIER=1
- fi
-
- meson test --print-errorlogs --timeout-multiplier=$TIMEOUT_MULTIPLIER
+ if [ -n "$SANITIZERS" ]; then
+ export ASAN_OPTIONS="$MKOSI_ASAN_OPTIONS"
+ export UBSAN_OPTIONS="$MKOSI_UBSAN_OPTIONS"
+ TIMEOUT_MULTIPLIER=3
+ else
+ TIMEOUT_MULTIPLIER=1
+ fi
+
+ meson test -C "$BUILDDIR" --print-errorlogs --timeout-multiplier=$TIMEOUT_MULTIPLIER
fi
-cd "$SRCDIR"
meson install -C "$BUILDDIR" --quiet --no-rebuild --only-changed
-mkdir -p "$DESTDIR"/etc
-
-cat >"$DESTDIR"/etc/issue <<EOF
-\S (built from systemd tree)
-Kernel \r on an \m (\l)
-
-EOF
-
-if [ -n "$IMAGE_ID" ] ; then
- mkdir -p "$DESTDIR"/usr/lib
- sed -n \
- -e '/^IMAGE_ID=/!p' \
- -e "\$aIMAGE_ID=$IMAGE_ID" <"/usr/lib/os-release" >"${DESTDIR}/usr/lib/os-release"
-
- OSRELEASEFILE="$DESTDIR"/usr/lib/os-release
-else
- OSRELEASEFILE=/usr/lib/os-release
-fi
-
-
-if [ -n "$IMAGE_VERSION" ] ; then
- mkdir -p "$DESTDIR"/usr/lib
- sed -n \
- -e '/^IMAGE_VERSION=/!p' \
- -e "\$aIMAGE_VERSION=$IMAGE_VERSION" <$OSRELEASEFILE >"/tmp/os-release.tmp"
-
- cat /tmp/os-release.tmp >"$DESTDIR"/usr/lib/os-release
- rm /tmp/os-release.tmp
-fi
-
-# If $CI_BUILD is set, copy over the CI service which executes a service check
-# after boot and then shuts down the machine
-if [ -n "$CI_BUILD" ]; then
- mkdir -p "$DESTDIR/usr/lib/systemd/system"
- cp -v "$SRCDIR/test/mkosi-check-and-shutdown.service" "$DESTDIR/usr/lib/systemd/system/mkosi-check-and-shutdown.service"
- cp -v "$SRCDIR/test/mkosi-check-and-shutdown.sh" "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh"
- chmod +x "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh"
-fi
-
-if [ -n "$SANITIZERS" ]; then
- LD_PRELOAD=$(ldd "$BUILDDIR"/systemd | grep libasan.so | awk '{print $3}')
-
- mkdir -p "$DESTDIR/etc/systemd/system.conf.d"
-
- cat >"$DESTDIR/etc/systemd/system.conf.d/10-asan.conf" <<EOF
-[Manager]
-ManagerEnvironment=ASAN_OPTIONS=$ASAN_OPTIONS\\
- UBSAN_OPTIONS=$UBSAN_OPTIONS\\
- LD_PRELOAD=$LD_PRELOAD
-DefaultEnvironment=ASAN_OPTIONS=$ASAN_OPTIONS\\
- UBSAN_OPTIONS=$UBSAN_OPTIONS\\
- LD_PRELOAD=$LD_PRELOAD
-EOF
-
- # ASAN logs to stderr by default. However, journald's stderr is connected to /dev/null, so we lose
- # all the ASAN logs. To rectify that, let's connect journald's stdout to the console so that any
- # sanitizer failures appear directly on the user's console.
- mkdir -p "$DESTDIR/etc/systemd/system/systemd-journald.service.d"
-
- cat >"$DESTDIR/etc/systemd/system/systemd-journald.service.d/10-stdout-tty.conf" <<EOF
-[Service]
-StandardOutput=tty
-EOF
-
- # Both systemd and util-linux's login call vhangup() on /dev/console which disconnects all users.
- # This means systemd-journald can't log to /dev/console even if we configure `StandardOutput=tty`. As
- # a workaround, we modify console-getty.service to disable systemd's vhangup() and disallow login
- # from calling vhangup() so that journald's ASAN logs correctly end up in the console.
-
- mkdir -p "$DESTDIR/etc/systemd/system/console-getty.service.d"
-
- cat >"$DESTDIR/etc/systemd/system/console-getty.service.d/10-no-vhangup.conf" <<EOF
-[Service]
-TTYVHangup=no
-CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
-EOF
-fi
-
-# Make sure services aren't enabled by default on Debian/Ubuntu.
-mkdir -p "$DESTDIR/etc/systemd/system-preset"
-echo "disable *" >"$DESTDIR/etc/systemd/system-preset/99-mkosi.preset"
-
if [ -d mkosi.kernel/ ]; then
- cd "$SRCDIR/mkosi.kernel"
- mkdir -p "$BUILDDIR/mkosi.kernel"
-
- # Ensure fast incremental builds by fixating these values which usually change for each build.
- export KBUILD_BUILD_TIMESTAMP="Fri Jun 5 15:58:00 CEST 2015"
- export KBUILD_BUILD_HOST="mkosi"
-
- scripts/kconfig/merge_config.sh -O "$BUILDDIR/mkosi.kernel" \
- ../mkosi.kernel.config \
- tools/testing/selftests/bpf/config.x86_64 \
- tools/testing/selftests/bpf/config
-
- make O="$BUILDDIR/mkosi.kernel" -j "$(nproc)"
-
- KERNEL_RELEASE=$(make O="$BUILDDIR"/mkosi.kernel -s kernelrelease)
- mkdir -p "$DESTDIR/usr/lib/modules/$KERNEL_RELEASE"
- make O="$BUILDDIR/mkosi.kernel" INSTALL_MOD_PATH="$DESTDIR/usr" modules_install
- make O="$BUILDDIR/mkosi.kernel" INSTALL_PATH="$DESTDIR/usr/lib/modules/$KERNEL_RELEASE" install
- mkdir -p "$DESTDIR/usr/lib/kernel/selftests"
- make -C tools/testing/selftests -j "$(nproc)" O="$BUILDDIR/mkosi.kernel" KSFT_INSTALL_PATH="$DESTDIR/usr/lib/kernel/selftests" SKIP_TARGETS="" install
-
- ln -sf /usr/lib/kernel/selftests/bpf/bpftool "$DESTDIR/usr/bin/bpftool"
+ SRCDIR="$SRCDIR/mkosi.kernel"
+ BUILDDIR="$BUILDDIR/mkosi.kernel"
+ cd "$SRCDIR"
+ mkdir -p "$BUILDDIR"
+
+ # Ensure fast incremental builds by fixating these values which usually change for each build.
+ export KBUILD_BUILD_TIMESTAMP="Fri Jun 5 15:58:00 CEST 2015"
+ export KBUILD_BUILD_HOST="mkosi"
+
+ scripts/kconfig/merge_config.sh -O "$BUILDDIR" \
+ ../mkosi.kernel.config \
+ tools/testing/selftests/bpf/config.x86_64 \
+ tools/testing/selftests/bpf/config
+
+ make O="$BUILDDIR" -j "$(nproc)"
+
+ KERNEL_RELEASE=$(make O="$BUILDDIR" -s kernelrelease)
+ mkdir -p "$DESTDIR/usr/lib/modules/$KERNEL_RELEASE"
+ make O="$BUILDDIR" INSTALL_MOD_PATH="$DESTDIR/usr" modules_install
+ make O="$BUILDDIR" INSTALL_PATH="$DESTDIR/usr/lib/modules/$KERNEL_RELEASE" install
+ mkdir -p "$DESTDIR/usr/lib/kernel/selftests"
+ make -C tools/testing/selftests -j "$(nproc)" O="$BUILDDIR" KSFT_INSTALL_PATH="$DESTDIR/usr/lib/kernel/selftests" SKIP_TARGETS="" install
+
+ ln -sf /usr/lib/kernel/selftests/bpf/bpftool "$DESTDIR/usr/bin/bpftool"
fi
[Output]
Bootable=yes
-# Prevent ASAN warnings when building the image
+# Prevent ASAN warnings when building the image and ship the real ASAN options prefixed with MKOSI_.
Environment=ASAN_OPTIONS=verify_asan_link_order=false
+ MKOSI_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:disable_coredump=0:use_madv_dontdump=1
+ MKOSI_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
OutputDirectory=mkosi.output
[Content]
--- /dev/null
+\S (built from systemd tree)
+Kernel \r on an \m (\l)
--- /dev/null
+set debuginfod enabled off
+set build-id-verbose 0
#!/bin/sh
# SPDX-License-Identifier: LGPL-2.1-or-later
-if [ "$1" = "final" ]; then
- if command -v bootctl >/dev/null && [ -d "/efi" ]; then
- bootctl install
- fi
-
- cat >>/root/.gdbinit <<EOF
-set debuginfod enabled off
-set build-id-verbose 0
+if [ "$1" = "build" ]; then
+ exit 0
+fi
+
+if [ -n "$SANITIZERS" ]; then
+ LD_PRELOAD=$(ldd /usr/lib/systemd/systemd | grep libasan.so | awk '{print $3}')
+
+ mkdir -p /etc/systemd/system.conf.d
+
+ cat >/etc/systemd/system.conf.d/10-asan.conf <<EOF
+[Manager]
+ManagerEnvironment=ASAN_OPTIONS=$MKOSI_ASAN_OPTIONS\\
+ UBSAN_OPTIONS=$MKOSI_UBSAN_OPTIONS\\
+ LD_PRELOAD=$LD_PRELOAD
+DefaultEnvironment=ASAN_OPTIONS=$MKOSI_ASAN_OPTIONS\\
+ UBSAN_OPTIONS=$MKOSI_UBSAN_OPTIONS\\
+ LD_PRELOAD=$LD_PRELOAD
+EOF
+
+ # ASAN logs to stderr by default. However, journald's stderr is connected to /dev/null, so we lose
+ # all the ASAN logs. To rectify that, let's connect journald's stdout to the console so that any
+ # sanitizer failures appear directly on the user's console.
+ mkdir -p /etc/systemd/system/systemd-journald.service.d
+ cat >/etc/systemd/system/systemd-journald.service.d/10-stdout-tty.conf <<EOF
+[Service]
+StandardOutput=tty
EOF
- if [ -n "$SANITIZERS" ]; then
- # ASAN and syscall filters aren't compatible with each other.
- find / -name '*.service' -type f -exec sed -i 's/^\(MemoryDeny\|SystemCall\)/# \1/' {} +
+ # Both systemd and util-linux's login call vhangup() on /dev/console which disconnects all users.
+ # This means systemd-journald can't log to /dev/console even if we configure `StandardOutput=tty`. As
+ # a workaround, we modify console-getty.service to disable systemd's vhangup() and disallow login
+ # from calling vhangup() so that journald's ASAN logs correctly end up in the console.
+
+ mkdir -p /etc/systemd/system/console-getty.service.d
+ cat >/etc/systemd/system/console-getty.service.d/10-no-vhangup.conf <<EOF
+[Service]
+TTYVHangup=no
+CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
+EOF
+ # ASAN and syscall filters aren't compatible with each other.
+ find / -name '*.service' -type f -exec sed -i 's/^\(MemoryDeny\|SystemCall\)/# \1/' {} +
+
+ # `systemd-hwdb update` takes > 50s when built with sanitizers so let's not run it by default.
+ systemctl mask systemd-hwdb-update.service
+fi
- # `systemd-hwdb update` takes > 50s when built with sanitizers so let's not run it by default.
- systemctl mask systemd-hwdb-update.service
- fi
+# Make sure dnsmasq.service doesn't start on boot on Debian/Ubuntu.
+rm -f /etc/systemd/system/multi-user.target.wants/dnsmasq.service
- # Make sure dnsmasq.service doesn't start on boot on Debian/Ubuntu.
- rm -f /etc/systemd/system/multi-user.target.wants/dnsmasq.service
+if [ -n "$IMAGE_ID" ] ; then
+ sed -n \
+ -i \
+ -e '/^IMAGE_ID=/!p' \
+ -e "\$aIMAGE_ID=$IMAGE_ID" \
+ /usr/lib/os-release
fi
-# Temporary workaround until https://github.com/openSUSE/suse-module-tools/commit/158643414ddb8d8208016a5f03a4484d58944d7a
-# gets into OpenSUSE repos
-if [ "$1" = "final" ] && grep -q openSUSE /etc/os-release; then
- if [ -e "/usr/lib/systemd/system/boot-sysctl.service" ] && \
- ! grep -F -q 'ConditionPathExists=/boot/sysctl.conf' "/usr/lib/systemd/system/boot-sysctl.service"; then
- mkdir -p "/etc/systemd/system/boot-sysctl.service.d/"
- printf '[Unit]\nConditionPathExists=/boot/sysctl.conf-%%v' >"/etc/systemd/system/boot-sysctl.service.d/99-temporary-workaround.conf"
- fi
+if [ -n "$IMAGE_VERSION" ] ; then
+ sed -n \
+ -i \
+ -e '/^IMAGE_VERSION=/!p' \
+ -e "\$aIMAGE_VERSION=$IMAGE_VERSION" \
+ /usr/lib/os-release
fi
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Moo, 2018. #zanata
+# mooo <hazap@hotmail.com>, 2023.
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-20 10:35+0200\n"
-"PO-Revision-Date: 2019-04-08 22:01+0300\n"
-"Last-Translator: Moo\n"
-"Language-Team: Lithuanian\n"
+"PO-Revision-Date: 2023-02-21 23:20+0000\n"
+"Last-Translator: mooo <hazap@hotmail.com>\n"
+"Language-Team: Lithuanian <https://translate.fedoraproject.org/projects/"
+"systemd/master/lt/>\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.2.1\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
-"%100<10 || n%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && ("
+"n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Weblate 4.15.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Norint nustatyti sistemos laikÄ…, reikia nustatyti tapatybÄ™."
#: src/hostname/org.freedesktop.hostname1.policy:71
-#, fuzzy
msgid "Get system description"
-msgstr "Nustatyti sistemos laiko juostÄ…"
+msgstr "Gauti sistemos aprašą"
#: src/hostname/org.freedesktop.hostname1.policy:72
-#, fuzzy
msgid "Authentication is required to get system description."
-msgstr "Norint nustatyti sistemos laiko juostÄ…, reikia nustatyti tapatybÄ™."
+msgstr "Norint gauti sistemos aprašą, reikia nustatyti tapatybę."
#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
#: src/login/org.freedesktop.login1.policy:406
msgid "Change Session"
-msgstr ""
+msgstr "Keisti seansÄ…"
#: src/login/org.freedesktop.login1.policy:407
#, fuzzy
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
-#, fuzzy
msgid "Set DNS servers"
-msgstr "Registruoti DNS-SD tarnybÄ…"
+msgstr "Nustatyti DNS serverius"
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
-#, fuzzy
msgid "Authentication is required to set DNS servers."
-msgstr "Norint registruoti DNS-SD tarnybÄ…, reikia nustatyti tapatybÄ™"
+msgstr "Norint nustatyti DNS serverius, reikia nustatyti tapatybÄ™."
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
msgid "Set default route"
-msgstr ""
+msgstr "Nustatyti numatytąjį maršrutą"
#: src/network/org.freedesktop.network1.policy:56
#: src/resolve/org.freedesktop.resolve1.policy:67
-#, fuzzy
msgid "Authentication is required to set default route."
-msgstr ""
-"Norint nustatyti vietinio serverio pavadinimÄ…, reikia nustatyti tapatybÄ™."
+msgstr "Norint nustatyti numatytąjį maršrutą, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:77
msgid "Enable/disable LLMNR"
-msgstr ""
+msgstr "Įjungti/išjungti LLMNR"
#: src/network/org.freedesktop.network1.policy:67
#: src/resolve/org.freedesktop.resolve1.policy:78
-#, fuzzy
msgid "Authentication is required to enable or disable LLMNR."
-msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę."
+msgstr "Norint įjungti ar išjungti LLMNR, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:77
#: src/resolve/org.freedesktop.resolve1.policy:88
#: src/network/org.freedesktop.network1.policy:88
#: src/resolve/org.freedesktop.resolve1.policy:99
msgid "Enable/disable DNS over TLS"
-msgstr ""
+msgstr "Įjungti/išjungti DNS per TLS"
#: src/network/org.freedesktop.network1.policy:89
#: src/resolve/org.freedesktop.resolve1.policy:100
-#, fuzzy
msgid "Authentication is required to enable or disable DNS over TLS."
-msgstr "Norint registruoti DNS-SD tarnybÄ…, reikia nustatyti tapatybÄ™"
+msgstr "Norint įjungti ar išjungti DNS per TLS, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:99
#: src/resolve/org.freedesktop.resolve1.policy:110
msgid "Enable/disable DNSSEC"
-msgstr ""
+msgstr "Įjungti/išjungti DNSSEC"
#: src/network/org.freedesktop.network1.policy:100
#: src/resolve/org.freedesktop.resolve1.policy:111
-#, fuzzy
msgid "Authentication is required to enable or disable DNSSEC."
-msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę."
+msgstr "Norint įjungti ar išjungti DNSSEC, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
suspend-then-hibernate kexec list-jobs list-sockets
list-timers list-units list-unit-files poweroff
reboot rescue show-environment suspend get-default
- is-system-running preset-all list-automounts'
+ is-system-running preset-all list-automounts list-paths'
[FILE]='link switch-root bind mount-image'
[TARGETS]='set-default'
[MACHINES]='list-machines'
local -a unit_commands=(
# Unit Commands
"list-automounts:List automounts"
+ "list-paths:List paths"
"list-sockets:List sockets"
"list-timers:List timers"
"list-units:List units"
int safe_fork_full(
const char *name,
+ const int stdio_fds[3],
const int except_fds[],
size_t n_except_fds,
ForkFlags flags,
}
}
+ if (flags & FORK_REARRANGE_STDIO) {
+ if (stdio_fds) {
+ r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]);
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to rearrange stdio fds: %m");
+ _exit(EXIT_FAILURE);
+ }
+ } else {
+ r = make_null_stdio();
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+ } else if (flags & FORK_STDOUT_TO_STDERR) {
+ if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
+ log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (flags & FORK_CLOSE_ALL_FDS) {
/* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
log_close();
log_set_open_when_needed(false);
}
- if (flags & FORK_NULL_STDIO) {
- r = make_null_stdio();
- if (r < 0) {
- log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
- _exit(EXIT_FAILURE);
- }
-
- } else if (flags & FORK_STDOUT_TO_STDERR) {
- if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
- log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
- _exit(EXIT_FAILURE);
- }
- }
-
if (flags & FORK_RLIMIT_NOFILE_SAFE) {
r = rlimit_nofile_safe();
if (r < 0) {
* process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
* /proc/self/fd works correctly. */
- r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
+ r = safe_fork_full(outer_name,
+ NULL,
+ except_fds, n_except_fds,
+ (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
if (r < 0)
return r;
if (r == 0) {
}
/* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
- r = safe_fork_full(inner_name, except_fds, n_except_fds, flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO), &pid);
+ r = safe_fork_full(inner_name,
+ NULL,
+ except_fds, n_except_fds,
+ flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), &pid);
if (r < 0)
_exit(EXIT_FAILURE);
if (r == 0) {
FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child to SIGTERM */
FORK_DEATHSIG_SIGINT = 1 << 3, /* Set PR_DEATHSIG in the child to SIGINT */
- FORK_NULL_STDIO = 1 << 4, /* Connect 0,1,2 to /dev/null */
+ FORK_REARRANGE_STDIO = 1 << 4, /* Connect 0,1,2 to specified fds or /dev/null */
FORK_REOPEN_LOG = 1 << 5, /* Reopen log connection */
FORK_LOG = 1 << 6, /* Log above LOG_DEBUG log level about failures */
FORK_WAIT = 1 << 7, /* Wait until child exited */
FORK_CLOEXEC_OFF = 1 << 15, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
} ForkFlags;
-int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
+int safe_fork_full(
+ const char *name,
+ const int stdio_fds[3],
+ const int except_fds[],
+ size_t n_except_fds,
+ ForkFlags flags,
+ pid_t *ret_pid);
static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
- return safe_fork_full(name, NULL, 0, flags, ret_pid);
+ return safe_fork_full(name, NULL, NULL, 0, flags, ret_pid);
}
int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid);
#include <getopt.h>
+#include "blockdev-util.h"
#include "bootctl.h"
#include "bootctl-install.h"
#include "bootctl-random-seed.h"
#include "bootctl-systemd-efi-options.h"
#include "bootctl-uki.h"
#include "build.h"
+#include "devnum-util.h"
#include "dissect-image.h"
#include "escape.h"
#include "find-esp.h"
char *arg_xbootldr_path = NULL;
bool arg_print_esp_path = false;
bool arg_print_dollar_boot_path = false;
+unsigned arg_print_root_device = 0;
bool arg_touch_variables = true;
PagerFlags arg_pager_flags = 0;
bool arg_graceful = false;
" --image=PATH Operate on disk image as filesystem root\n"
" --install-source=auto|image|host\n"
" Where to pick files when using --root=/--image=\n"
- " -p --print-esp-path Print path to the EFI System Partition\n"
- " -x --print-boot-path Print path to the $BOOT partition\n"
+ " -p --print-esp-path Print path to the EFI System Partition mount point\n"
+ " -x --print-boot-path Print path to the $BOOT partition mount point\n"
+ " -R --print-root-device\n"
+ " Print path to the root device node\n"
" --no-variables Don't touch EFI variables\n"
" --no-pager Do not pipe output into a pager\n"
" --graceful Don't fail when the ESP cannot be found or EFI\n"
{ "print-esp-path", no_argument, NULL, 'p' },
{ "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */
{ "print-boot-path", no_argument, NULL, 'x' },
+ { "print-root-device", no_argument, NULL, 'R' },
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "graceful", no_argument, NULL, ARG_GRACEFUL },
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hpx", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hpxR", options, NULL)) >= 0)
switch (c) {
case 'h':
break;
case 'p':
- if (arg_print_dollar_boot_path)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--print-boot-path/-x cannot be combined with --print-esp-path/-p");
arg_print_esp_path = true;
break;
case 'x':
- if (arg_print_esp_path)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--print-boot-path/-x cannot be combined with --print-esp-path/-p");
arg_print_dollar_boot_path = true;
break;
+ case 'R':
+ arg_print_root_device ++;
+ break;
+
case ARG_NO_VARIABLES:
arg_touch_variables = false;
break;
assert_not_reached();
}
+ if (!!arg_print_esp_path + !!arg_print_dollar_boot_path + (arg_print_root_device > 0) > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--print-esp-path/-p, --print-boot-path/-x, --print-root-device=/-R cannot be combined.");
+
if ((arg_root || arg_image) && argv[optind] && !STR_IN_SET(argv[optind], "status", "list",
"install", "update", "remove", "is-installed", "random-seed", "unlink", "cleanup"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
if (r <= 0)
return r;
+ if (arg_print_root_device > 0) {
+ _cleanup_free_ char *path = NULL;
+ dev_t devno;
+
+ r = blockdev_get_root(LOG_ERR, &devno);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ log_error("Root file system not backed by a (single) whole block device.");
+ return 80; /* some recognizable error code */
+ }
+
+ if (arg_print_root_device > 1) {
+ r = block_get_whole_disk(devno, &devno);
+ if (r < 0)
+ log_debug_errno(r, "Unable to find whole block device for root block device, ignoring: %m");
+ }
+
+ r = device_path_make_canonical(S_IFBLK, devno, &path);
+ if (r < 0)
+ return log_oom();
+
+ puts(path);
+ return EXIT_SUCCESS;
+ }
+
/* Open up and mount the image */
if (arg_image) {
assert(!arg_root);
extern char *arg_xbootldr_path;
extern bool arg_print_esp_path;
extern bool arg_print_dollar_boot_path;
+extern unsigned arg_print_root_device;
extern bool arg_touch_variables;
extern PagerFlags arg_pager_flags;
extern bool arg_graceful;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <stdint.h>
-#include <uchar.h>
+#include "efi.h"
char16_t *get_bcd_title(uint8_t *bcd, size_t bcd_len);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efigpt.h>
-#include <efilib.h>
-#include <inttypes.h>
-
#include "bcd.h"
#include "bootspec-fundamental.h"
#include "console.h"
#include "measure.h"
#include "part-discovery.h"
#include "pe.h"
-#include "vmm.h"
+#include "proto/block-io.h"
+#include "proto/device-path.h"
+#include "proto/simple-text-io.h"
#include "random-seed.h"
#include "secure-boot.h"
#include "shim.h"
#include "ticks.h"
#include "util.h"
+#include "vmm.h"
#ifndef GNU_EFI_USE_MS_ABI
/* We do not use uefi_call_wrapper() in systemd-boot. As such, we rely on the
#error systemd-boot requires compilation with GNU_EFI_USE_MS_ABI defined.
#endif
-#define TEXT_ATTR_SWAP(c) EFI_TEXT_ATTR(((c) & 0b11110000) >> 4, (c) & 0b1111)
-
/* Magic string for recognizing our own binaries */
_used_ _section_(".sdmagic") static const char magic[] =
"#### LoaderInfo: systemd-boot " GIT_VERSION " ####";
for (;;) {
EFI_STATUS err;
uint64_t key;
- size_t j, cursor_color = TEXT_ATTR_SWAP(COLOR_EDIT);
+ size_t j, cursor_color = EFI_TEXT_ATTR_SWAP(COLOR_EDIT);
j = MIN(len - first, x_max);
memcpy(print, line + first, j * sizeof(char16_t));
print[cursor+1] = '\0';
do {
print_at(cursor + 1, y_pos, cursor_color, print + cursor);
- cursor_color = TEXT_ATTR_SWAP(cursor_color);
+ cursor_color = EFI_TEXT_ATTR_SWAP(cursor_color);
err = console_key_read(&key, 750 * 1000);
if (!IN_SET(err, EFI_SUCCESS, EFI_TIMEOUT, EFI_NOT_READY))
case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'w'):
case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('w')):
- case KEYPRESS(EFI_ALT_PRESSED, 0, CHAR_BACKSPACE):
+ case KEYPRESS(EFI_ALT_PRESSED, 0, '\b'):
/* backward-kill-word */
clear = 0;
if ((first + cursor) > 0 && line[first + cursor-1] == ' ') {
len = first + cursor;
continue;
- case KEYPRESS(0, 0, CHAR_LINEFEED):
- case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
+ case KEYPRESS(0, 0, '\n'):
+ case KEYPRESS(0, 0, '\r'):
case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
- case KEYPRESS(0, SCAN_F3, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
+ case KEYPRESS(0, SCAN_F3, '\r'): /* Teclast X98+ II firmware sends malformed events */
if (!streq16(line, *line_in)) {
free(*line_in);
*line_in = TAKE_PTR(line);
}
return true;
- case KEYPRESS(0, 0, CHAR_BACKSPACE):
+ case KEYPRESS(0, 0, '\b'):
if (len == 0)
continue;
if (first == 0 && cursor == 0)
if (firmware_setup) {
firmware_setup = false;
- if (key == KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN))
+ if (IN_SET(key, KEYPRESS(0, 0, '\r'), KEYPRESS(0, 0, '\n')))
reboot_into_firmware();
continue;
}
idx_highlight = config->entry_count-1;
break;
- case KEYPRESS(0, 0, CHAR_LINEFEED):
- case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
+ case KEYPRESS(0, 0, '\n'):
+ case KEYPRESS(0, 0, '\r'):
case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
- case KEYPRESS(0, SCAN_F3, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
+ case KEYPRESS(0, SCAN_F3, '\r'): /* Teclast X98+ II firmware sends malformed events */
case KEYPRESS(0, SCAN_RIGHT, 0):
exit = true;
break;
if (err != EFI_SUCCESS)
return;
- err = get_file_info_harder(handle, &file_info, &file_info_size);
+ err = get_file_info(handle, &file_info, &file_info_size);
if (err != EFI_SUCCESS)
return;
for (;;) {
_cleanup_free_ char *content = NULL;
- err = readdir_harder(entries_dir, &f, &f_size);
+ err = readdir(entries_dir, &f, &f_size);
if (err != EFI_SUCCESS || !f)
break;
size_t offs[_SECTION_MAX] = {}, szs[_SECTION_MAX] = {}, pos = 0;
char *line, *key, *value;
- err = readdir_harder(linux_dir, &f, &f_size);
+ err = readdir(linux_dir, &f, &f_size);
if (err != EFI_SUCCESS || !f)
break;
return err;
_cleanup_free_ EFI_FILE_INFO *info = NULL;
- err = get_file_info_harder(handle, &info, NULL);
+ err = get_file_info(handle, &info, NULL);
if (err != EFI_SUCCESS)
return err;
size_t dirent_size = 0;
ConfigEntry *entry = NULL;
- err = readdir_harder(keys_basedir, &dirent, &dirent_size);
+ err = readdir(keys_basedir, &dirent, &dirent_size);
if (err != EFI_SUCCESS || !dirent)
return err;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "console.h"
+#include "proto/graphics-output.h"
#include "util.h"
#define SYSTEM_FONT_WIDTH 8
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include "missing_efi.h"
+#include "efi.h"
+#include "proto/simple-text-io.h"
enum {
EFI_SHIFT_PRESSED = EFI_RIGHT_SHIFT_PRESSED|EFI_LEFT_SHIFT_PRESSED,
#include "cpio.h"
#include "measure.h"
+#include "proto/device-path.h"
#include "util.h"
static char *write_cpio_word(char *p, uint32_t v) {
for (;;) {
_cleanup_free_ char16_t *d = NULL;
- err = readdir_harder(extra_dir, &dirent, &dirent_size);
+ err = readdir(extra_dir, &dirent, &dirent_size);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to read extra directory of loaded image: %m");
if (!dirent) /* End of directory */
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <stdbool.h>
-#include <uchar.h>
+#include "efi.h"
+#include "proto/loaded-image.h"
EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-
#include "devicetree.h"
-#include "missing_efi.h"
+#include "proto/dt-fixup.h"
#include "util.h"
#define FDT_V1_SIZE (7*4)
if (err != EFI_SUCCESS)
return err;
- err = get_file_info_harder(handle, &info, NULL);
+ err = get_file_info(handle, &info, NULL);
if (err != EFI_SUCCESS)
return err;
if (info->FileSize < FDT_V1_SIZE || info->FileSize > 32 * 1024 * 1024)
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <uchar.h>
+#include "efi.h"
struct devicetree_state {
EFI_PHYSICAL_ADDRESS addr;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "disk.h"
+#include "proto/device-path.h"
#include "util.h"
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, char16_t uuid[static 37]) {
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <uchar.h>
+#include "efi.h"
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, char16_t uuid[static 37]);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "drivers.h"
#include "util.h"
return log_error_status(err, "Failed to open \\EFI\\systemd\\drivers: %m");
for (;;) {
- err = readdir_harder(drivers_dir, &dirent, &dirent_size);
+ err = readdir(drivers_dir, &dirent, &dirent_size);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to read extra directory of loaded image: %m");
if (!dirent) /* End of directory */
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
+#include "efi.h"
+#include "proto/loaded-image.h"
EFI_STATUS reconnect_all_drivers(void);
EFI_STATUS load_drivers(
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <stdbool.h>
-#include <stdint.h>
-#include <wchar.h>
-
#include "efi-string.h"
#if SD_BOOT
-# include "missing_efi.h"
+# include "proto/simple-text-io.h"
# include "util.h"
#else
# include <stdlib.h>
static const char * const warn_table[] = {
[EFI_SUCCESS] = "Success",
-#if SD_BOOT
[EFI_WARN_UNKNOWN_GLYPH] = "Unknown glyph",
[EFI_WARN_DELETE_FAILURE] = "Delete failure",
[EFI_WARN_WRITE_FAILURE] = "Write failure",
[EFI_WARN_STALE_DATA] = "Stale data",
[EFI_WARN_FILE_SYSTEM] = "File system",
[EFI_WARN_RESET_REQUIRED] = "Reset required",
-#endif
};
/* Errors have MSB set, remove it to keep the table compact. */
static const char * const err_table[] = {
[NOERR(EFI_ERROR_MASK)] = "Error",
[NOERR(EFI_LOAD_ERROR)] = "Load error",
-#if SD_BOOT
[NOERR(EFI_INVALID_PARAMETER)] = "Invalid parameter",
[NOERR(EFI_UNSUPPORTED)] = "Unsupported",
[NOERR(EFI_BAD_BUFFER_SIZE)] = "Bad buffer size",
[NOERR(EFI_SECURITY_VIOLATION)] = "Security violation",
[NOERR(EFI_CRC_ERROR)] = "CRC error",
[NOERR(EFI_END_OF_MEDIA)] = "End of media",
- [29] = "Reserved (29)",
- [30] = "Reserved (30)",
+ [NOERR(EFI_ERROR_RESERVED_29)] = "Reserved (29)",
+ [NOERR(EFI_ERROR_RESERVED_30)] = "Reserved (30)",
[NOERR(EFI_END_OF_FILE)] = "End of file",
[NOERR(EFI_INVALID_LANGUAGE)] = "Invalid language",
[NOERR(EFI_COMPROMISED_DATA)] = "Compromised data",
[NOERR(EFI_IP_ADDRESS_CONFLICT)] = "IP address conflict",
[NOERR(EFI_HTTP_ERROR)] = "HTTP error",
-#endif
};
static const char *status_to_string(EFI_STATUS status) {
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <uchar.h>
-
+#include "efi.h"
#include "macro-fundamental.h"
size_t strnlen8(const char *s, size_t n);
bool parse_number8(const char *s, uint64_t *ret_u, const char **ret_tail);
bool parse_number16(const char16_t *s, uint64_t *ret_u, const char16_t **ret_tail);
-typedef size_t EFI_STATUS;
-
-#if !SD_BOOT
-/* Provide these for unit testing. */
-enum {
- EFI_ERROR_MASK = ((EFI_STATUS) 1 << (sizeof(EFI_STATUS) * CHAR_BIT - 1)),
- EFI_SUCCESS = 0,
- EFI_LOAD_ERROR = 1 | EFI_ERROR_MASK,
-};
-#endif
-
#ifdef __clang__
# define _gnu_printf_(a, b) _printf_(a, b)
#else
# define printf(...) printf_status(EFI_SUCCESS, __VA_ARGS__)
# define xasprintf(...) xasprintf_status(EFI_SUCCESS, __VA_ARGS__)
+/* inttypes.h is provided by libc instead of the compiler and is not supposed to be used in freestanding
+ * environments. We could use clang __*_FMT*__ constants for this, bug gcc does not have them. :( */
+
+# if defined(__ILP32__)
+# define PRI64_PREFIX "ll"
+# elif defined(__LP64__)
+# define PRI64_PREFIX "l"
+# elif defined(__LLP64__) || (__SIZEOF_LONG__ == 4 && __SIZEOF_POINTER__ == 8)
+# define PRI64_PREFIX "ll"
+# else
+# error Unknown 64-bit data model
+# endif
+
+# define PRIi32 "i"
+# define PRIu32 "u"
+# define PRIx32 "x"
+# define PRIX32 "X"
+# define PRIiPTR "zi"
+# define PRIuPTR "zu"
+# define PRIxPTR "zx"
+# define PRIXPTR "zX"
+# define PRIi64 PRI64_PREFIX "i"
+# define PRIu64 PRI64_PREFIX "u"
+# define PRIx64 PRI64_PREFIX "x"
+# define PRIX64 PRI64_PREFIX "X"
+
/* The compiler normally has knowledge about standard functions such as memcmp, but this is not the case when
* compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
* optimizations again. Note that we still need to provide implementations as the compiler is free to not
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "macro-fundamental.h"
+
+#if SD_BOOT
+/* uchar.h/wchar.h are not suitable for freestanding environments. */
+typedef __WCHAR_TYPE__ wchar_t;
+typedef __CHAR16_TYPE__ char16_t;
+typedef __CHAR32_TYPE__ char32_t;
+
+/* Let's be paranoid and do some sanity checks. */
+assert_cc(__STDC_HOSTED__ == 0);
+assert_cc(sizeof(bool) == 1);
+assert_cc(sizeof(uint8_t) == 1);
+assert_cc(sizeof(uint16_t) == 2);
+assert_cc(sizeof(uint32_t) == 4);
+assert_cc(sizeof(uint64_t) == 8);
+assert_cc(sizeof(wchar_t) == 2);
+assert_cc(sizeof(char16_t) == 2);
+assert_cc(sizeof(char32_t) == 4);
+assert_cc(sizeof(size_t) == sizeof(void *));
+assert_cc(sizeof(size_t) == sizeof(uintptr_t));
+#else
+# include <uchar.h>
+# include <wchar.h>
+#endif
+
+/* We use size_t/ssize_t to represent UEFI UINTN/INTN. */
+typedef size_t EFI_STATUS;
+typedef intptr_t ssize_t;
+
+typedef void* EFI_HANDLE;
+typedef void* EFI_EVENT;
+typedef size_t EFI_TPL;
+typedef uint64_t EFI_LBA;
+typedef uint64_t EFI_PHYSICAL_ADDRESS;
+
+#if defined(__x86_64__)
+# define EFIAPI __attribute__((ms_abi))
+#else
+# define EFIAPI
+#endif
+
+#if __SIZEOF_POINTER__ == 8
+# define EFI_ERROR_MASK 0x8000000000000000ULL
+#elif __SIZEOF_POINTER__ == 4
+# define EFI_ERROR_MASK 0x80000000ULL
+#else
+# error Unsupported pointer size
+#endif
+
+#define EFIWARN(s) ((EFI_STATUS) s)
+#define EFIERR(s) ((EFI_STATUS) (s | EFI_ERROR_MASK))
+
+#define EFI_SUCCESS EFIWARN(0)
+#define EFI_WARN_UNKNOWN_GLYPH EFIWARN(1)
+#define EFI_WARN_DELETE_FAILURE EFIWARN(2)
+#define EFI_WARN_WRITE_FAILURE EFIWARN(3)
+#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4)
+#define EFI_WARN_STALE_DATA EFIWARN(5)
+#define EFI_WARN_FILE_SYSTEM EFIWARN(6)
+#define EFI_WARN_RESET_REQUIRED EFIWARN(7)
+
+#define EFI_LOAD_ERROR EFIERR(1)
+#define EFI_INVALID_PARAMETER EFIERR(2)
+#define EFI_UNSUPPORTED EFIERR(3)
+#define EFI_BAD_BUFFER_SIZE EFIERR(4)
+#define EFI_BUFFER_TOO_SMALL EFIERR(5)
+#define EFI_NOT_READY EFIERR(6)
+#define EFI_DEVICE_ERROR EFIERR(7)
+#define EFI_WRITE_PROTECTED EFIERR(8)
+#define EFI_OUT_OF_RESOURCES EFIERR(9)
+#define EFI_VOLUME_CORRUPTED EFIERR(10)
+#define EFI_VOLUME_FULL EFIERR(11)
+#define EFI_NO_MEDIA EFIERR(12)
+#define EFI_MEDIA_CHANGED EFIERR(13)
+#define EFI_NOT_FOUND EFIERR(14)
+#define EFI_ACCESS_DENIED EFIERR(15)
+#define EFI_NO_RESPONSE EFIERR(16)
+#define EFI_NO_MAPPING EFIERR(17)
+#define EFI_TIMEOUT EFIERR(18)
+#define EFI_NOT_STARTED EFIERR(19)
+#define EFI_ALREADY_STARTED EFIERR(20)
+#define EFI_ABORTED EFIERR(21)
+#define EFI_ICMP_ERROR EFIERR(22)
+#define EFI_TFTP_ERROR EFIERR(23)
+#define EFI_PROTOCOL_ERROR EFIERR(24)
+#define EFI_INCOMPATIBLE_VERSION EFIERR(25)
+#define EFI_SECURITY_VIOLATION EFIERR(26)
+#define EFI_CRC_ERROR EFIERR(27)
+#define EFI_END_OF_MEDIA EFIERR(28)
+#define EFI_ERROR_RESERVED_29 EFIERR(29)
+#define EFI_ERROR_RESERVED_30 EFIERR(30)
+#define EFI_END_OF_FILE EFIERR(31)
+#define EFI_INVALID_LANGUAGE EFIERR(32)
+#define EFI_COMPROMISED_DATA EFIERR(33)
+#define EFI_IP_ADDRESS_CONFLICT EFIERR(34)
+#define EFI_HTTP_ERROR EFIERR(35)
+
+typedef struct {
+ uint32_t Data1;
+ uint16_t Data2;
+ uint16_t Data3;
+ uint8_t Data4[8];
+} EFI_GUID;
+
+#define GUID_DEF(d1, d2, d3, d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7, d4_8) \
+ { d1, d2, d3, { d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7, d4_8 } }
+
+/* Creates a EFI_GUID pointer suitable for EFI APIs. Use of const allows the compiler to merge multiple
+ * uses (although, currently compilers do that regardless). Most EFI APIs declare their EFI_GUID input
+ * as non-const, but almost all of them are in fact const. */
+#define MAKE_GUID_PTR(name) ((EFI_GUID *) &(const EFI_GUID) name##_GUID)
+
+/* These allow MAKE_GUID_PTR() to work without requiring an extra _GUID in the passed name. We want to
+ * keep the GUID definitions in line with the UEFI spec. */
+#define EFI_GLOBAL_VARIABLE_GUID EFI_GLOBAL_VARIABLE
+#define EFI_FILE_INFO_GUID EFI_FILE_INFO_ID
+
+#define EFI_GLOBAL_VARIABLE \
+ GUID_DEF(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
+ GUID_DEF(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
+
+#define EVT_TIMER 0x80000000U
+#define EVT_RUNTIME 0x40000000U
+#define EVT_NOTIFY_WAIT 0x00000100U
+#define EVT_NOTIFY_SIGNAL 0x00000200U
+#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201U
+#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202U
+
+#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x01U
+#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x02U
+#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x04U
+#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x08U
+#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x10U
+#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x20U
+
+#define EFI_VARIABLE_NON_VOLATILE 0x01U
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x02U
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x04U
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x08U
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x10U
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x20U
+#define EFI_VARIABLE_APPEND_WRITE 0x40U
+#define EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS 0x80U
+
+#define EFI_TIME_ADJUST_DAYLIGHT 0x001U
+#define EFI_TIME_IN_DAYLIGHT 0x002U
+#define EFI_UNSPECIFIED_TIMEZONE 0x7FFU
+
+#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x01U
+#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x02U
+#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 0x04U
+#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED 0x08U
+#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED 0x10U
+#define EFI_OS_INDICATIONS_START_OS_RECOVERY 0x20U
+#define EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY 0x40U
+#define EFI_OS_INDICATIONS_JSON_CONFIG_DATA_REFRESH 0x80U
+
+#define EFI_PAGE_SIZE 4096U
+#define EFI_SIZE_TO_PAGES(s) ((s) + 0xFFFU) >> 12U
+
+/* These are common enough to warrant forward declaration. We also give them a
+ * shorter name for convenience. */
+typedef struct EFI_FILE_PROTOCOL EFI_FILE;
+typedef struct EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH;
+
+typedef struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+typedef struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+
+typedef enum {
+ TimerCancel,
+ TimerPeriodic,
+ TimerRelative,
+} EFI_TIMER_DELAY;
+
+typedef enum {
+ AllocateAnyPages,
+ AllocateMaxAddress,
+ AllocateAddress,
+ MaxAllocateType,
+} EFI_ALLOCATE_TYPE;
+
+typedef enum {
+ EfiReservedMemoryType,
+ EfiLoaderCode,
+ EfiLoaderData,
+ EfiBootServicesCode,
+ EfiBootServicesData,
+ EfiRuntimeServicesCode,
+ EfiRuntimeServicesData,
+ EfiConventionalMemory,
+ EfiUnusableMemory,
+ EfiACPIReclaimMemory,
+ EfiACPIMemoryNVS,
+ EfiMemoryMappedIO,
+ EfiMemoryMappedIOPortSpace,
+ EfiPalCode,
+ EfiPersistentMemory,
+ EfiUnacceptedMemoryType,
+ EfiMaxMemoryType,
+} EFI_MEMORY_TYPE;
+
+typedef enum {
+ AllHandles,
+ ByRegisterNotify,
+ ByProtocol,
+} EFI_LOCATE_SEARCH_TYPE;
+
+typedef enum {
+ EfiResetCold,
+ EfiResetWarm,
+ EfiResetShutdown,
+ EfiResetPlatformSpecific,
+} EFI_RESET_TYPE;
+
+typedef struct {
+ uint16_t Year;
+ uint8_t Month;
+ uint8_t Day;
+ uint8_t Hour;
+ uint8_t Minute;
+ uint8_t Second;
+ uint8_t Pad1;
+ uint32_t Nanosecond;
+ int16_t TimeZone;
+ uint8_t Daylight;
+ uint8_t Pad2;
+} EFI_TIME;
+
+typedef struct {
+ uint32_t Resolution;
+ uint32_t Accuracy;
+ bool SetsToZero;
+} EFI_TIME_CAPABILITIES;
+
+typedef struct {
+ uint64_t Signature;
+ uint32_t Revision;
+ uint32_t HeaderSize;
+ uint32_t CRC32;
+ uint32_t Reserved;
+} EFI_TABLE_HEADER;
+
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ void *RaiseTPL;
+ void *RestoreTPL;
+ EFI_STATUS (EFIAPI *AllocatePages)(
+ EFI_ALLOCATE_TYPE Type,
+ EFI_MEMORY_TYPE MemoryType,
+ size_t Pages,
+ EFI_PHYSICAL_ADDRESS *Memory);
+ EFI_STATUS (EFIAPI *FreePages)(
+ EFI_PHYSICAL_ADDRESS Memory,
+ size_t Pages);
+ void *GetMemoryMap;
+ EFI_STATUS (EFIAPI *AllocatePool)(
+ EFI_MEMORY_TYPE PoolType,
+ size_t Size,
+ void **Buffer);
+ EFI_STATUS (EFIAPI *FreePool)(void *Buffer);
+ EFI_STATUS (EFIAPI *CreateEvent)(
+ uint32_t Type,
+ EFI_TPL NotifyTpl,
+ void *NotifyFunction,
+ void *NotifyContext,
+ EFI_EVENT *Event);
+ EFI_STATUS (EFIAPI *SetTimer)(
+ EFI_EVENT Event,
+ EFI_TIMER_DELAY Type,
+ uint64_t TriggerTime);
+ EFI_STATUS (EFIAPI *WaitForEvent)(
+ size_t NumberOfEvents,
+ EFI_EVENT *Event,
+ size_t *Index);
+ void *SignalEvent;
+ EFI_STATUS (EFIAPI *CloseEvent)(EFI_EVENT Event);
+ EFI_STATUS (EFIAPI *CheckEvent)(EFI_EVENT Event);
+ void *InstallProtocolInterface;
+ EFI_STATUS (EFIAPI *ReinstallProtocolInterface)(
+ EFI_HANDLE Handle,
+ EFI_GUID *Protocol,
+ void *OldInterface,
+ void *NewInterface);
+ void *UninstallProtocolInterface;
+ EFI_STATUS (EFIAPI *HandleProtocol)(
+ EFI_HANDLE Handle,
+ EFI_GUID *Protocol,
+ void **Interface);
+ void *Reserved;
+ void *RegisterProtocolNotify;
+ EFI_STATUS (EFIAPI *LocateHandle)(
+ EFI_LOCATE_SEARCH_TYPE SearchType,
+ EFI_GUID *Protocol,
+ void *SearchKey,
+ size_t *BufferSize,
+ EFI_HANDLE *Buffer);
+ EFI_STATUS (EFIAPI *LocateDevicePath)(
+ EFI_GUID *Protocol,
+ EFI_DEVICE_PATH **DevicePath,
+ EFI_HANDLE *Device);
+ EFI_STATUS (EFIAPI *InstallConfigurationTable)(
+ EFI_GUID *Guid,
+ void *Table);
+ EFI_STATUS (EFIAPI *LoadImage)(
+ bool BootPolicy,
+ EFI_HANDLE ParentImageHandle,
+ EFI_DEVICE_PATH *DevicePath,
+ void *SourceBuffer,
+ size_t SourceSize,
+ EFI_HANDLE *ImageHandle);
+ EFI_STATUS (EFIAPI *StartImage)(
+ EFI_HANDLE ImageHandle,
+ size_t *ExitDataSize,
+ char16_t **ExitData);
+ EFI_STATUS (EFIAPI *Exit)(
+ EFI_HANDLE ImageHandle,
+ EFI_STATUS ExitStatus,
+ size_t ExitDataSize,
+ char16_t *ExitData);
+ EFI_STATUS (EFIAPI *UnloadImage)(EFI_HANDLE ImageHandle);
+ void *ExitBootServices;
+ EFI_STATUS (EFIAPI *GetNextMonotonicCount)(uint64_t *Count);
+ EFI_STATUS (EFIAPI *Stall)(size_t Microseconds);
+ EFI_STATUS (EFIAPI *SetWatchdogTimer)(
+ size_t Timeout,
+ uint64_t WatchdogCode,
+ size_t DataSize,
+ char16_t *WatchdogData);
+ EFI_STATUS (EFIAPI *ConnectController)(
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE *DriverImageHandle,
+ EFI_DEVICE_PATH *RemainingDevicePath,
+ bool Recursive);
+ EFI_STATUS (EFIAPI *DisconnectController)(
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE DriverImageHandle,
+ EFI_HANDLE ChildHandle);
+ EFI_STATUS (EFIAPI *OpenProtocol)(
+ EFI_HANDLE Handle,
+ EFI_GUID *Protocol,
+ void **Interface,
+ EFI_HANDLE AgentHandle,
+ EFI_HANDLE ControllerHandle,
+ uint32_t Attributes);
+ EFI_STATUS (EFIAPI *CloseProtocol)(
+ EFI_HANDLE Handle,
+ EFI_GUID *Protocol,
+ EFI_HANDLE AgentHandle,
+ EFI_HANDLE ControllerHandle);
+ void *OpenProtocolInformation;
+ EFI_STATUS (EFIAPI *ProtocolsPerHandle)(
+ EFI_HANDLE Handle,
+ EFI_GUID ***ProtocolBuffer,
+ size_t *ProtocolBufferCount);
+ EFI_STATUS (EFIAPI *LocateHandleBuffer)(
+ EFI_LOCATE_SEARCH_TYPE SearchType,
+ EFI_GUID *Protocol,
+ void *SearchKey,
+ size_t *NoHandles,
+ EFI_HANDLE **Buffer);
+ EFI_STATUS (EFIAPI *LocateProtocol)(
+ EFI_GUID *Protocol,
+ void *Registration,
+ void **Interface);
+ EFI_STATUS (EFIAPI *InstallMultipleProtocolInterfaces)(EFI_HANDLE *Handle, ...);
+ EFI_STATUS (EFIAPI *UninstallMultipleProtocolInterfaces)(EFI_HANDLE Handle, ...);
+ EFI_STATUS (EFIAPI *CalculateCrc32)(
+ void *Data,
+ size_t DataSize,
+ uint32_t *Crc32);
+ void (EFIAPI *CopyMem)(
+ void *Destination,
+ void *Source,
+ size_t Length);
+ void (EFIAPI *SetMem)(
+ void *Buffer,
+ size_t Size,
+ uint8_t Value);
+ void *CreateEventEx;
+} EFI_BOOT_SERVICES;
+
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ EFI_STATUS (EFIAPI *GetTime)(
+ EFI_TIME *Time,
+ EFI_TIME_CAPABILITIES *Capabilities);
+ EFI_STATUS (EFIAPI *SetTime)(EFI_TIME *Time);
+ void *GetWakeupTime;
+ void *SetWakeupTime;
+ void *SetVirtualAddressMap;
+ void *ConvertPointer;
+ EFI_STATUS (EFIAPI *GetVariable)(
+ char16_t *VariableName,
+ EFI_GUID *VendorGuid,
+ uint32_t *Attributes,
+ size_t *DataSize,
+ void *Data);
+ void *GetNextVariableName;
+ EFI_STATUS (EFIAPI *SetVariable)(
+ char16_t *VariableName,
+ EFI_GUID *VendorGuid,
+ uint32_t Attributes,
+ size_t DataSize,
+ void *Data);
+ EFI_STATUS (EFIAPI *GetNextHighMonotonicCount)(uint32_t *HighCount);
+ void (EFIAPI *ResetSystem)(
+ EFI_RESET_TYPE ResetType,
+ EFI_STATUS ResetStatus,
+ size_t DataSize,
+ void *ResetData);
+ void *UpdateCapsule;
+ void *QueryCapsuleCapabilities;
+ void *QueryVariableInfo;
+} EFI_RUNTIME_SERVICES;
+
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ char16_t *FirmwareVendor;
+ uint32_t FirmwareRevision;
+ EFI_HANDLE ConsoleInHandle;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
+ EFI_HANDLE ConsoleOutHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+ EFI_HANDLE StandardErrorHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
+ EFI_RUNTIME_SERVICES *RuntimeServices;
+ EFI_BOOT_SERVICES *BootServices;
+ size_t NumberOfTableEntries;
+ struct {
+ EFI_GUID VendorGuid;
+ void *VendorTable;
+ } *ConfigurationTable;
+} EFI_SYSTEM_TABLE;
+
+extern EFI_SYSTEM_TABLE *ST;
+extern EFI_BOOT_SERVICES *BS;
+extern EFI_RUNTIME_SERVICES *RT;
* Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
*/
-#include <efi.h>
-#include <efilib.h>
-
#include "graphics.h"
-#include "missing_efi.h"
+#include "proto/console-control.h"
+#include "proto/simple-text-io.h"
#include "util.h"
EFI_STATUS graphics_mode(bool on) {
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
EFI_CONSOLE_CONTROL_SCREEN_MODE new;
EFI_CONSOLE_CONTROL_SCREEN_MODE current;
- BOOLEAN uga_exists;
- BOOLEAN stdin_locked;
+ bool uga_exists, stdin_locked;
EFI_STATUS err;
- err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_CONSOLE_CONTROL), NULL, (void **) &ConsoleControl);
+ err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_CONSOLE_CONTROL_PROTOCOL), NULL, (void **) &ConsoleControl);
if (err != EFI_SUCCESS)
/* console control protocol is nonstandard and might not exist. */
return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
*/
#pragma once
-#include <efi.h>
-#include <stdbool.h>
+#include "efi.h"
EFI_STATUS graphics_mode(bool on);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "initrd.h"
#include "macro-fundamental.h"
-#include "missing_efi.h"
+#include "proto/device-path.h"
+#include "proto/load-file.h"
#include "util.h"
+#define LINUX_INITRD_MEDIA_GUID \
+ GUID_DEF(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
+
/* extend LoadFileProtocol */
struct initrd_loader {
EFI_LOAD_FILE_PROTOCOL load_file;
.Header = {
.Type = MEDIA_DEVICE_PATH,
.SubType = MEDIA_VENDOR_DP,
- .Length = { sizeof(efi_initrd_device_path.vendor), 0 }
+ .Length = sizeof(efi_initrd_device_path.vendor),
},
.Guid = LINUX_INITRD_MEDIA_GUID
},
.end = {
.Type = END_DEVICE_PATH_TYPE,
.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .Length = { sizeof(efi_initrd_device_path.end), 0 }
+ .Length = sizeof(efi_initrd_device_path.end),
}
};
static EFIAPI EFI_STATUS initrd_load_file(
EFI_LOAD_FILE_PROTOCOL *this,
EFI_DEVICE_PATH *file_path,
- BOOLEAN boot_policy,
+ bool boot_policy,
size_t *buffer_size,
void *buffer) {
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <stddef.h>
+#include "efi.h"
EFI_STATUS initrd_register(
const void *initrd_address,
* This method works for Linux 5.8 and newer on ARM/Aarch64, x86/x68_64 and RISC-V.
*/
-#include <efi.h>
-#include <efilib.h>
-
#include "initrd.h"
#include "linux.h"
#include "pe.h"
+#include "proto/device-path.h"
+#include "proto/loaded-image.h"
#include "secure-boot.h"
#include "util.h"
.Header = {
.Type = MEDIA_DEVICE_PATH,
.SubType = MEDIA_VENDOR_DP,
- .Length = { sizeof(payload_device_path.payload), 0 },
+ .Length = sizeof(payload_device_path.payload),
},
.Guid = STUB_PAYLOAD_GUID,
},
.end = {
.Type = END_DEVICE_PATH_TYPE,
.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .Length = { sizeof(payload_device_path.end), 0 },
+ .Length = sizeof(payload_device_path.end),
},
};
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <uchar.h>
+#include "efi.h"
EFI_STATUS linux_exec(
EFI_HANDLE parent,
* see https://docs.kernel.org/x86/boot.html
*/
-#include <efi.h>
-#include <efilib.h>
-
#include "initrd.h"
#include "linux.h"
#include "macro-fundamental.h"
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "log.h"
+#include "proto/simple-text-io.h"
static unsigned log_count = 0;
if (ST->ConOut->Mode->CursorColumn > 0)
ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n");
- ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
+ ST->ConOut->SetAttribute(ST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTRED, EFI_BLACK));
va_list ap;
va_start(ap, format);
#if ENABLE_TPM
-#include <efi.h>
-#include <efilib.h>
-
-#include "tpm-pcr.h"
#include "macro-fundamental.h"
#include "measure.h"
-#include "missing_efi.h"
+#include "proto/tcg.h"
+#include "tpm-pcr.h"
#include "util.h"
static EFI_STATUS tpm1_measure_to_pcr_and_event_log(
- const EFI_TCG *tcg,
+ const EFI_TCG_PROTOCOL *tcg,
uint32_t pcrindex,
EFI_PHYSICAL_ADDRESS buffer,
size_t buffer_size,
memcpy(tcg_event->Event, description, desc_len);
return tcg->HashLogExtendEvent(
- (EFI_TCG *) tcg,
+ (EFI_TCG_PROTOCOL *) tcg,
buffer, buffer_size,
TCG_ALG_SHA,
tcg_event,
}
static EFI_STATUS tpm2_measure_to_pcr_and_event_log(
- EFI_TCG2 *tcg,
+ EFI_TCG2_PROTOCOL *tcg,
uint32_t pcrindex,
EFI_PHYSICAL_ADDRESS buffer,
uint64_t buffer_size,
tcg_event);
}
-static EFI_TCG* tcg1_interface_check(void) {
+static EFI_TCG_PROTOCOL *tcg1_interface_check(void) {
EFI_PHYSICAL_ADDRESS event_log_location, event_log_last_entry;
- TCG_BOOT_SERVICE_CAPABILITY capability = {
+ EFI_TCG_BOOT_SERVICE_CAPABILITY capability = {
.Size = sizeof(capability),
};
EFI_STATUS err;
uint32_t features;
- EFI_TCG *tcg;
+ EFI_TCG_PROTOCOL *tcg;
- err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG), NULL, (void **) &tcg);
+ err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG_PROTOCOL), NULL, (void **) &tcg);
if (err != EFI_SUCCESS)
return NULL;
return tcg;
}
-static EFI_TCG2* tcg2_interface_check(void) {
+static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
.Size = sizeof(capability),
};
EFI_STATUS err;
- EFI_TCG2 *tcg;
+ EFI_TCG2_PROTOCOL *tcg;
- err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2), NULL, (void **) &tcg);
+ err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg);
if (err != EFI_SUCCESS)
return NULL;
if (capability.StructureVersion.Major == 1 &&
capability.StructureVersion.Minor == 0) {
- TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
- (TCG_BOOT_SERVICE_CAPABILITY*) &capability;
+ EFI_TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
+ (EFI_TCG_BOOT_SERVICE_CAPABILITY*) &capability;
if (caps_1_0->TPMPresentFlag)
return tcg;
}
}
EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
- EFI_TCG2 *tpm2;
+ EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err;
assert(description || pcrindex == UINT32_MAX);
if (tpm2)
err = tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
else {
- EFI_TCG *tpm1;
+ EFI_TCG_PROTOCOL *tpm1;
tpm1 = tcg1_interface_check();
if (tpm1)
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <stdbool.h>
-#include <uchar.h>
+#include "efi.h"
#if ENABLE_TPM
'-I', meson.current_source_dir(),
'-include', efi_config_h,
'-include', version_h,
- '-isystem', efi_incdir / efi_arch[1],
- '-isystem', efi_incdir,
'-std=gnu11',
'-Wall',
'-Wextra',
'-Wl,--warn-common',
'-Wl,-Bsymbolic',
'-z', 'nocombreloc',
+ '-z', 'noexecstack',
efi_crt0,
]
'disk.h',
'drivers.h',
'efi-string.h',
+ 'efi.h',
'graphics.h',
'initrd.h',
'linux.h',
'log.h',
'measure.h',
- 'missing_efi.h',
'part-discovery.h',
'pe.h',
+ 'proto/block-io.h',
+ 'proto/console-control.h',
+ 'proto/device-path.h',
+ 'proto/dt-fixup.h',
+ 'proto/file-io.h',
+ 'proto/graphics-output.h',
+ 'proto/load-file.h',
+ 'proto/loaded-image.h',
+ 'proto/rng.h',
+ 'proto/security-arch.h',
+ 'proto/shell-parameters.h',
+ 'proto/simple-text-io.h',
+ 'proto/tcg.h',
'random-seed.h',
'secure-boot.h',
'shim.h',
+++ /dev/null
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <efi.h>
-
-#include "macro-fundamental.h"
-
-/* gnu-efi 3.0.13 */
-#ifndef EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
-
-#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
- { 0xdd9e7534, 0x7762, 0x4698, {0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa} }
-#define SimpleTextInputExProtocol ((EFI_GUID)EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID)
-
-#define EFI_SHIFT_STATE_VALID 0x80000000
-#define EFI_RIGHT_SHIFT_PRESSED 0x00000001
-#define EFI_LEFT_SHIFT_PRESSED 0x00000002
-#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
-#define EFI_LEFT_CONTROL_PRESSED 0x00000008
-#define EFI_RIGHT_ALT_PRESSED 0x00000010
-#define EFI_LEFT_ALT_PRESSED 0x00000020
-#define EFI_RIGHT_LOGO_PRESSED 0x00000040
-#define EFI_LEFT_LOGO_PRESSED 0x00000080
-
-struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
-
-typedef EFI_STATUS (EFIAPI *EFI_INPUT_RESET_EX)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- BOOLEAN ExtendedVerification
-);
-
-typedef UINT8 EFI_KEY_TOGGLE_STATE;
-
-typedef struct {
- UINT32 KeyShiftState;
- EFI_KEY_TOGGLE_STATE KeyToggleState;
-} EFI_KEY_STATE;
-
-typedef struct {
- EFI_INPUT_KEY Key;
- EFI_KEY_STATE KeyState;
-} EFI_KEY_DATA;
-
-typedef EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY_EX)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- EFI_KEY_DATA *KeyData
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_SET_STATE)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- EFI_KEY_TOGGLE_STATE *KeyToggleState
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_KEY_NOTIFY_FUNCTION)(
- EFI_KEY_DATA *KeyData
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- EFI_KEY_DATA KeyData,
- EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
- VOID **NotifyHandle
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- VOID *NotificationHandle
-);
-
-typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
- EFI_INPUT_RESET_EX Reset;
- EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
- EFI_EVENT WaitForKeyEx;
- EFI_SET_STATE SetState;
- EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
- EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
-} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
-
-#endif
-
-/* gnu-efi 3.0.14 */
-#ifndef EFI_IMAGE_MACHINE_RISCV64
- #define EFI_IMAGE_MACHINE_RISCV64 0x5064
-#endif
-
-/* gnu-efi 3.0.14 */
-#ifndef EFI_DTB_TABLE_GUID
-#define EFI_DTB_TABLE_GUID \
- { 0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0} }
-#define EfiDtbTableGuid ((EFI_GUID)EFI_DTB_TABLE_GUID)
-#endif
-
-#ifndef EFI_DT_FIXUP_PROTOCOL_GUID
-#define EFI_DT_FIXUP_PROTOCOL_GUID \
- { 0xe617d64c, 0xfe08, 0x46da, {0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00} }
-#define EfiDtFixupProtocol ((EFI_GUID)EFI_DT_FIXUP_PROTOCOL_GUID)
-
-#define EFI_DT_FIXUP_PROTOCOL_REVISION 0x00010000
-
-/* Add nodes and update properties */
-#define EFI_DT_APPLY_FIXUPS 0x00000001
-/*
- * Reserve memory according to the /reserved-memory node
- * and the memory reservation block
- */
-#define EFI_DT_RESERVE_MEMORY 0x00000002
-
-typedef struct _EFI_DT_FIXUP_PROTOCOL EFI_DT_FIXUP_PROTOCOL;
-
-typedef EFI_STATUS (EFIAPI *EFI_DT_FIXUP) (
- IN EFI_DT_FIXUP_PROTOCOL *This,
- IN VOID *Fdt,
- IN OUT UINTN *BufferSize,
- IN UINT32 Flags);
-
-struct _EFI_DT_FIXUP_PROTOCOL {
- UINT64 Revision;
- EFI_DT_FIXUP Fixup;
-};
-
-#endif
-
-/* TCG EFI Protocol Specification */
-#ifndef EFI_TCG_GUID
-
-#define EFI_TCG_GUID \
- { 0xf541796d, 0xa62e, 0x4954, { 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd } }
-
-typedef struct _TCG_VERSION {
- UINT8 Major;
- UINT8 Minor;
- UINT8 RevMajor;
- UINT8 RevMinor;
-} TCG_VERSION;
-
-typedef struct tdEFI_TCG2_VERSION {
- UINT8 Major;
- UINT8 Minor;
-} EFI_TCG2_VERSION;
-
-typedef struct _TCG_BOOT_SERVICE_CAPABILITY {
- UINT8 Size;
- struct _TCG_VERSION StructureVersion;
- struct _TCG_VERSION ProtocolSpecVersion;
- UINT8 HashAlgorithmBitmap;
- BOOLEAN TPMPresentFlag;
- BOOLEAN TPMDeactivatedFlag;
-} TCG_BOOT_SERVICE_CAPABILITY;
-
-typedef struct tdTREE_BOOT_SERVICE_CAPABILITY {
- UINT8 Size;
- EFI_TCG2_VERSION StructureVersion;
- EFI_TCG2_VERSION ProtocolVersion;
- UINT32 HashAlgorithmBitmap;
- UINT32 SupportedEventLogs;
- BOOLEAN TrEEPresentFlag;
- UINT16 MaxCommandSize;
- UINT16 MaxResponseSize;
- UINT32 ManufacturerID;
-} TREE_BOOT_SERVICE_CAPABILITY;
-
-typedef UINT32 TCG_ALGORITHM_ID;
-#define TCG_ALG_SHA 0x00000004 // The SHA1 algorithm
-
-#define SHA1_DIGEST_SIZE 20
-
-typedef struct _TCG_DIGEST {
- UINT8 Digest[SHA1_DIGEST_SIZE];
-} TCG_DIGEST;
-
-#define EV_IPL 13
-
-typedef struct _TCG_PCR_EVENT {
- UINT32 PCRIndex;
- UINT32 EventType;
- struct _TCG_DIGEST digest;
- UINT32 EventSize;
- UINT8 Event[1];
-} TCG_PCR_EVENT;
-
-INTERFACE_DECL(_EFI_TCG);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG_STATUS_CHECK) (IN struct _EFI_TCG * This,
- OUT struct _TCG_BOOT_SERVICE_CAPABILITY * ProtocolCapability,
- OUT UINT32 * TCGFeatureFlags,
- OUT EFI_PHYSICAL_ADDRESS * EventLogLocation,
- OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_ALL) (IN struct _EFI_TCG * This,
- IN UINT8 * HashData,
- IN UINT64 HashDataLen,
- IN TCG_ALGORITHM_ID AlgorithmId,
- IN OUT UINT64 * HashedDataLen, IN OUT UINT8 ** HashedDataResult);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG_LOG_EVENT) (IN struct _EFI_TCG * This,
- IN struct _TCG_PCR_EVENT * TCGLogData,
- IN OUT UINT32 * EventNumber, IN UINT32 Flags);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG_PASS_THROUGH_TO_TPM) (IN struct _EFI_TCG * This,
- IN UINT32 TpmInputParameterBlockSize,
- IN UINT8 * TpmInputParameterBlock,
- IN UINT32 TpmOutputParameterBlockSize,
- IN UINT8 * TpmOutputParameterBlock);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_LOG_EXTEND_EVENT) (IN struct _EFI_TCG * This,
- IN EFI_PHYSICAL_ADDRESS HashData,
- IN UINT64 HashDataLen,
- IN TCG_ALGORITHM_ID AlgorithmId,
- IN struct _TCG_PCR_EVENT * TCGLogData,
- IN OUT UINT32 * EventNumber,
- OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry);
-
-typedef struct _EFI_TCG {
- EFI_TCG_STATUS_CHECK StatusCheck;
- EFI_TCG_HASH_ALL HashAll;
- EFI_TCG_LOG_EVENT LogEvent;
- EFI_TCG_PASS_THROUGH_TO_TPM PassThroughToTPM;
- EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
-} EFI_TCG;
-
-#endif
-
-/* TCG EFI Protocol Specification */
-#ifndef EFI_TCG2_GUID
-
-#define EFI_TCG2_GUID \
- { 0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f } }
-
-typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
-
-typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP;
-typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT;
-typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP;
-
-typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY {
- UINT8 Size;
- EFI_TCG2_VERSION StructureVersion;
- EFI_TCG2_VERSION ProtocolVersion;
- EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap;
- EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs;
- BOOLEAN TPMPresentFlag;
- UINT16 MaxCommandSize;
- UINT16 MaxResponseSize;
- UINT32 ManufacturerID;
- UINT32 NumberOfPCRBanks;
- EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks;
-} EFI_TCG2_BOOT_SERVICE_CAPABILITY;
-
-#define EFI_TCG2_EVENT_HEADER_VERSION 1
-
-typedef struct {
- UINT32 HeaderSize;
- UINT16 HeaderVersion;
- UINT32 PCRIndex;
- UINT32 EventType;
-} _packed_ EFI_TCG2_EVENT_HEADER;
-
-typedef struct tdEFI_TCG2_EVENT {
- UINT32 Size;
- EFI_TCG2_EVENT_HEADER Header;
- UINT8 Event[1];
-} _packed_ EFI_TCG2_EVENT;
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_CAPABILITY) (IN EFI_TCG2_PROTOCOL * This,
- IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY * ProtocolCapability);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_EVENT_LOG) (IN EFI_TCG2_PROTOCOL * This,
- IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat,
- OUT EFI_PHYSICAL_ADDRESS * EventLogLocation,
- OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry,
- OUT BOOLEAN * EventLogTruncated);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_HASH_LOG_EXTEND_EVENT) (IN EFI_TCG2_PROTOCOL * This,
- IN UINT64 Flags,
- IN EFI_PHYSICAL_ADDRESS DataToHash,
- IN UINT64 DataToHashLen, IN EFI_TCG2_EVENT * EfiTcgEvent);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_SUBMIT_COMMAND) (IN EFI_TCG2_PROTOCOL * This,
- IN UINT32 InputParameterBlockSize,
- IN UINT8 * InputParameterBlock,
- IN UINT32 OutputParameterBlockSize, IN UINT8 * OutputParameterBlock);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, OUT UINT32 * ActivePcrBanks);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, IN UINT32 ActivePcrBanks);
-
-typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This,
- OUT UINT32 * OperationPresent, OUT UINT32 * Response);
-
-typedef struct tdEFI_TCG2_PROTOCOL {
- EFI_TCG2_GET_CAPABILITY GetCapability;
- EFI_TCG2_GET_EVENT_LOG GetEventLog;
- EFI_TCG2_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
- EFI_TCG2_SUBMIT_COMMAND SubmitCommand;
- EFI_TCG2_GET_ACTIVE_PCR_BANKS GetActivePcrBanks;
- EFI_TCG2_SET_ACTIVE_PCR_BANKS SetActivePcrBanks;
- EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks;
-} EFI_TCG2;
-
-#endif
-
-#ifndef EFI_LOAD_FILE2_PROTOCOL_GUID
-#define EFI_LOAD_FILE2_PROTOCOL_GUID \
- {0x4006c0c1, 0xfcb3, 0x403e, {0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d} }
-#define EfiLoadFile2Protocol ((EFI_GUID)EFI_LOAD_FILE2_PROTOCOL_GUID)
-#endif
-
-#define LINUX_INITRD_MEDIA_GUID \
- {0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68} }
-
-/* UEFI Platform Initialization (Vol2: DXE) */
-#ifndef EFI_SECURITY_ARCH_PROTOCOL_GUID
-
-#define EFI_SECURITY_ARCH_PROTOCOL_GUID \
- { 0xa46423e3, 0x4617, 0x49f1, { 0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } }
-#define EFI_SECURITY2_ARCH_PROTOCOL_GUID \
- { 0x94ab2f58, 0x1438, 0x4ef1, { 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }
-
-typedef struct EFI_SECURITY_ARCH_PROTOCOL EFI_SECURITY_ARCH_PROTOCOL;
-typedef struct EFI_SECURITY2_ARCH_PROTOCOL EFI_SECURITY2_ARCH_PROTOCOL;
-
-typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE)(
- const EFI_SECURITY_ARCH_PROTOCOL *This,
- uint32_t AuthenticationStatus,
- const EFI_DEVICE_PATH *File);
-
-struct EFI_SECURITY_ARCH_PROTOCOL {
- EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
-};
-
-typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION)(
- const EFI_SECURITY2_ARCH_PROTOCOL *This,
- const EFI_DEVICE_PATH *DevicePath,
- void *FileBuffer,
- UINTN FileSize,
- BOOLEAN BootPolicy);
-
-struct EFI_SECURITY2_ARCH_PROTOCOL {
- EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
-};
-
-#endif
-
-#ifndef EFI_CONSOLE_CONTROL_GUID
-
-#define EFI_CONSOLE_CONTROL_GUID \
- { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }
-
-struct _EFI_CONSOLE_CONTROL_PROTOCOL;
-
-typedef enum {
- EfiConsoleControlScreenText,
- EfiConsoleControlScreenGraphics,
- EfiConsoleControlScreenMaxValue,
-} EFI_CONSOLE_CONTROL_SCREEN_MODE;
-
-typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE)(
- struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
- EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
- BOOLEAN *UgaExists,
- BOOLEAN *StdInLocked
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE)(
- struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
- EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN)(
- struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
- CHAR16 *Password
-);
-
-typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL {
- EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode;
- EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
- EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
-} EFI_CONSOLE_CONTROL_PROTOCOL;
-
-#endif
-
-#ifndef EFI_IMAGE_SECURITY_DATABASE_VARIABLE
-
-#define EFI_IMAGE_SECURITY_DATABASE_VARIABLE \
- { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }}
-
-#endif
-
-#ifndef EFI_SHELL_PARAMETERS_PROTOCOL_GUID
-# define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \
- { 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } }
-
-typedef struct {
- CHAR16 **Argv;
- UINTN Argc;
- void *StdIn;
- void *StdOut;
- void *StdErr;
-} EFI_SHELL_PARAMETERS_PROTOCOL;
-#endif
-
-#ifndef EFI_WARN_UNKNOWN_GLYPH
-# define EFI_WARN_UNKNOWN_GLYPH 1
-#endif
-
-#ifndef EFI_WARN_RESET_REQUIRED
-# define EFI_WARN_STALE_DATA 5
-# define EFI_WARN_FILE_SYSTEM 6
-# define EFI_WARN_RESET_REQUIRED 7
-# define EFI_IP_ADDRESS_CONFLICT EFIERR(34)
-# define EFI_HTTP_ERROR EFIERR(35)
-#endif
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efigpt.h>
-#include <efilib.h>
-
#include "part-discovery.h"
+#include "proto/block-io.h"
+#include "proto/device-path.h"
#include "util.h"
-union GptHeaderBuffer {
- EFI_PARTITION_TABLE_HEADER gpt_header;
- uint8_t space[CONST_ALIGN_TO(sizeof(EFI_PARTITION_TABLE_HEADER), 512)];
-};
+typedef struct {
+ EFI_GUID PartitionTypeGUID;
+ EFI_GUID UniquePartitionGUID;
+ EFI_LBA StartingLBA;
+ EFI_LBA EndingLBA;
+ uint64_t Attributes;
+ char16_t PartitionName[36];
+} EFI_PARTITION_ENTRY;
+
+typedef struct {
+ EFI_TABLE_HEADER Header;
+ EFI_LBA MyLBA;
+ EFI_LBA AlternateLBA;
+ EFI_LBA FirstUsableLBA;
+ EFI_LBA LastUsableLBA;
+ EFI_GUID DiskGUID;
+ EFI_LBA PartitionEntryLBA;
+ uint32_t NumberOfPartitionEntries;
+ uint32_t SizeOfPartitionEntry;
+ uint32_t PartitionEntryArrayCRC32;
+ uint8_t _pad[420];
+} _packed_ GptHeader;
+assert_cc(sizeof(GptHeader) == 512);
static EFI_DEVICE_PATH *path_replace_hd(
const EFI_DEVICE_PATH *path,
if (new_node)
new_node_len = DevicePathNodeLength(&new_node->Header);
- EFI_DEVICE_PATH *ret = xmalloc(len + new_node_len + END_DEVICE_PATH_LENGTH);
+ EFI_DEVICE_PATH *ret = xmalloc(len + new_node_len + sizeof(EFI_DEVICE_PATH));
EFI_DEVICE_PATH *end = mempcpy(ret, path, len);
if (new_node)
return ret;
}
-static bool verify_gpt(union GptHeaderBuffer *gpt_header_buffer, EFI_LBA lba_expected) {
- EFI_PARTITION_TABLE_HEADER *h;
+static bool verify_gpt(/*const*/ GptHeader *h, EFI_LBA lba_expected) {
uint32_t crc32, crc32_saved;
EFI_STATUS err;
- assert(gpt_header_buffer);
-
- h = &gpt_header_buffer->gpt_header;
+ assert(h);
/* Some superficial validation of the GPT header */
if (memcmp(&h->Header.Signature, "EFI PART", sizeof(h->Header.Signature)) != 0)
/* Calculate CRC check */
crc32_saved = h->Header.CRC32;
h->Header.CRC32 = 0;
- err = BS->CalculateCrc32(gpt_header_buffer, h->Header.HeaderSize, &crc32);
+ err = BS->CalculateCrc32(h, h->Header.HeaderSize, &crc32);
h->Header.CRC32 = crc32_saved;
if (err != EFI_SUCCESS || crc32 != crc32_saved)
return false;
HARDDRIVE_DEVICE_PATH *ret_hd) {
_cleanup_free_ EFI_PARTITION_ENTRY *entries = NULL;
- union GptHeaderBuffer gpt;
+ GptHeader gpt;
EFI_STATUS err;
uint32_t crc32;
size_t size;
/* Indicate the location of backup LBA even if the rest of the header is corrupt. */
if (ret_backup_lba)
- *ret_backup_lba = gpt.gpt_header.AlternateLBA;
+ *ret_backup_lba = gpt.AlternateLBA;
if (!verify_gpt(&gpt, lba))
return EFI_NOT_FOUND;
/* Now load the GPT entry table */
- size = ALIGN_TO((size_t) gpt.gpt_header.SizeOfPartitionEntry * (size_t) gpt.gpt_header.NumberOfPartitionEntries, 512);
+ size = ALIGN_TO((size_t) gpt.SizeOfPartitionEntry * (size_t) gpt.NumberOfPartitionEntries, 512);
entries = xmalloc(size);
err = block_io->ReadBlocks(
block_io,
block_io->Media->MediaId,
- gpt.gpt_header.PartitionEntryLBA,
+ gpt.PartitionEntryLBA,
size, entries);
if (err != EFI_SUCCESS)
return err;
/* Calculate CRC of entries array, too */
err = BS->CalculateCrc32(entries, size, &crc32);
- if (err != EFI_SUCCESS || crc32 != gpt.gpt_header.PartitionEntryArrayCRC32)
+ if (err != EFI_SUCCESS || crc32 != gpt.PartitionEntryArrayCRC32)
return EFI_CRC_ERROR;
/* Now we can finally look for xbootloader partitions. */
- for (size_t i = 0; i < gpt.gpt_header.NumberOfPartitionEntries; i++) {
+ for (size_t i = 0; i < gpt.NumberOfPartitionEntries; i++) {
EFI_PARTITION_ENTRY *entry =
- (EFI_PARTITION_ENTRY *) ((uint8_t *) entries + gpt.gpt_header.SizeOfPartitionEntry * i);
+ (EFI_PARTITION_ENTRY *) ((uint8_t *) entries + gpt.SizeOfPartitionEntry * i);
if (!efi_guid_equal(&entry->PartitionTypeGUID, type))
continue;
.Header = {
.Type = MEDIA_DEVICE_PATH,
.SubType = MEDIA_HARDDRIVE_DP,
+ .Length = sizeof(HARDDRIVE_DEVICE_PATH),
},
.PartitionNumber = i + 1,
.PartitionStart = entry->StartingLBA,
};
memcpy(ret_hd->Signature, &entry->UniquePartitionGUID, sizeof(ret_hd->Signature));
- /* HARDDRIVE_DEVICE_PATH has padding, which at least OVMF does not like. */
- SetDevicePathNodeLength(
- &ret_hd->Header,
- offsetof(HARDDRIVE_DEVICE_PATH, SignatureType) + sizeof(ret_hd->SignatureType));
-
return EFI_SUCCESS;
}
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
+#include "efi.h"
#define XBOOTLDR_GUID \
{ 0xbc13c2ff, 0x59e6, 0x4262, { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 } }
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
-#include "missing_efi.h"
#include "pe.h"
#include "util.h"
#define MAX_SECTIONS 96
#if defined(__i386__)
-# define TARGET_MACHINE_TYPE EFI_IMAGE_MACHINE_IA32
-# define TARGET_MACHINE_TYPE_COMPATIBILITY EFI_IMAGE_MACHINE_X64
+# define TARGET_MACHINE_TYPE 0x014CU
+# define TARGET_MACHINE_TYPE_COMPATIBILITY 0x8664U
#elif defined(__x86_64__)
-# define TARGET_MACHINE_TYPE EFI_IMAGE_MACHINE_X64
+# define TARGET_MACHINE_TYPE 0x8664U
#elif defined(__aarch64__)
-# define TARGET_MACHINE_TYPE EFI_IMAGE_MACHINE_AARCH64
+# define TARGET_MACHINE_TYPE 0xAA64U
#elif defined(__arm__)
-# define TARGET_MACHINE_TYPE EFI_IMAGE_MACHINE_ARMTHUMB_MIXED
+# define TARGET_MACHINE_TYPE 0x01C2U
#elif defined(__riscv) && __riscv_xlen == 64
-# define TARGET_MACHINE_TYPE EFI_IMAGE_MACHINE_RISCV64
+# define TARGET_MACHINE_TYPE 0x5064U
#else
# error Unknown EFI arch
#endif
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efidef.h>
-#include <uchar.h>
+#include "efi.h"
EFI_STATUS pe_memory_locate_sections(
const void *base,
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_BLOCK_IO_PROTOCOL_GUID \
+ GUID_DEF(0x0964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+typedef struct EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL;
+struct EFI_BLOCK_IO_PROTOCOL {
+ uint64_t Revision;
+ struct {
+ uint32_t MediaId;
+ bool RemovableMedia;
+ bool MediaPresent;
+ bool LogicalPartition;
+ bool ReadOnly;
+ bool WriteCaching;
+ uint32_t BlockSize;
+ uint32_t IoAlign;
+ EFI_LBA LastBlock;
+ EFI_LBA LowestAlignedLba;
+ uint32_t LogicalBlocksPerPhysicalBlock;
+ uint32_t OptimalTransferLengthGranularity;
+ } *Media;
+
+ EFI_STATUS (EFIAPI *Reset)(
+ EFI_BLOCK_IO_PROTOCOL *This,
+ bool ExtendedVerification);
+ EFI_STATUS (EFIAPI *ReadBlocks)(
+ EFI_BLOCK_IO_PROTOCOL *This,
+ uint32_t MediaId,
+ EFI_LBA LBA,
+ size_t BufferSize,
+ void *Buffer);
+ EFI_STATUS (EFIAPI *WriteBlocks)(
+ EFI_BLOCK_IO_PROTOCOL *This,
+ uint32_t MediaId,
+ EFI_LBA LBA,
+ size_t BufferSize,
+ void *Buffer);
+ EFI_STATUS (EFIAPI *FlushBlocks)(EFI_BLOCK_IO_PROTOCOL *This);
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
+ GUID_DEF(0xf42f7782, 0x12e, 0x4c12, 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21)
+
+typedef enum {
+ EfiConsoleControlScreenText,
+ EfiConsoleControlScreenGraphics,
+ EfiConsoleControlScreenMaxValue,
+} EFI_CONSOLE_CONTROL_SCREEN_MODE;
+
+typedef struct EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL;
+struct EFI_CONSOLE_CONTROL_PROTOCOL {
+ EFI_STATUS (EFIAPI *GetMode)(
+ EFI_CONSOLE_CONTROL_PROTOCOL *This,
+ EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
+ bool *UgaExists,
+ bool *StdInLocked);
+ EFI_STATUS (EFIAPI *SetMode)(
+ EFI_CONSOLE_CONTROL_PROTOCOL *This,
+ EFI_CONSOLE_CONTROL_SCREEN_MODE Mode);
+ EFI_STATUS(EFIAPI *LockStdIn)(
+ EFI_CONSOLE_CONTROL_PROTOCOL *This,
+ char16_t *Password);
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+ GUID_DEF(0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \
+ GUID_DEF(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c)
+#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \
+ GUID_DEF(0x05c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e)
+
+/* Device path types. */
+enum {
+ HARDWARE_DEVICE_PATH = 0x01,
+ ACPI_DEVICE_PATH = 0x02,
+ MESSAGING_DEVICE_PATH = 0x03,
+ MEDIA_DEVICE_PATH = 0x04,
+ BBS_DEVICE_PATH = 0x05,
+ END_DEVICE_PATH_TYPE = 0x7f,
+};
+
+/* Device path sub-types. */
+enum {
+ END_INSTANCE_DEVICE_PATH_SUBTYPE = 0x01,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE = 0xff,
+
+ MEDIA_HARDDRIVE_DP = 0x01,
+ MEDIA_VENDOR_DP = 0x03,
+ MEDIA_FILEPATH_DP = 0x04,
+ MEDIA_PIWG_FW_FILE_DP = 0x06,
+ MEDIA_PIWG_FW_VOL_DP = 0x07,
+};
+
+struct _packed_ EFI_DEVICE_PATH_PROTOCOL {
+ uint8_t Type;
+ uint8_t SubType;
+ uint16_t Length;
+};
+
+typedef struct {
+ EFI_DEVICE_PATH Header;
+ EFI_GUID Guid;
+} _packed_ VENDOR_DEVICE_PATH;
+
+#define MBR_TYPE_PCAT 0x01U
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02U
+#define NO_DISK_SIGNATURE 0x00U
+#define SIGNATURE_TYPE_MBR 0x01U
+#define SIGNATURE_TYPE_GUID 0x02U
+
+typedef struct {
+ EFI_DEVICE_PATH Header;
+ uint32_t PartitionNumber;
+ uint64_t PartitionStart;
+ uint64_t PartitionSize;
+ uint8_t Signature[16];
+ uint8_t MBRType;
+ uint8_t SignatureType;
+} _packed_ HARDDRIVE_DEVICE_PATH;
+
+typedef struct {
+ EFI_DEVICE_PATH Header;
+ char16_t PathName[];
+} _packed_ FILEPATH_DEVICE_PATH;
+
+typedef struct {
+ char16_t* (EFIAPI *ConvertDeviceNodeToText)(
+ const EFI_DEVICE_PATH *DeviceNode,
+ bool DisplayOnly,
+ bool AllowShortcuts);
+ char16_t* (EFIAPI *ConvertDevicePathToText)(
+ const EFI_DEVICE_PATH *DevicePath,
+ bool DisplayOnly,
+ bool AllowShortcuts);
+} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL;
+
+typedef struct {
+ EFI_DEVICE_PATH* (EFIAPI *ConvertTextToDevicNode)(
+ const char16_t *TextDeviceNode);
+ EFI_DEVICE_PATH* (EFIAPI *ConvertTextToDevicPath)(
+ const char16_t *ConvertTextToDevicPath);
+} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL;
+
+#define DevicePathType(dp) ((dp)->Type)
+#define DevicePathSubType(dp) ((dp)->SubType)
+#define DevicePathNodeLength(dp) ((dp)->Length)
+
+static inline EFI_DEVICE_PATH *NextDevicePathNode(const EFI_DEVICE_PATH *dp) {
+ assert(dp);
+ return (EFI_DEVICE_PATH *) ((uint8_t *) dp + dp->Length);
+}
+
+static inline bool IsDevicePathEnd(const EFI_DEVICE_PATH *dp) {
+ assert(dp);
+ return dp->Type == END_DEVICE_PATH_TYPE && dp->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE;
+}
+
+static inline void SetDevicePathEndNode(EFI_DEVICE_PATH *dp) {
+ assert(dp);
+ dp->Type = END_DEVICE_PATH_TYPE;
+ dp->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ dp->Length = sizeof(EFI_DEVICE_PATH);
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_DTB_TABLE_GUID \
+ GUID_DEF(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
+#define EFI_DT_FIXUP_PROTOCOL_GUID \
+ GUID_DEF(0xe617d64c, 0xfe08, 0x46da, 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00)
+
+#define EFI_DT_FIXUP_PROTOCOL_REVISION 0x00010000
+
+/* Add nodes and update properties */
+#define EFI_DT_APPLY_FIXUPS 0x00000001
+
+/*
+ * Reserve memory according to the /reserved-memory node
+ * and the memory reservation block
+ */
+#define EFI_DT_RESERVE_MEMORY 0x00000002
+
+typedef struct EFI_DT_FIXUP_PROTOCOL EFI_DT_FIXUP_PROTOCOL;
+struct EFI_DT_FIXUP_PROTOCOL {
+ uint64_t Revision;
+ EFI_STATUS (EFIAPI *Fixup)(
+ EFI_DT_FIXUP_PROTOCOL *This,
+ void *Fdt,
+ size_t *BufferSize,
+ uint32_t Flags);
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+ GUID_DEF(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_FILE_INFO_ID \
+ GUID_DEF(0x009576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_FILE_MODE_READ 0x0000000000000001U
+#define EFI_FILE_MODE_WRITE 0x0000000000000002U
+#define EFI_FILE_MODE_CREATE 0x8000000000000000U
+
+#define EFI_FILE_READ_ONLY 0x01U
+#define EFI_FILE_HIDDEN 0x02U
+#define EFI_FILE_SYSTEM 0x04U
+#define EFI_FILE_RESERVED 0x08U
+#define EFI_FILE_DIRECTORY 0x10U
+#define EFI_FILE_ARCHIVE 0x20U
+#define EFI_FILE_VALID_ATTR 0x37U
+
+typedef struct {
+ uint64_t Size;
+ uint64_t FileSize;
+ uint64_t PhysicalSize;
+ EFI_TIME CreateTime;
+ EFI_TIME LastAccessTime;
+ EFI_TIME ModificationTime;
+ uint64_t Attribute;
+ char16_t FileName[];
+} EFI_FILE_INFO;
+
+typedef struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
+struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
+ uint64_t Revision;
+ EFI_STATUS (EFIAPI *OpenVolume)(
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ EFI_FILE **Root);
+};
+
+struct EFI_FILE_PROTOCOL {
+ uint64_t Revision;
+ EFI_STATUS (EFIAPI *Open)(
+ EFI_FILE *This,
+ EFI_FILE **NewHandle,
+ char16_t *FileName,
+ uint64_t OpenMode,
+ uint64_t Attributes);
+ EFI_STATUS (EFIAPI *Close)(EFI_FILE *This);
+ EFI_STATUS (EFIAPI *Delete)(EFI_FILE *This);
+ EFI_STATUS (EFIAPI *Read)(
+ EFI_FILE *This,
+ size_t *BufferSize,
+ void *Buffer);
+ EFI_STATUS (EFIAPI *Write)(
+ EFI_FILE *This,
+ size_t *BufferSize,
+ void *Buffer);
+ EFI_STATUS (EFIAPI *GetPosition)(EFI_FILE *This, uint64_t *Position);
+ EFI_STATUS (EFIAPI *SetPosition)(EFI_FILE *This, uint64_t Position);
+ EFI_STATUS (EFIAPI *GetInfo)(
+ EFI_FILE *This,
+ EFI_GUID *InformationType,
+ size_t *BufferSize,
+ void *Buffer);
+ EFI_STATUS (EFIAPI *SetInfo)(
+ EFI_FILE *This,
+ EFI_GUID *InformationType,
+ size_t BufferSize,
+ void *Buffer);
+ EFI_STATUS (EFIAPI *Flush)(EFI_FILE *This);
+ void *OpenEx;
+ void *ReadEx;
+ void *WriteEx;
+ void *FlushEx;
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
+ GUID_DEF(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a)
+
+typedef enum {
+ PixelRedGreenBlueReserved8BitPerColor,
+ PixelBlueGreenRedReserved8BitPerColor,
+ PixelBitMask,
+ PixelBltOnly,
+ PixelFormatMax,
+} EFI_GRAPHICS_PIXEL_FORMAT;
+
+typedef enum {
+ EfiBltVideoFill,
+ EfiBltVideoToBltBuffer,
+ EfiBltBufferToVideo,
+ EfiBltVideoToVideo,
+ EfiGraphicsOutputBltOperationMax,
+} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;
+
+typedef struct {
+ uint32_t RedMask;
+ uint32_t GreenMask;
+ uint32_t BlueMask;
+ uint32_t ReservedMask;
+} EFI_PIXEL_BITMASK;
+
+typedef struct {
+ uint8_t Blue;
+ uint8_t Green;
+ uint8_t Red;
+ uint8_t Reserved;
+} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;
+
+typedef struct {
+ uint32_t Version;
+ uint32_t HorizontalResolution;
+ uint32_t VerticalResolution;
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
+ EFI_PIXEL_BITMASK PixelInformation;
+ uint32_t PixelsPerScanLine;
+} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
+
+typedef struct EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL;
+struct EFI_GRAPHICS_OUTPUT_PROTOCOL {
+ EFI_STATUS (EFIAPI *QueryMode)(
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ uint32_t ModeNumber,
+ size_t *SizeOfInfo,
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info);
+ EFI_STATUS(EFIAPI *SetMode)(
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ uint32_t ModeNumber);
+ EFI_STATUS (EFIAPI *Blt)(
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ size_t SourceX,
+ size_t SourceY,
+ size_t DestinationX,
+ size_t DestinationY,
+ size_t Width,
+ size_t Height,
+ size_t Delta);
+
+ struct {
+ uint32_t MaxMode;
+ uint32_t Mode;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ size_t SizeOfInfo;
+ EFI_PHYSICAL_ADDRESS FrameBufferBase;
+ size_t FrameBufferSize;
+ } *Mode;
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_LOAD_FILE_PROTOCOL_GUID \
+ GUID_DEF(0x56EC3091, 0x954C, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_LOAD_FILE2_PROTOCOL_GUID \
+ GUID_DEF(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
+
+typedef struct EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL;
+typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE2_PROTOCOL;
+
+struct EFI_LOAD_FILE_PROTOCOL {
+ EFI_STATUS (EFIAPI *LoadFile)(
+ EFI_LOAD_FILE_PROTOCOL *This,
+ EFI_DEVICE_PATH *FilePath,
+ bool BootPolicy,
+ size_t *BufferSize,
+ void *Buffer);
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
+ GUID_DEF(0x5B1B31A1, 0x9562, 0x11d2, 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B)
+#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \
+ GUID_DEF(0xbc62157e, 0x3e33, 0x4fec, 0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf)
+
+typedef EFI_STATUS (EFIAPI *EFI_IMAGE_ENTRY_POINT)(
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable);
+
+typedef struct {
+ uint32_t Revision;
+ EFI_HANDLE ParentHandle;
+ EFI_SYSTEM_TABLE *SystemTable;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH *FilePath;
+ void *Reserved;
+ uint32_t LoadOptionsSize;
+ void *LoadOptions;
+ void *ImageBase;
+ uint64_t ImageSize;
+ EFI_MEMORY_TYPE ImageCodeType;
+ EFI_MEMORY_TYPE ImageDataType;
+ EFI_STATUS (EFIAPI *Unload)(EFI_HANDLE ImageHandle);
+} EFI_LOADED_IMAGE_PROTOCOL;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_RNG_PROTOCOL_GUID \
+ GUID_DEF(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+
+typedef struct EFI_RNG_PROTOCOL EFI_RNG_PROTOCOL;
+struct EFI_RNG_PROTOCOL {
+ EFI_STATUS (EFIAPI *GetInfo)(
+ EFI_RNG_PROTOCOL *This,
+ size_t *RNGAlgorithmListSize,
+ EFI_GUID *RNGAlgorithmList);
+ EFI_STATUS (EFIAPI *GetRNG)(
+ EFI_RNG_PROTOCOL *This,
+ EFI_GUID *RNGAlgorithm,
+ size_t RNGValueLength,
+ uint8_t *RNGValue);
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_SECURITY_ARCH_PROTOCOL_GUID \
+ GUID_DEF(0xA46423E3, 0x4617, 0x49f1, 0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39)
+#define EFI_SECURITY2_ARCH_PROTOCOL_GUID \
+ GUID_DEF(0x94ab2f58, 0x1438, 0x4ef1, 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68)
+
+typedef struct EFI_SECURITY_ARCH_PROTOCOL EFI_SECURITY_ARCH_PROTOCOL;
+typedef struct EFI_SECURITY2_ARCH_PROTOCOL EFI_SECURITY2_ARCH_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE)(
+ const EFI_SECURITY_ARCH_PROTOCOL *This,
+ uint32_t AuthenticationStatus,
+ const EFI_DEVICE_PATH *File);
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION)(
+ const EFI_SECURITY2_ARCH_PROTOCOL *This,
+ const EFI_DEVICE_PATH *DevicePath,
+ void *FileBuffer,
+ size_t FileSize,
+ bool BootPolicy);
+
+struct EFI_SECURITY_ARCH_PROTOCOL {
+ EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
+};
+
+struct EFI_SECURITY2_ARCH_PROTOCOL {
+ EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \
+ GUID_DEF(0x752f3136, 0x4e16, 0x4fdc, 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca)
+
+typedef struct {
+ char16_t **Argv;
+ size_t Argc;
+ void *StdIn;
+ void *StdOut;
+ void *StdErr;
+} EFI_SHELL_PARAMETERS_PROTOCOL;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \
+ GUID_DEF(0x387477c1, 0x69c7, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
+ GUID_DEF(0xdd9e7534, 0x7762, 0x4698, 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa)
+#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \
+ GUID_DEF(0x387477c2, 0x69c7, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_SHIFT_STATE_VALID 0x80000000U
+#define EFI_RIGHT_SHIFT_PRESSED 0x00000001U
+#define EFI_LEFT_SHIFT_PRESSED 0x00000002U
+#define EFI_RIGHT_CONTROL_PRESSED 0x00000004U
+#define EFI_LEFT_CONTROL_PRESSED 0x00000008U
+#define EFI_RIGHT_ALT_PRESSED 0x00000010U
+#define EFI_LEFT_ALT_PRESSED 0x00000020U
+#define EFI_RIGHT_LOGO_PRESSED 0x00000040U
+#define EFI_LEFT_LOGO_PRESSED 0x00000080U
+#define EFI_MENU_KEY_PRESSED 0x00000100U
+#define EFI_SYS_REQ_PRESSED 0x00000200U
+
+#define EFI_TOGGLE_STATE_VALID 0x80U
+#define EFI_KEY_STATE_EXPOSED 0x40U
+#define EFI_SCROLL_LOCK_ACTIVE 0x01U
+#define EFI_NUM_LOCK_ACTIVE 0x02U
+#define EFI_CAPS_LOCK_ACTIVE 0x04U
+
+enum {
+ EFI_BLACK = 0x00,
+ EFI_BLUE = 0x01,
+ EFI_GREEN = 0x02,
+ EFI_CYAN = EFI_BLUE | EFI_GREEN,
+ EFI_RED = 0x04,
+ EFI_MAGENTA = EFI_BLUE | EFI_RED,
+ EFI_BROWN = EFI_GREEN | EFI_RED,
+ EFI_LIGHTGRAY = EFI_BLUE | EFI_GREEN | EFI_RED,
+ EFI_BRIGHT = 0x08,
+ EFI_DARKGRAY = EFI_BLACK | EFI_BRIGHT,
+ EFI_LIGHTBLUE = EFI_BLUE | EFI_BRIGHT,
+ EFI_LIGHTGREEN = EFI_GREEN | EFI_BRIGHT,
+ EFI_LIGHTCYAN = EFI_CYAN | EFI_BRIGHT,
+ EFI_LIGHTRED = EFI_RED | EFI_BRIGHT,
+ EFI_LIGHTMAGENTA = EFI_MAGENTA | EFI_BRIGHT,
+ EFI_YELLOW = EFI_BROWN | EFI_BRIGHT,
+ EFI_WHITE = EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT,
+};
+
+#define EFI_TEXT_ATTR(fg, bg) ((fg) | ((bg) << 4))
+#define EFI_TEXT_ATTR_SWAP(c) EFI_TEXT_ATTR(((c) & 0xF0U) >> 4, (c) & 0xFU)
+
+enum {
+ SCAN_NULL = 0x000,
+ SCAN_UP = 0x001,
+ SCAN_DOWN = 0x002,
+ SCAN_RIGHT = 0x003,
+ SCAN_LEFT = 0x004,
+ SCAN_HOME = 0x005,
+ SCAN_END = 0x006,
+ SCAN_INSERT = 0x007,
+ SCAN_DELETE = 0x008,
+ SCAN_PAGE_UP = 0x009,
+ SCAN_PAGE_DOWN = 0x00A,
+ SCAN_F1 = 0x00B,
+ SCAN_F2 = 0x00C,
+ SCAN_F3 = 0x00D,
+ SCAN_F4 = 0x00E,
+ SCAN_F5 = 0x00F,
+ SCAN_F6 = 0x010,
+ SCAN_F7 = 0x011,
+ SCAN_F8 = 0x012,
+ SCAN_F9 = 0x013,
+ SCAN_F10 = 0x014,
+ SCAN_F11 = 0x015,
+ SCAN_F12 = 0x016,
+ SCAN_ESC = 0x017,
+ SCAN_PAUSE = 0x048,
+ SCAN_F13 = 0x068,
+ SCAN_F14 = 0x069,
+ SCAN_F15 = 0x06A,
+ SCAN_F16 = 0x06B,
+ SCAN_F17 = 0x06C,
+ SCAN_F18 = 0x06D,
+ SCAN_F19 = 0x06E,
+ SCAN_F20 = 0x06F,
+ SCAN_F21 = 0x070,
+ SCAN_F22 = 0x071,
+ SCAN_F23 = 0x072,
+ SCAN_F24 = 0x073,
+ SCAN_MUTE = 0x07F,
+ SCAN_VOLUME_UP = 0x080,
+ SCAN_VOLUME_DOWN = 0x081,
+ SCAN_BRIGHTNESS_UP = 0x100,
+ SCAN_BRIGHTNESS_DOWN = 0x101,
+ SCAN_SUSPEND = 0x102,
+ SCAN_HIBERNATE = 0x103,
+ SCAN_TOGGLE_DISPLAY = 0x104,
+ SCAN_RECOVERY = 0x105,
+ SCAN_EJECT = 0x106,
+};
+
+typedef struct {
+ uint16_t ScanCode;
+ char16_t UnicodeChar;
+} EFI_INPUT_KEY;
+
+typedef struct {
+ uint32_t KeyShiftState;
+ uint8_t KeyToggleState;
+} EFI_KEY_STATE;
+
+typedef struct {
+ EFI_INPUT_KEY Key;
+ EFI_KEY_STATE KeyState;
+} EFI_KEY_DATA;
+
+struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
+ EFI_STATUS (EFIAPI *Reset)(
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ bool ExtendedVerification);
+ EFI_STATUS (EFIAPI *ReadKeyStroke)(
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ EFI_INPUT_KEY *Key);
+ EFI_EVENT WaitForKey;
+};
+
+typedef struct EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
+struct EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
+ EFI_STATUS (EFIAPI *Reset)(
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ bool ExtendedVerification);
+ EFI_STATUS (EFIAPI *ReadKeyStrokeEx)(
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ EFI_KEY_DATA *KeyData);
+ EFI_EVENT WaitForKeyEx;
+ void *SetState;
+ void *RegisterKeyNotify;
+ void *UnregisterKeyNotify;
+};
+
+typedef struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
+ EFI_STATUS (EFIAPI *Reset)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ bool ExtendedVerification);
+ EFI_STATUS (EFIAPI *OutputString)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ char16_t *String);
+ EFI_STATUS (EFIAPI *TestString)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ char16_t *String);
+ EFI_STATUS (EFIAPI *QueryMode)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ size_t ModeNumber,
+ size_t *Columns,
+ size_t *Rows);
+ EFI_STATUS (EFIAPI *SetMode)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ size_t ModeNumber);
+ EFI_STATUS (EFIAPI *SetAttribute)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ size_t Attribute);
+ EFI_STATUS (EFIAPI *ClearScreen)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This);
+ EFI_STATUS (EFIAPI *SetCursorPosition)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ size_t Column,
+ size_t Row);
+ EFI_STATUS (EFIAPI *EnableCursor)(
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ bool Visible);
+ struct {
+ int32_t MaxMode;
+ int32_t Mode;
+ int32_t Attribute;
+ int32_t CursorColumn;
+ int32_t CursorRow;
+ bool CursorVisible;
+ } *Mode;
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+#define EFI_TCG_PROTOCOL_GUID \
+ GUID_DEF(0xf541796d, 0xa62e, 0x4954, 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd)
+#define EFI_TCG2_PROTOCOL_GUID \
+ GUID_DEF(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
+
+#define TCG_ALG_SHA 0x4
+#define EFI_TCG2_EVENT_HEADER_VERSION 1
+#define EV_IPL 13
+
+typedef struct {
+ uint8_t Major;
+ uint8_t Minor;
+ uint8_t RevMajor;
+ uint8_t RevMinor;
+} TCG_VERSION;
+
+typedef struct {
+ uint8_t Major;
+ uint8_t Minor;
+} EFI_TCG2_VERSION;
+
+typedef struct {
+ uint8_t Size;
+ TCG_VERSION StructureVersion;
+ TCG_VERSION ProtocolSpecVersion;
+ uint8_t HashAlgorithmBitmap;
+ bool TPMPresentFlag;
+ bool TPMDeactivatedFlag;
+} EFI_TCG_BOOT_SERVICE_CAPABILITY;
+
+typedef struct {
+ uint8_t Size;
+ EFI_TCG2_VERSION StructureVersion;
+ EFI_TCG2_VERSION ProtocolVersion;
+ uint32_t HashAlgorithmBitmap;
+ uint32_t SupportedEventLogs;
+ bool TPMPresentFlag;
+ uint16_t MaxCommandSize;
+ uint16_t MaxResponseSize;
+ uint32_t ManufacturerID;
+ uint32_t NumberOfPCRBanks;
+ uint32_t ActivePcrBanks;
+} EFI_TCG2_BOOT_SERVICE_CAPABILITY;
+
+typedef struct {
+ uint32_t PCRIndex;
+ uint32_t EventType;
+ struct {
+ uint8_t Digest[20];
+ } Digest;
+ uint32_t EventSize;
+ uint8_t Event[0];
+} _packed_ TCG_PCR_EVENT;
+
+typedef struct {
+ uint32_t HeaderSize;
+ uint16_t HeaderVersion;
+ uint32_t PCRIndex;
+ uint32_t EventType;
+} _packed_ EFI_TCG2_EVENT_HEADER;
+
+typedef struct {
+ uint32_t Size;
+ EFI_TCG2_EVENT_HEADER Header;
+ uint8_t Event[];
+} _packed_ EFI_TCG2_EVENT;
+
+typedef struct EFI_TCG_PROTOCOL EFI_TCG_PROTOCOL;
+struct EFI_TCG_PROTOCOL {
+ EFI_STATUS (EFIAPI *StatusCheck)(
+ EFI_TCG_PROTOCOL *This,
+ EFI_TCG_BOOT_SERVICE_CAPABILITY *ProtocolCapability,
+ uint32_t *TCGFeatureFlags,
+ EFI_PHYSICAL_ADDRESS *EventLogLocation,
+ EFI_PHYSICAL_ADDRESS *EventLogLastEntry);
+ void *HashAll;
+ void *LogEvent;
+ void *PassThroughToTpm;
+ EFI_STATUS (EFIAPI *HashLogExtendEvent)(
+ EFI_TCG_PROTOCOL *This,
+ EFI_PHYSICAL_ADDRESS HashData,
+ uint64_t HashDataLen,
+ uint32_t AlgorithmId,
+ TCG_PCR_EVENT *TCGLogData,
+ uint32_t *EventNumber,
+ EFI_PHYSICAL_ADDRESS *EventLogLastEntry);
+};
+
+typedef struct EFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
+struct EFI_TCG2_PROTOCOL {
+ EFI_STATUS (EFIAPI *GetCapability)(
+ EFI_TCG2_PROTOCOL *This,
+ EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability);
+ void *GetEventLog;
+ EFI_STATUS (EFIAPI *HashLogExtendEvent)(
+ EFI_TCG2_PROTOCOL *This,
+ uint64_t Flags,
+ EFI_PHYSICAL_ADDRESS DataToHash,
+ uint64_t DataToHashLen,
+ EFI_TCG2_EVENT *EfiTcgEvent);
+ void *SubmitCommand;
+ void *GetActivePcrBanks;
+ void *SetActivePcrBanks;
+ void *GetResultOfSetActivePcrBanks;
+};
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "memory-util-fundamental.h"
-#include "missing_efi.h"
+#include "proto/rng.h"
#include "random-seed.h"
#include "secure-boot.h"
#include "sha256.h"
return err;
}
- err = get_file_info_harder(handle, &info, NULL);
+ err = get_file_info(handle, &info, NULL);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to get file info for random seed: %m");
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
+#include "efi.h"
EFI_STATUS process_random_seed(EFI_FILE *root_dir);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "console.h"
+#include "proto/security-arch.h"
#include "sbat.h"
#include "secure-boot.h"
#include "util.h"
char *buffer;
size_t size;
} sb_vars[] = {
- { u"db", u"db.auth", EFI_IMAGE_SECURITY_DATABASE_VARIABLE, NULL, 0 },
+ { u"db", u"db.auth", EFI_IMAGE_SECURITY_DATABASE_GUID, NULL, 0 },
{ u"KEK", u"KEK.auth", EFI_GLOBAL_VARIABLE, NULL, 0 },
{ u"PK", u"PK.auth", EFI_GLOBAL_VARIABLE, NULL, 0 },
};
const EFI_DEVICE_PATH *device_path,
void *file_buffer,
size_t file_size,
- BOOLEAN boot_policy) {
+ bool boot_policy) {
assert(security_override.validator);
assert(security_override.security2);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-
+#include "efi.h"
#include "efivars-fundamental.h"
-#include "missing_efi.h"
typedef enum {
ENROLL_OFF, /* no Secure Boot key enrollment whatsoever, even manual entries are not generated */
* https://github.com/mjg59/efitools
*/
-#include <efi.h>
-#include <efilib.h>
-
-#include "missing_efi.h"
-#include "util.h"
#include "secure-boot.h"
#include "shim.h"
+#include "util.h"
#if defined(__x86_64__) || defined(__i386__)
#define __sysv_abi__ __attribute__((sysv_abi))
*/
#pragma once
-#include <efi.h>
-#include <stdbool.h>
+#include "efi.h"
bool shim_loaded(void);
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "graphics.h"
+#include "proto/graphics-output.h"
#include "splash.h"
+#include "unaligned-fundamental.h"
#include "util.h"
struct bmp_file {
int32_t y_pixel_meter;
uint32_t colors_used;
uint32_t colors_important;
+ uint32_t channel_mask_r;
+ uint32_t channel_mask_g;
+ uint32_t channel_mask_b;
+ uint32_t channel_mask_a;
} _packed_;
+#define SIZEOF_BMP_DIB offsetof(struct bmp_dib, channel_mask_r)
+#define SIZEOF_BMP_DIB_RGB offsetof(struct bmp_dib, channel_mask_a)
+#define SIZEOF_BMP_DIB_RGBA sizeof(struct bmp_dib)
+
struct bmp_map {
uint8_t blue;
uint8_t green;
assert(ret_map);
assert(pixmap);
- if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
+ if (size < sizeof(struct bmp_file) + SIZEOF_BMP_DIB)
return EFI_INVALID_PARAMETER;
/* check file header */
/* check device-independent bitmap */
struct bmp_dib *dib = (struct bmp_dib *) (bmp + sizeof(struct bmp_file));
- if (dib->size < sizeof(struct bmp_dib))
+ if (dib->size < SIZEOF_BMP_DIB)
return EFI_UNSUPPORTED;
switch (dib->depth) {
assert(dib);
- if (IN_SET(dib->depth, 16, 32) && dib->size >= sizeof(*dib) + 3 * sizeof(uint32_t)) {
- uint32_t *mask = (uint32_t *) ((uint8_t *) dib + sizeof(*dib));
- channel_mask[R] = mask[R];
- channel_mask[G] = mask[G];
- channel_mask[B] = mask[B];
- channel_shift[R] = __builtin_ctz(mask[R]);
- channel_shift[G] = __builtin_ctz(mask[G]);
- channel_shift[B] = __builtin_ctz(mask[B]);
- channel_scale[R] = 0xff / ((1 << __builtin_popcount(mask[R])) - 1);
- channel_scale[G] = 0xff / ((1 << __builtin_popcount(mask[G])) - 1);
- channel_scale[B] = 0xff / ((1 << __builtin_popcount(mask[B])) - 1);
-
- if (dib->size >= sizeof(*dib) + 4 * sizeof(uint32_t) && mask[A] != 0) {
- channel_mask[A] = mask[A];
- channel_shift[A] = __builtin_ctz(mask[A]);
- channel_scale[A] = 0xff / ((1 << __builtin_popcount(mask[A])) - 1);
+ if (IN_SET(dib->depth, 16, 32) && dib->size >= SIZEOF_BMP_DIB_RGB) {
+ channel_mask[R] = dib->channel_mask_r;
+ channel_mask[G] = dib->channel_mask_g;
+ channel_mask[B] = dib->channel_mask_b;
+ channel_shift[R] = __builtin_ctz(dib->channel_mask_r);
+ channel_shift[G] = __builtin_ctz(dib->channel_mask_g);
+ channel_shift[B] = __builtin_ctz(dib->channel_mask_b);
+ channel_scale[R] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_r)) - 1);
+ channel_scale[G] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_g)) - 1);
+ channel_scale[B] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_b)) - 1);
+
+ if (dib->size >= SIZEOF_BMP_DIB_RGBA && dib->channel_mask_a != 0) {
+ channel_mask[A] = dib->channel_mask_a;
+ channel_shift[A] = __builtin_ctz(dib->channel_mask_a);
+ channel_scale[A] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_a)) - 1);
} else {
channel_mask[A] = 0;
channel_shift[A] = 0;
case 16:
case 32: {
- uint32_t i = dib->depth == 16 ? *(uint16_t *) in : *(uint32_t *) in;
+ uint32_t i = dib->depth == 16 ? unaligned_read_ne16(in) :
+ unaligned_read_ne32(in);
uint8_t r = ((i & channel_mask[R]) >> channel_shift[R]) * channel_scale[R],
g = ((i & channel_mask[G]) >> channel_shift[G]) * channel_scale[G],
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <stddef.h>
+#include "efi.h"
EFI_STATUS graphics_splash(const uint8_t *content, size_t len);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "cpio.h"
#include "devicetree.h"
#include "disk.h"
#include "measure.h"
#include "part-discovery.h"
#include "pe.h"
+#include "proto/shell-parameters.h"
#include "random-seed.h"
#include "secure-boot.h"
#include "splash.h"
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-
#include "ticks.h"
#include "util.h"
#include "vmm.h"
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-#include <inttypes.h>
-
+#include "proto/device-path.h"
+#include "proto/simple-text-io.h"
#include "ticks.h"
#include "util.h"
}
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const char16_t *name, char **ret, size_t *ret_size) {
- _cleanup_free_ char *buf = NULL;
- size_t l;
EFI_STATUS err;
assert(vendor);
assert(name);
- l = sizeof(char16_t *) * EFI_MAXIMUM_VARIABLE_SIZE;
- buf = xmalloc(l);
+ size_t size = 0;
+ err = RT->GetVariable((char16_t *) name, (EFI_GUID *) vendor, NULL, &size, NULL);
+ if (err != EFI_BUFFER_TOO_SMALL)
+ return err;
- err = RT->GetVariable((char16_t *) name, (EFI_GUID *) vendor, NULL, &l, buf);
+ _cleanup_free_ void *buf = xmalloc(size);
+ err = RT->GetVariable((char16_t *) name, (EFI_GUID *) vendor, NULL, &size, buf);
if (err != EFI_SUCCESS)
return err;
if (ret)
*ret = TAKE_PTR(buf);
if (ret_size)
- *ret_size = l;
+ *ret_size = size;
return EFI_SUCCESS;
}
if (size == 0) {
_cleanup_free_ EFI_FILE_INFO *info = NULL;
- err = get_file_info_harder(handle, &info, NULL);
+ err = get_file_info(handle, &info, NULL);
if (err != EFI_SUCCESS)
return err;
}
}
-EFI_STATUS get_file_info_harder(
- EFI_FILE *handle,
- EFI_FILE_INFO **ret,
- size_t *ret_size) {
-
+EFI_STATUS get_file_info(EFI_FILE *handle, EFI_FILE_INFO **ret, size_t *ret_size) {
size_t size = offsetof(EFI_FILE_INFO, FileName) + 256;
_cleanup_free_ EFI_FILE_INFO *fi = NULL;
EFI_STATUS err;
assert(handle);
assert(ret);
- /* A lot like LibFileInfo() but with useful error propagation */
-
fi = xmalloc(size);
err = handle->GetInfo(handle, MAKE_GUID_PTR(EFI_FILE_INFO), &size, fi);
if (err == EFI_BUFFER_TOO_SMALL) {
return EFI_SUCCESS;
}
-EFI_STATUS readdir_harder(
+EFI_STATUS readdir(
EFI_FILE *handle,
EFI_FILE_INFO **buffer,
size_t *buffer_size) {
* position when returning EFI_BUFFER_TOO_SMALL, effectively skipping over any files when
* the buffer was too small. Therefore, start with a buffer that should handle FAT32 max
* file name length.
- * As a side effect, most readdir_harder() calls will now be slightly faster. */
+ * As a side effect, most readdir() calls will now be slightly faster. */
sz = sizeof(EFI_FILE_INFO) + 256 * sizeof(char16_t);
*buffer = xmalloc(sz);
*buffer_size = sz;
if (err != EFI_SUCCESS)
return err;
- err = get_file_info_harder(dir, &file_info, NULL);
+ err = get_file_info(dir, &file_info, NULL);
if (err != EFI_SUCCESS)
return err;
if (!FLAGS_SET(file_info->Attribute, EFI_FILE_DIRECTORY))
size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp;
/* Make a copy that can also hold a file media device path. */
- *ret_dp = xmalloc(dp_size + file_size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
+ *ret_dp = xmalloc(dp_size + file_size + sizeof(FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH));
dp = mempcpy(*ret_dp, dp, dp_size);
/* Replace end node with file media device path. Use memcpy() in case dp is unaligned (if accessed as
* FILEPATH_DEVICE_PATH). */
dp->Type = MEDIA_DEVICE_PATH;
dp->SubType = MEDIA_FILEPATH_DP;
- memcpy((uint8_t *) dp + offsetof(FILEPATH_DEVICE_PATH, PathName), file, file_size);
- SetDevicePathNodeLength(dp, offsetof(FILEPATH_DEVICE_PATH, PathName) + file_size);
+ dp->Length = sizeof(FILEPATH_DEVICE_PATH) + file_size;
+ memcpy((uint8_t *) dp + sizeof(FILEPATH_DEVICE_PATH), file, file_size);
dp = NextDevicePathNode(dp);
SetDevicePathEndNode(dp);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <efilib.h>
-#include <stddef.h>
-
+#include "efi.h"
#include "log.h"
+#include "proto/file-io.h"
#include "string-util-fundamental.h"
static inline void free(void *p) {
(void) BS->UnloadImage(*image);
}
-/* Creates a EFI_GUID pointer suitable for EFI APIs. Use of const allows the compiler to merge multiple
- * uses (although, currently compilers do that regardless). Most EFI APIs declare their EFI_GUID input
- * as non-const, but almost all of them are in fact const. */
-#define MAKE_GUID_PTR(name) ((EFI_GUID *) &(const EFI_GUID) name##_GUID)
-
-/* These allow MAKE_GUID_PTR() to work without requiring an extra _GUID in the passed name. We want to
- * keep the GUID definitions in line with the UEFI spec. */
-#define EFI_GLOBAL_VARIABLE_GUID EFI_GLOBAL_VARIABLE
-#define EFI_FILE_INFO_GUID EFI_FILE_INFO_ID
-
/*
* Allocated random UUID, intended to be shared across tools that implement
* the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
typedef int (*compare_pointer_func_t)(const void *a, const void *b);
void sort_pointer_array(void **array, size_t n_members, compare_pointer_func_t compare);
-EFI_STATUS get_file_info_harder(EFI_FILE *handle, EFI_FILE_INFO **ret, size_t *ret_size);
-
-EFI_STATUS readdir_harder(EFI_FILE *handle, EFI_FILE_INFO **buffer, size_t *buffer_size);
+EFI_STATUS get_file_info(EFI_FILE *handle, EFI_FILE_INFO **ret, size_t *ret_size);
+EFI_STATUS readdir(EFI_FILE *handle, EFI_FILE_INFO **buffer, size_t *buffer_size);
bool is_ascii(const char16_t *f);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <efi.h>
-#include <efilib.h>
-#include <stdbool.h>
#if defined(__i386__) || defined(__x86_64__)
# include <cpuid.h>
#endif
#include "drivers.h"
#include "efi-string.h"
+#include "proto/device-path.h"
#include "string-util-fundamental.h"
#include "util.h"
return false;
}
+#define SMBIOS_TABLE_GUID \
+ GUID_DEF(0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+#define SMBIOS3_TABLE_GUID \
+ GUID_DEF(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94)
+
typedef struct {
uint8_t anchor_string[4];
uint8_t entry_point_structure_checksum;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <efi.h>
-#include <efilib.h>
+#include "efi.h"
bool is_direct_boot(EFI_HANDLE device);
EFI_STATUS vmm_open(EFI_HANDLE *ret_qemu_dev, EFI_FILE **ret_qemu_dir);
}
/* If there are encrypted credentials we might need to access the TPM. */
- ExecLoadCredential *cred;
- HASHMAP_FOREACH(cred, ec->load_credentials)
- if (cred->encrypted) {
- r = cgroup_add_device_allow(cc, "/dev/tpmrm0", "rw");
- if (r < 0)
- return r;
+ bool allow_tpm = false;
+ ExecLoadCredential *load_cred;
+ ExecSetCredential *set_cred;
+ HASHMAP_FOREACH(load_cred, ec->load_credentials)
+ if ((allow_tpm |= load_cred->encrypted))
break;
- }
+ HASHMAP_FOREACH(set_cred, ec->set_credentials)
+ if ((allow_tpm |= set_cred->encrypted))
+ break;
+
+ if (allow_tpm) {
+ r = cgroup_add_device_allow(cc, "/dev/tpmrm0", "rw");
+ if (r < 0)
+ return r;
+ }
}
}
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include <errno.h>
+#ifdef SD_BOOT
+# define EINVAL 22
+#else
+# include <errno.h>
+#endif
#include "string-util-fundamental.h"
/* Features of the loader, i.e. systemd-boot */
#define ALIGN2_PTR(p) ((void*) ALIGN2((uintptr_t) p))
#define ALIGN4_PTR(p) ((void*) ALIGN4((uintptr_t) p))
#define ALIGN8_PTR(p) ((void*) ALIGN8((uintptr_t) p))
-#if !SD_BOOT
-/* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */
#define ALIGN(l) ALIGN_TO(l, sizeof(void*))
#define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p)))
-#endif
/* Checks if the specified pointer is aligned as appropriate for the specific type */
#define IS_ALIGNED16(p) (((uintptr_t) p) % __alignof__(uint16_t) == 0)
return (sd_char*) s + l;
}
-#if !SD_BOOT
sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
size_t l;
return (sd_char*) s + l;
}
-#endif
sd_char* endswith(const sd_char *s, const sd_char *postfix) {
size_t sl, pl;
#pragma once
#if SD_BOOT
-# include <efi.h>
-# include <efilib.h>
+# include "efi.h"
# include "efi-string.h"
#else
# include <string.h>
}
sd_char *startswith(const sd_char *s, const sd_char *prefix) _pure_;
-#if !SD_BOOT
sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) _pure_;
-#endif
sd_char *endswith(const sd_char *s, const sd_char *postfix) _pure_;
sd_char *endswith_no_case(const sd_char *s, const sd_char *postfix) _pure_;
}
static int add_mounts(void) {
- _cleanup_free_ char *p = NULL;
- int r;
dev_t devno;
+ int r;
- /* If the root mount has been replaced by some form of volatile file system (overlayfs), the
- * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
- * here. */
- r = readlink_malloc("/run/systemd/volatile-root", &p);
- if (r == -ENOENT) { /* volatile-root not found */
- r = get_block_device_harder("/", &devno);
- if (r == -EUCLEAN)
- return btrfs_log_dev_root(LOG_ERR, r, "root file system");
- if (r < 0)
- return log_error_errno(r, "Failed to determine block device of root file system: %m");
- if (r == 0) { /* Not backed by a single block device. (Could be NFS or so, or could be multi-device RAID or so) */
- r = get_block_device_harder("/usr", &devno);
- if (r == -EUCLEAN)
- return btrfs_log_dev_root(LOG_ERR, r, "/usr");
- if (r < 0)
- return log_error_errno(r, "Failed to determine block device of /usr/ file system: %m");
- if (r == 0) { /* /usr/ not backed by single block device, either. */
- log_debug("Neither root nor /usr/ file system are on a (single) block device.");
- return 0;
- }
- }
- } else if (r < 0)
- return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
- else {
- mode_t m;
- r = device_path_parse_major_minor(p, &m, &devno);
- if (r < 0)
- return log_error_errno(r, "Failed to parse major/minor device node: %m");
- if (!S_ISBLK(m))
- return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Volatile root device is of wrong type.");
+ r = blockdev_get_root(LOG_ERR, &devno);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ log_debug("Skipping automatic GPT dissection logic, root file system not backed by a (single) whole block device.");
+ return 0;
}
return enumerate_partitions(devno);
return -errno;
r = safe_fork_full("(sd-homework)",
- (int[]) { stdin_fd, stdout_fd }, 2,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &pid);
+ (int[]) { stdin_fd, stdout_fd, STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
if (r < 0)
log_warning_errno(r, "Failed to update $SYSTEMD_EXEC_PID, ignoring: %m");
- r = rearrange_stdio(TAKE_FD(stdin_fd), TAKE_FD(stdout_fd), STDERR_FILENO); /* fds are invalidated by rearrange_stdio() even on failure */
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout/stderr: %m");
- _exit(EXIT_FAILURE);
- }
-
-
/* Allow overriding the homework path via an environment variable, to make debugging
* easier. */
homework = getenv("SYSTEMD_HOMEWORK_PATH") ?: SYSTEMD_HOMEWORK_PATH;
use_selinux = mac_selinux_use();
- r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(tar)",
+ (int[]) { pipefd[0], -EBADF, STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
- pipefd[1] = safe_close(pipefd[1]);
-
- r = rearrange_stdio(TAKE_FD(pipefd[0]), -EBADF, STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
if (unshare(CLONE_NEWNET) < 0)
log_warning_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
use_selinux = mac_selinux_use();
- r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(tar)",
+ (int[]) { -EBADF, pipefd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
- pipefd[0] = safe_close(pipefd[0]);
-
- r = rearrange_stdio(-EBADF, TAKE_FD(pipefd[1]), STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
if (unshare(CLONE_NEWNET) < 0)
log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
if (pipe2(pipefd, O_CLOEXEC) < 0)
return -errno;
- r = safe_fork("(sd-transfer)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &t->pid);
+ r = safe_fork_full("(sd-transfer)",
+ (int[]) { t->stdin_fd, t->stdout_fd < 0 ? pipefd[1] : t->stdout_fd, pipefd[1] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO, &t->pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
- pipefd[0] = safe_close(pipefd[0]);
-
- r = rearrange_stdio(TAKE_FD(t->stdin_fd),
- t->stdout_fd < 0 ? pipefd[1] : TAKE_FD(t->stdout_fd),
- pipefd[1]);
- TAKE_FD(pipefd[1]);
- if (r < 0) {
- log_error_errno(r, "Failed to set stdin/stdout/stderr: %m");
- _exit(EXIT_FAILURE);
- }
-
if (setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1) < 0 ||
setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1) < 0) {
log_error_errno(errno, "setenv() failed: %m");
gpg_home_created = true;
- r = safe_fork("(gpg)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
+ r = safe_fork_full("(gpg)",
+ (int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ &pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
- gpg_pipe[1] = safe_close(gpg_pipe[1]);
-
- r = rearrange_stdio(TAKE_FD(gpg_pipe[0]), -EBADF, STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
cmd[k++] = strjoina("--homedir=", gpg_home);
/* We add the user keyring only to the command line arguments, if it's around since gpg fails
if (pipe(fd) < 0)
return log_error_errno(errno, "Failed to create pager pipe: %m");
- r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &child_pid);
+ r = safe_fork_full("(remote)",
+ (int[]) {STDIN_FILENO, fd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &child_pid);
if (r < 0) {
safe_close_pair(fd);
return r;
/* In the child */
if (r == 0) {
- fd[0] = safe_close(fd[0]);
-
- r = rearrange_stdio(STDIN_FILENO, TAKE_FD(fd[1]), STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to dup pipe to stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
execvp(child, argv);
log_error_errno(errno, "Failed to exec child %s: %m", child);
_exit(EXIT_FAILURE);
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Journal file has been deleted, rotating.", f->path);
return true;
- case -ETXTBSY: /* Journal file is from the future */
- log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Journal file is from the future, rotating.", f->path);
- return true;
-
case -EREMCHG: /* Wallclock time (CLOCK_REALTIME) jumped backwards relative to last journal entry */
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Realtime clock jumped backwards relative to last journal entry, rotating.", f->path);
return true;
-EBUSY, /* Unclean shutdown */
-ESHUTDOWN, /* Already archived */
-EIO, /* IO error, including SIGBUS on mmap */
- -EIDRM, /* File has been deleted */
- -ETXTBSY)) /* File is from the future */
+ -EIDRM)) /* File has been deleted */
return r;
if ((open_flags & O_ACCMODE) == O_RDONLY)
assert_se(one->file->header->state == STATE_ONLINE);
assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->machine_id));
- assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->boot_id));
+ assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->tail_entry_boot_id));
assert_se(sd_id128_equal(one->file->header->file_id, one->file->header->seqnum_id));
memcpy(&seqnum_id, &one->file->header->seqnum_id, sizeof(sd_id128_t));
assert_se(two->file->header->state == STATE_ONLINE);
assert_se(!sd_id128_equal(two->file->header->file_id, one->file->header->file_id));
assert_se(sd_id128_equal(one->file->header->machine_id, one->file->header->machine_id));
- assert_se(sd_id128_equal(one->file->header->boot_id, one->file->header->boot_id));
+ assert_se(sd_id128_equal(one->file->header->tail_entry_boot_id, one->file->header->tail_entry_boot_id));
assert_se(sd_id128_equal(one->file->header->seqnum_id, one->file->header->seqnum_id));
append_number(two, 3, &seqnum);
if (r < 0)
return -errno;
- r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid);
+ r = safe_fork_full("(sd-busexec)",
+ (int[]) { s[1], s[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid);
if (r < 0) {
safe_close_pair(s);
return r;
if (r == 0) {
/* Child */
- r = rearrange_stdio(s[1], s[1], STDERR_FILENO);
- TAKE_FD(s[1]);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
if (b->exec_argv)
execvp(b->exec_path, b->exec_argv);
else
* n_entry_arrays. */
gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
- gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id));
+ gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id));
gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
HEADER_INCOMPATIBLE_KEYED_HASH = 1 << 2,
HEADER_INCOMPATIBLE_COMPRESSED_ZSTD = 1 << 3,
HEADER_INCOMPATIBLE_COMPACT = 1 << 4,
-};
-#define HEADER_INCOMPATIBLE_ANY \
- (HEADER_INCOMPATIBLE_COMPRESSED_XZ | \
- HEADER_INCOMPATIBLE_COMPRESSED_LZ4 | \
- HEADER_INCOMPATIBLE_KEYED_HASH | \
- HEADER_INCOMPATIBLE_COMPRESSED_ZSTD | \
- HEADER_INCOMPATIBLE_COMPACT)
+ HEADER_INCOMPATIBLE_ANY = HEADER_INCOMPATIBLE_COMPRESSED_XZ |
+ HEADER_INCOMPATIBLE_COMPRESSED_LZ4 |
+ HEADER_INCOMPATIBLE_KEYED_HASH |
+ HEADER_INCOMPATIBLE_COMPRESSED_ZSTD |
+ HEADER_INCOMPATIBLE_COMPACT,
+
+ HEADER_INCOMPATIBLE_SUPPORTED = (HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) |
+ (HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) |
+ (HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) |
+ HEADER_INCOMPATIBLE_KEYED_HASH |
+ HEADER_INCOMPATIBLE_COMPACT,
+};
-#define HEADER_INCOMPATIBLE_SUPPORTED \
- ((HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) | \
- (HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) | \
- (HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) | \
- HEADER_INCOMPATIBLE_KEYED_HASH | \
- HEADER_INCOMPATIBLE_COMPACT)
enum {
- HEADER_COMPATIBLE_SEALED = 1 << 0,
+ HEADER_COMPATIBLE_SEALED = 1 << 0,
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID = 1 << 1, /* if set, the last_entry_boot_id field in the header is exclusively refreshed when an entry is appended */
+ HEADER_COMPATIBLE_ANY = HEADER_COMPATIBLE_SEALED|
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
+
+ HEADER_COMPATIBLE_SUPPORTED = (HAVE_GCRYPT ? HEADER_COMPATIBLE_SEALED : 0) |
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
};
-#define HEADER_COMPATIBLE_ANY HEADER_COMPATIBLE_SEALED
-#if HAVE_GCRYPT
-# define HEADER_COMPATIBLE_SUPPORTED HEADER_COMPATIBLE_SEALED
-#else
-# define HEADER_COMPATIBLE_SUPPORTED 0
-#endif
#define HEADER_SIGNATURE \
((const uint8_t[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' })
uint8_t reserved[7]; \
sd_id128_t file_id; \
sd_id128_t machine_id; \
- sd_id128_t boot_id; /* last writer */ \
+ sd_id128_t tail_entry_boot_id; \
sd_id128_t seqnum_id; \
le64_t header_size; \
le64_t arena_size; \
FLAGS_SET(file_flags, JOURNAL_COMPRESS) * COMPRESSION_TO_HEADER_INCOMPATIBLE_FLAG(DEFAULT_COMPRESSION) |
keyed_hash_requested() * HEADER_INCOMPATIBLE_KEYED_HASH |
compact_mode_requested() * HEADER_INCOMPATIBLE_COMPACT),
- .compatible_flags = htole32(seal * HEADER_COMPATIBLE_SEALED),
+ .compatible_flags = htole32(
+ (seal * HEADER_COMPATIBLE_SEALED) |
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID),
};
assert_cc(sizeof(h.signature) == sizeof(HEADER_SIGNATURE));
if (r < 0)
return r;
+ r = sd_id128_get_machine(&h.machine_id);
+ if (r < 0 && !ERRNO_IS_MACHINE_ID_UNSET(r))
+ return r; /* If we have no valid machine ID (test environment?), let's simply leave the
+ * machine ID field all zeroes. */
+
if (template) {
h.seqnum_id = template->header->seqnum_id;
h.tail_entry_seqnum = template->header->tail_entry_seqnum;
assert(f);
assert(f->header);
- r = sd_id128_get_machine(&f->header->machine_id);
- if (r < 0) {
- if (!ERRNO_IS_MACHINE_ID_UNSET(r))
- return r;
-
- /* don't have a machine-id, let's continue without */
- f->header->machine_id = SD_ID128_NULL;
- }
-
- r = sd_id128_get_boot(&f->header->boot_id);
- if (r < 0)
- return r;
+ /* We used to update the header's boot ID field here, but we don't do that anymore, as per
+ * HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID */
r = journal_file_set_online(f);
int r;
r = sd_id128_get_machine(&machine_id);
- if (r < 0)
- return r;
+ if (r < 0) {
+ if (!ERRNO_IS_MACHINE_ID_UNSET(r)) /* handle graceful if machine ID is not initialized yet */
+ return r;
+
+ machine_id = SD_ID128_NULL;
+ }
if (!sd_id128_equal(machine_id, f->header->machine_id))
return log_debug_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
if (f->header->field_hash_table_size == 0 || f->header->data_hash_table_size == 0)
return -EBADMSG;
-
- /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't
- * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks
- * bisection. */
- if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME))
- return log_debug_errno(SYNTHETIC_ERRNO(ETXTBSY),
- "Journal file %s is from the future, refusing to append new data to it that'd be older.",
- f->path);
}
return 0;
JournalFile *f,
const dual_timestamp *ts,
const sd_id128_t *boot_id,
+ const sd_id128_t *machine_id,
uint64_t xor_hash,
const EntryItem items[],
size_t n_items,
"timestamp %" PRIu64 ", refusing entry.",
ts->realtime, le64toh(f->header->tail_entry_realtime));
- if (!sd_id128_is_null(f->header->boot_id) && boot_id) {
+ if (!sd_id128_is_null(f->header->tail_entry_boot_id) && boot_id) {
- if (!sd_id128_equal(f->header->boot_id, *boot_id))
+ if (!sd_id128_equal(f->header->tail_entry_boot_id, *boot_id))
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE),
"Boot ID to write is different from previous boot id, refusing entry.");
}
}
+ if (machine_id && sd_id128_is_null(f->header->machine_id))
+ /* Initialize machine ID when not set yet */
+ f->header->machine_id = *machine_id;
+
osize = offsetof(Object, entry.items) + (n_items * journal_file_entry_item_size(f));
r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np);
o->entry.monotonic = htole64(ts->monotonic);
o->entry.xor_hash = htole64(xor_hash);
if (boot_id)
- f->header->boot_id = *boot_id;
- o->entry.boot_id = f->header->boot_id;
+ f->header->tail_entry_boot_id = *boot_id;
+ o->entry.boot_id = f->header->tail_entry_boot_id;
for (size_t i = 0; i < n_items; i++)
write_entry_item(f, o, i, &items[i]);
EntryItem *items;
uint64_t xor_hash = 0;
struct dual_timestamp _ts;
- sd_id128_t _boot_id;
+ sd_id128_t _boot_id, _machine_id, *machine_id;
int r;
assert(f);
boot_id = &_boot_id;
}
+ r = sd_id128_get_machine(&_machine_id);
+ if (r < 0) {
+ if (!ERRNO_IS_MACHINE_ID_UNSET(r))
+ return r;
+
+ /* If the machine ID is not initialized yet, handle gracefully */
+ machine_id = NULL;
+ } else
+ machine_id = &_machine_id;
+
#if HAVE_GCRYPT
r = journal_file_maybe_append_tag(f, ts->realtime);
if (r < 0)
typesafe_qsort(items, n_iovec, entry_item_cmp);
n_iovec = remove_duplicate_entry_items(items, n_iovec);
- r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, seqnum_id, ret_object, ret_offset);
+ r = journal_file_append_entry_internal(
+ f,
+ ts,
+ boot_id,
+ machine_id,
+ xor_hash,
+ items,
+ n_iovec,
+ seqnum,
+ seqnum_id,
+ ret_object,
+ ret_offset);
/* If the memory mapping triggered a SIGBUS then we return an
* IO error and ignore the error code passed down to us, since
f->current_xor_hash = le64toh(o->entry.xor_hash);
}
-int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
- int r;
-
- assert(af);
- assert(af->header);
- assert(bf);
- assert(bf->header);
- assert(af->location_type == LOCATION_SEEK);
- assert(bf->location_type == LOCATION_SEEK);
-
- /* If contents, timestamps and seqnum match, these entries are
- * identical. */
- if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
- af->current_monotonic == bf->current_monotonic &&
- af->current_realtime == bf->current_realtime &&
- af->current_xor_hash == bf->current_xor_hash &&
- sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id) &&
- af->current_seqnum == bf->current_seqnum)
- return 0;
-
- if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
-
- /* If this is from the same seqnum source, compare
- * seqnums */
- r = CMP(af->current_seqnum, bf->current_seqnum);
- if (r != 0)
- return r;
-
- /* Wow! This is weird, different data but the same
- * seqnums? Something is borked, but let's make the
- * best of it and compare by time. */
- }
-
- if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
-
- /* If the boot id matches, compare monotonic time */
- r = CMP(af->current_monotonic, bf->current_monotonic);
- if (r != 0)
- return r;
- }
-
- /* Otherwise, compare UTC time */
- r = CMP(af->current_realtime, bf->current_realtime);
- if (r != 0)
- return r;
-
- /* Finally, compare by contents */
- return CMP(af->current_xor_hash, bf->current_xor_hash);
-}
-
static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) {
/* Consider it an error if any of the two offsets is uninitialized */
"Boot ID: %s\n"
"Sequential number ID: %s\n"
"State: %s\n"
- "Compatible flags:%s%s\n"
+ "Compatible flags:%s%s%s\n"
"Incompatible flags:%s%s%s%s%s%s\n"
"Header size: %"PRIu64"\n"
"Arena size: %"PRIu64"\n"
f->path,
SD_ID128_TO_STRING(f->header->file_id),
SD_ID128_TO_STRING(f->header->machine_id),
- SD_ID128_TO_STRING(f->header->boot_id),
+ SD_ID128_TO_STRING(f->header->tail_entry_boot_id),
SD_ID128_TO_STRING(f->header->seqnum_id),
f->header->state == STATE_OFFLINE ? "OFFLINE" :
f->header->state == STATE_ONLINE ? "ONLINE" :
f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "",
+ JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(f->header) ? " TAIL_ENTRY_BOOT_ID" : "",
(le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_ANY) ? " ???" : "",
JOURNAL_HEADER_COMPRESSED_XZ(f->header) ? " COMPRESSED-XZ" : "",
JOURNAL_HEADER_COMPRESSED_LZ4(f->header) ? " COMPRESSED-LZ4" : "",
return r;
}
- r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n, seqnum, seqnum_id, NULL, NULL);
+ r = journal_file_append_entry_internal(
+ to,
+ &ts,
+ boot_id,
+ &from->header->machine_id,
+ xor_hash,
+ items,
+ n,
+ seqnum,
+ seqnum_id,
+ /* ret_object= */ NULL,
+ /* ret_offset= */ NULL);
if (mmap_cache_fd_got_sigbus(to->cache_fd))
return -EIO;
#define JOURNAL_HEADER_SEALED(h) \
FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_SEALED)
+#define JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(h) \
+ FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID)
+
#define JOURNAL_HEADER_COMPRESSED_XZ(h) \
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPRESSED_XZ)
void journal_file_reset_location(JournalFile *f);
void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
-int journal_file_compare_locations(JournalFile *af, JournalFile *bf);
int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_next_entry_for_data(JournalFile *f, Object *d, direction_t direction, Object **ret_object, uint64_t *ret_offset);
}
if (entry_monotonic_set &&
- (sd_id128_equal(entry_boot_id, f->header->boot_id) &&
+ (sd_id128_equal(entry_boot_id, f->header->tail_entry_boot_id) &&
+ JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(f->header) &&
entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
error(0,
"Invalid tail monotonic timestamp (%"PRIu64" != %"PRIu64")",
}
}
+static int compare_locations(JournalFile *af, JournalFile *bf) {
+ int r;
+
+ assert(af);
+ assert(af->header);
+ assert(bf);
+ assert(bf->header);
+ assert(af->location_type == LOCATION_SEEK);
+ assert(bf->location_type == LOCATION_SEEK);
+
+ /* If contents, timestamps and seqnum match, these entries are identical. */
+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
+ af->current_monotonic == bf->current_monotonic &&
+ af->current_realtime == bf->current_realtime &&
+ af->current_xor_hash == bf->current_xor_hash &&
+ sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id) &&
+ af->current_seqnum == bf->current_seqnum)
+ return 0;
+
+ if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
+ /* If this is from the same seqnum source, compare seqnums */
+ r = CMP(af->current_seqnum, bf->current_seqnum);
+ if (r != 0)
+ return r;
+
+ /* Wow! This is weird, different data but the same seqnums? Something is borked, but let's
+ * make the best of it and compare by time. */
+ }
+
+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
+ /* If the boot id matches, compare monotonic time */
+ r = CMP(af->current_monotonic, bf->current_monotonic);
+ if (r != 0)
+ return r;
+ }
+
+ /* Otherwise, compare UTC time */
+ r = CMP(af->current_realtime, bf->current_realtime);
+ if (r != 0)
+ return r;
+
+ /* Finally, compare by contents */
+ return CMP(af->current_xor_hash, bf->current_xor_hash);
+}
+
static int real_journal_next(sd_journal *j, direction_t direction) {
JournalFile *new_file = NULL;
unsigned n_files;
else {
int k;
- k = journal_file_compare_locations(f, new_file);
+ k = compare_locations(f, new_file);
found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
}
assert(w->child == 0);
assert(!w->child_event_source);
- r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
+ r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
if (r < 0)
return r;
if (r == 0) {
idle = session_get_idle_hint(s, &ts);
if (idle) {
- log_debug("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
+ log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
return session_stop(s, /* force */ true);
}
return PAM_SUCCESS;
}
-static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) {
+static int append_session_cpu_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r;
- bool is_cpu_weight;
- is_cpu_weight = streq(field, "CPUWeight");
if (isempty(limit))
return PAM_SUCCESS;
- r = is_cpu_weight ? cg_cpu_weight_parse(limit, &val) : cg_weight_parse(limit, &val);
- if (r >= 0) {
- r = sd_bus_message_append(m, "(sv)", field, "t", val);
+ r = cg_cpu_weight_parse(limit, &val);
+ if (r < 0)
+ pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit);
+ else {
+ r = sd_bus_message_append(m, "(sv)", "CPUWeight", "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
- } else if (is_cpu_weight)
- pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit);
- else
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int append_session_io_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
+ uint64_t val;
+ int r;
+
+ if (isempty(limit))
+ return PAM_SUCCESS;
+
+ r = cg_weight_parse(limit, &val);
+ if (r < 0)
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight, ignoring: %s", limit);
+ else {
+ r = sd_bus_message_append(m, "(sv)", "IOWeight", "t", val);
+ if (r < 0)
+ return pam_bus_log_create_error(handle, r);
+ }
return PAM_SUCCESS;
}
if (r != PAM_SUCCESS)
return r;
- r = append_session_cg_weight(handle, m, cpu_weight, "CPUWeight");
+ r = append_session_cpu_weight(handle, m, cpu_weight);
if (r != PAM_SUCCESS)
return r;
- r = append_session_cg_weight(handle, m, io_weight, "IOWeight");
+ r = append_session_io_weight(handle, m, io_weight);
if (r != PAM_SUCCESS)
return r;
if (pipe2(pipe_fds, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to allocate pipe: %m");
- r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
+ r = safe_fork_full("(getent)",
+ (int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ &pid);
if (r < 0) {
safe_close_pair(pipe_fds);
return r;
}
if (r == 0) {
- char *empty_env = NULL;
-
- pipe_fds[0] = safe_close(pipe_fds[0]);
-
- if (rearrange_stdio(-EBADF, TAKE_FD(pipe_fds[1]), -EBADF) < 0)
- _exit(EXIT_FAILURE);
-
- (void) close_all_fds(NULL, 0);
-
- execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
- execle("/bin/getent", "getent", database, key, NULL, &empty_env);
+ execle("/usr/bin/getent", "getent", database, key, NULL, &(char*[1]){});
+ execle("/bin/getent", "getent", database, key, NULL, &(char*[1]){});
_exit(EXIT_FAILURE);
}
fd_tls = fd[1];
}
- r = safe_fork_full("(test-resolved-stream-tls-openssl)", (int[]) { fd_server, fd_tls }, 2,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &openssl_pid);
+ r = safe_fork_full("(test-resolved-stream-tls-openssl)",
+ (int[]) { fd_tls, fd_tls, STDOUT_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG,
+ &openssl_pid);
assert_se(r >= 0);
if (r == 0) {
/* Child */
- assert_se(dup2(fd_tls, STDIN_FILENO) >= 0);
- assert_se(dup2(fd_tls, STDOUT_FILENO) >= 0);
- close(TAKE_FD(fd_server));
- close(TAKE_FD(fd_tls));
-
execlp("openssl", "openssl", "s_server", "-accept", bind_str,
"-key", key_path, "-cert", cert_path,
"-quiet", "-naccept", "1", NULL);
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "missing_magic.h"
#include "parse-util.h"
*ret = ssz;
return 0;
}
+
+int blockdev_get_root(int level, dev_t *ret) {
+ _cleanup_free_ char *p = NULL;
+ dev_t devno;
+ int r;
+
+ /* Returns the device node backing the root file system. Traces through
+ * dm-crypt/dm-verity/... Returns > 0 and the devno of the device on success. If there's no block
+ * device (or multiple) returns 0 and a devno of 0. Failure otherwise.
+ *
+ * If the root mount has been replaced by some form of volatile file system (overlayfs), the original
+ * root block device node is symlinked in /run/systemd/volatile-root. Let's read that here. */
+ r = readlink_malloc("/run/systemd/volatile-root", &p);
+ if (r == -ENOENT) { /* volatile-root not found */
+ r = get_block_device_harder("/", &devno);
+ if (r == -EUCLEAN)
+ return btrfs_log_dev_root(level, r, "root file system");
+ if (r < 0)
+ return log_full_errno(level, r, "Failed to determine block device of root file system: %m");
+ if (r == 0) { /* Not backed by a single block device. (Could be NFS or so, or could be multi-device RAID or so) */
+ r = get_block_device_harder("/usr", &devno);
+ if (r == -EUCLEAN)
+ return btrfs_log_dev_root(level, r, "/usr");
+ if (r < 0)
+ return log_full_errno(level, r, "Failed to determine block device of /usr/ file system: %m");
+ if (r == 0) { /* /usr/ not backed by single block device, either. */
+ log_debug("Neither root nor /usr/ file system are on a (single) block device.");
+
+ if (ret)
+ *ret = 0;
+
+ return 0;
+ }
+ }
+ } else if (r < 0)
+ return log_full_errno(level, r, "Failed to read symlink /run/systemd/volatile-root: %m");
+ else {
+ mode_t m;
+ r = device_path_parse_major_minor(p, &m, &devno);
+ if (r < 0)
+ return log_full_errno(level, r, "Failed to parse major/minor device node: %m");
+ if (!S_ISBLK(m))
+ return log_full_errno(level, SYNTHETIC_ERRNO(ENOTBLK), "Volatile root device is of wrong type.");
+ }
+
+ if (ret)
+ *ret = devno;
+
+ return 1;
+}
int blockdev_reread_partition_table(sd_device *dev);
int blockdev_get_sector_size(int fd, uint32_t *ret);
+
+int blockdev_get_root(int level, dev_t *ret);
r = safe_fork_full(
"(fsck)",
+ NULL,
&node_fd, 1, /* Leave the node fd open */
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOEXEC_OFF,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
&pid);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
* system call or interacting with the system in any way, besides reading from
* the file descriptor and writing into these four pipes. */
r = safe_fork_full("(sd-parse-elf)",
+ NULL,
(int[]){ fd, error_pipe[1], return_pipe[1], json_pipe[1] },
4,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
r = safe_fork_full(name,
+ NULL,
except,
n_except,
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
install_changes_add(changes, n_changes, q, *s, NULL);
if (r >= 0)
r = q;
+
+ continue;
}
if (!unit_name_is_valid(dst, valid_dst_type)) {
} else
args[1] = desc;
- r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
+#include "udev-util.h"
#define BATTERY_LOW_CAPACITY_LEVEL 5
#define DISCHARGE_RATE_FILEPATH "/var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour"
return battery_capacity;
}
-/* If battery percentage capacity is <= 5%, return success */
-int battery_is_low(void) {
+/* If a battery whose percentage capacity is <= 5% exists, and we're not on AC power, return success */
+int battery_is_discharging_and_low(void) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *dev;
int r;
* or Normal in case ACPI is not working properly. In case of no battery
* 0 will be returned and system will be suspended for 1st cycle then hibernated */
+ r = on_ac_power();
+ if (r < 0)
+ log_debug_errno(r, "Failed to check if the system is running on AC, assuming it is not: %m");
+ if (r > 0)
+ return false;
+
r = battery_enumerator_new(&e);
if (r < 0)
return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
int can_sleep(SleepOperation operation);
int can_sleep_disk(char **types);
int can_sleep_state(char **types);
-int battery_is_low(void);
+int battery_is_discharging_and_low(void);
int get_total_suspend_interval(Hashmap *last_capacity, usec_t *ret);
int fetch_batteries_capacity_by_name(Hashmap **ret_current_capacity);
int get_capacity_by_name(Hashmap *capacities_by_name, const char *name);
/* Due to the possibility of a remount operation hanging, we fork a child process and set a
* timeout. If the timeout lapses, the assumption is that the particular remount failed. */
- r = safe_fork_full("(sd-remount)", pfd, ELEMENTSOF(pfd), FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
+ r = safe_fork_full("(sd-remount)",
+ NULL,
+ pfd, ELEMENTSOF(pfd),
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
/* Due to the possibility of a umount operation hanging, we fork a child process and set a
* timeout. If the timeout lapses, the assumption is that the particular umount failed. */
- r = safe_fork_full("(sd-umount)", pfd, ELEMENTSOF(pfd), FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
+ r = safe_fork_full("(sd-umount)",
+ NULL,
+ pfd, ELEMENTSOF(pfd),
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
hibernate_timestamp = usec_add(now(CLOCK_BOOTTIME), sleep_config->hibernate_delay_usec);
- while (battery_is_low() == 0) {
+ while (battery_is_discharging_and_low() == 0) {
_cleanup_hashmap_free_ Hashmap *last_capacity = NULL, *current_capacity = NULL;
_cleanup_close_ int tfd = -EBADF;
struct itimerspec ts = {};
#include "alloc-util.h"
#include "build.h"
+#include "daemon-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "log.h"
static int run(int argc, char *argv[]) {
_cleanup_(context_clear) Context context = {};
+ _unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r, n, fd;
log_parse_environment();
return r;
}
+ notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
r = sd_event_loop(context.event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
#include "bus-locator.h"
#include "format-table.h"
#include "locale-util.h"
+#include "path-util.h"
#include "set.h"
#include "sort-util.h"
#include "systemctl-list-units.h"
printf("Pass --all to see loaded but inactive %ss, too.\n", type);
}
+static int table_add_triggered(Table *table, char **triggered) {
+ assert(table);
+
+ if (strv_isempty(triggered))
+ return table_add_cell(table, NULL, TABLE_EMPTY, NULL);
+ else if (strv_length(triggered) == 1)
+ return table_add_cell(table, NULL, TABLE_STRING, triggered[0]);
+ else
+ /* This should never happen, currently our socket units can only trigger a
+ * single unit. But let's handle this anyway, who knows what the future
+ * brings? */
+ return table_add_cell(table, NULL, TABLE_STRV, triggered);
+}
+
+static char *format_unit_id(const char *unit, const char *machine) {
+ assert(unit);
+
+ return machine ? strjoin(machine, ":", unit) : strdup(unit);
+}
+
static int output_units_list(const UnitInfo *unit_infos, size_t c) {
_cleanup_(table_unrefp) Table *table = NULL;
size_t job_count = 0;
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (const UnitInfo *u = unit_infos; unit_infos && (size_t) (u - unit_infos) < c; u++) {
- _cleanup_free_ char *j = NULL;
- const char *on_underline = "", *on_loaded = "", *on_active = "";
- const char *on_circle = "", *id;
+ _cleanup_free_ char *id = NULL;
+ const char *on_underline = "", *on_loaded = "", *on_active = "", *on_circle = "";
bool circle = false, underline = false;
if (u + 1 < unit_infos + c &&
on_loaded = on_underline;
}
- if (u->machine) {
- j = strjoin(u->machine, ":", u->id);
- if (!j)
- return log_oom();
-
- id = j;
- } else
- id = u->id;
+ id = format_unit_id(u->id, u->machine);
+ if (!id)
+ return log_oom();
r = table_add_many(table,
TABLE_STRING, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ",
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (struct socket_info *s = socket_infos; s < socket_infos + cs; s++) {
- _cleanup_free_ char *j = NULL;
- const char *path;
+ _cleanup_free_ char *unit = NULL;
- if (s->machine) {
- j = strjoin(s->machine, ":", s->path);
- if (!j)
- return log_oom();
- path = j;
- } else
- path = s->path;
+ unit = format_unit_id(s->id, s->machine);
+ if (!unit)
+ return log_oom();
r = table_add_many(table,
- TABLE_STRING, path,
+ TABLE_STRING, s->path,
TABLE_STRING, s->type,
- TABLE_STRING, s->id);
+ TABLE_STRING, unit);
if (r < 0)
return table_log_add_error(r);
- if (strv_isempty(s->triggered))
- r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
- else if (strv_length(s->triggered) == 1)
- r = table_add_cell(table, NULL, TABLE_STRING, s->triggered[0]);
- else
- /* This should never happen, currently our socket units can only trigger a
- * single unit. But let's handle this anyway, who knows what the future
- * brings? */
- r = table_add_cell(table, NULL, TABLE_STRV, s->triggered);
+ r = table_add_triggered(table, s->triggered);
if (r < 0)
return table_log_add_error(r);
}
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (struct timer_info *t = timer_infos; t < timer_infos + n; t++) {
- _cleanup_free_ char *j = NULL, *activates = NULL;
- const char *unit;
-
- if (t->machine) {
- j = strjoin(t->machine, ":", t->id);
- if (!j)
- return log_oom();
- unit = j;
- } else
- unit = t->id;
+ _cleanup_free_ char *unit = NULL;
- activates = strv_join(t->triggered, ", ");
- if (!activates)
+ unit = format_unit_id(t->id, t->machine);
+ if (!unit)
return log_oom();
r = table_add_many(table,
TABLE_TIMESTAMP_RELATIVE, t->next_elapse,
TABLE_TIMESTAMP, t->last_trigger,
TABLE_TIMESTAMP_RELATIVE, t->last_trigger,
- TABLE_STRING, unit,
- TABLE_STRING, activates);
+ TABLE_STRING, unit);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ r = table_add_triggered(table, t->triggered);
if (r < 0)
return table_log_add_error(r);
}
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (struct automount_info *info = infos; info < infos + n_infos; info++) {
- _cleanup_free_ char *j = NULL;
- const char *unit;
+ _cleanup_free_ char *unit = NULL;
- if (info->machine) {
- j = strjoin(info->machine, ":", info->id);
- if (!j)
- return log_oom();
- unit = j;
- } else
- unit = info->id;
+ unit = format_unit_id(info->id, info->machine);
+ if (!unit)
+ return log_oom();
r = table_add_many(table,
TABLE_STRING, info->what,
return r;
}
+
+struct path_info {
+ const char *machine;
+ const char *id;
+
+ char *path;
+ char *condition;
+
+ /* Note: triggered is a list here, although it almost certainly will always be one
+ * unit. Nevertheless, dbus API allows for multiple values, so let's follow that. */
+ char** triggered;
+};
+
+struct path_infos {
+ size_t count;
+ struct path_info *items;
+};
+
+static int path_info_compare(const struct path_info *a, const struct path_info *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ r = strcasecmp_ptr(a->machine, b->machine);
+ if (r != 0)
+ return r;
+
+ r = path_compare(a->path, b->path);
+ if (r != 0)
+ return r;
+
+ r = strcmp(a->condition, b->condition);
+ if (r != 0)
+ return r;
+
+ return strcasecmp_ptr(a->id, b->id);
+}
+
+static void path_infos_done(struct path_infos *ps) {
+ assert(ps);
+ assert(ps->items || ps->count == 0);
+
+ for (struct path_info *p = ps->items; p < ps->items + ps->count; p++) {
+ free(p->condition);
+ free(p->path);
+ strv_free(p->triggered);
+ }
+
+ free(ps->items);
+}
+
+static int get_paths(sd_bus *bus, const char *unit_path, char ***ret_conditions, char ***ret_paths) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_strv_free_ char **conditions = NULL, **paths = NULL;
+ const char *condition, *path;
+ int r, n = 0;
+
+ assert(bus);
+ assert(unit_path);
+ assert(ret_conditions);
+ assert(ret_paths);
+
+ r = sd_bus_get_property(bus,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.systemd1.Path",
+ "Paths",
+ &error,
+ &reply,
+ "a(ss)");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get paths: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(ss)", &condition, &path)) > 0) {
+ if (strv_extend(&conditions, condition) < 0)
+ return log_oom();
+
+ if (strv_extend(&paths, path) < 0)
+ return log_oom();
+
+ n++;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ *ret_conditions = TAKE_PTR(conditions);
+ *ret_paths = TAKE_PTR(paths);
+
+ return n;
+}
+
+static int output_paths_list(struct path_infos *ps) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+ int r;
+
+ assert(ps);
+ assert(ps->items || ps->count == 0);
+
+ table = table_new("path", "condition", "unit", "activates");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, arg_legend != 0);
+ if (arg_full)
+ table_set_width(table, 0);
+
+ table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
+
+ for (struct path_info *p = ps->items; p < ps->items + ps->count; p++) {
+ _cleanup_free_ char *unit = NULL;
+
+ unit = format_unit_id(p->id, p->machine);
+ if (!unit)
+ return log_oom();
+
+ r = table_add_many(table,
+ TABLE_STRING, p->path,
+ TABLE_STRING, p->condition,
+ TABLE_STRING, unit);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ r = table_add_triggered(table, p->triggered);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (arg_legend != 0)
+ output_legend("path", ps->count);
+
+ return 0;
+}
+
+int verb_list_paths(int argc, char *argv[], void *userdata) {
+ _cleanup_(message_set_freep) Set *replies = NULL;
+ _cleanup_strv_free_ char **machines = NULL, **units = NULL;
+ _cleanup_free_ UnitInfo *unit_infos = NULL;
+ _cleanup_(path_infos_done) struct path_infos path_infos = {};
+ int r, n;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ pager_open(arg_pager_flags);
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), ".path", &units, NULL);
+ if (r < 0)
+ return r;
+
+ if (argc == 1 || units) {
+ n = get_unit_list_recursive(bus, units, &unit_infos, &replies, &machines);
+ if (n < 0)
+ return n;
+
+ for (const UnitInfo *u = unit_infos; u < unit_infos + n; u++) {
+ _cleanup_strv_free_ char **conditions = NULL, **paths = NULL, **triggered = NULL;
+ int c;
+
+ if (!endswith(u->id, ".path"))
+ continue;
+
+ r = get_triggered_units(bus, u->unit_path, &triggered);
+ if (r < 0)
+ return r;
+
+ c = get_paths(bus, u->unit_path, &conditions, &paths);
+ if (c < 0)
+ return c;
+
+ if (!GREEDY_REALLOC(path_infos.items, path_infos.count + c))
+ return log_oom();
+
+ for (int i = c - 1; i >= 0; i--) {
+ char **t;
+
+ t = strv_copy(triggered);
+ if (!t)
+ return log_oom();
+
+ path_infos.items[path_infos.count++] = (struct path_info) {
+ .machine = u->machine,
+ .id = u->id,
+ .condition = TAKE_PTR(conditions[i]),
+ .path = TAKE_PTR(paths[i]),
+ .triggered = t,
+ };
+ }
+ }
+
+ typesafe_qsort(path_infos.items, path_infos.count, path_info_compare);
+ }
+
+ output_paths_list(&path_infos);
+
+ return 0;
+}
int verb_list_sockets(int argc, char *argv[], void *userdata);
int verb_list_timers(int argc, char *argv[], void *userdata);
int verb_list_automounts(int argc, char *argv[], void *userdata);
+int verb_list_paths(int argc, char *argv[], void *userdata);
usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next);
" list-units [PATTERN...] List units currently in memory\n"
" list-automounts [PATTERN...] List automount units currently in memory,\n"
" ordered by path\n"
+ " list-paths [PATTERN...] List path units currently in memory,\n"
+ " ordered by path\n"
" list-sockets [PATTERN...] List socket units currently in memory,\n"
" ordered by address\n"
" list-timers [PATTERN...] List timer units currently in memory,\n"
{ "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, verb_list_units },
{ "list-unit-files", VERB_ANY, VERB_ANY, 0, verb_list_unit_files },
{ "list-automounts", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_automounts },
+ { "list-paths", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_paths },
{ "list-sockets", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_sockets },
{ "list-timers", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_timers },
{ "list-jobs", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_jobs },
log_info("%s Acquiring manifest file %s%s", special_glyph(SPECIAL_GLYPH_DOWNLOAD),
suffixed_url, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
- r = safe_fork("(sd-pull)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(sd-pull)",
+ (int[]) { -EBADF, pfd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG,
+ &pid);
if (r < 0)
return r;
if (r == 0) {
NULL
};
- pfd[0] = safe_close(pfd[0]);
-
- r = rearrange_stdio(-EBADF, pfd[1], STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
(void) unsetenv("NOTIFY_SOCKET");
execv(pull_binary_path(), (char *const*) cmdline);
log_error_errno(errno, "Failed to execute %s tool: %m", pull_binary_path());
assert_se(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) == 0);
assert_se(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) == 0);
- r = safe_fork("(spawn-ldd)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(spawn-ldd)",
+ (int[]) { -EBADF, outpipe[1], errpipe[1] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
- if (rearrange_stdio(-EBADF, TAKE_FD(outpipe[1]), TAKE_FD(errpipe[1])) < 0)
- _exit(EXIT_FAILURE);
-
- (void) close_all_fds(NULL, 0);
-
execlp("ldd", "ldd", exec, NULL);
_exit(EXIT_FAILURE);
}
BLOCK_SIGNALS(SIGCHLD);
- r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
+ r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
log_device_debug(event->dev, "Starting '%s'", cmd);
- r = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
+ r = safe_fork_full("(spawn)",
+ (int[]) { -EBADF, outpipe[WRITE_END], errpipe[WRITE_END] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ &pid);
if (r < 0)
return log_device_error_errno(event->dev, r,
"Failed to fork() to execute command '%s': %m", cmd);
if (r == 0) {
- if (rearrange_stdio(-EBADF, TAKE_FD(outpipe[WRITE_END]), TAKE_FD(errpipe[WRITE_END])) < 0)
- _exit(EXIT_FAILURE);
-
- (void) close_all_fds(NULL, 0);
-
DEVICE_TRACE_POINT(spawn_exec, event->dev, cmd);
-
execve(argv[0], argv, envp);
_exit(EXIT_FAILURE);
}
"$bootctl" list --json=pretty | jq . >/dev/null
"$bootctl" list --json=short | jq . >/dev/null
+
+# bootctl --print-root-device should either succeed or fail with exit status 80
+# (because not backed by a single block device), but not fail otherwise.
+"$bootctl" -R || test "$?" -eq 80
+"$bootctl" -RR || test "$?" -eq 80
+
+if "$bootctl" -R > /dev/null ; then
+ P=$("$bootctl" -R)
+ PP=$("$bootctl" -RR)
+
+ echo "$P vs $PP"
+ test -b "$P"
+ test -b "$PP"
+
+ # $P must be a prefix of $PP
+ [[ $P = $PP* ]]
+fi
EDITOR='mv' script -ec 'systemctl edit "$UNIT_NAME"' /dev/null
printf '%s\n' '[Service]' 'ExecStart=' 'ExecStart=sleep 10d' | cmp - "/etc/systemd/system/$UNIT_NAME.d/override.conf"
+# Double free when editing a template unit (#26483)
+EDITOR='true' script -ec 'systemctl edit user@0' /dev/null
+
# Argument help
systemctl --state help
systemctl --signal help
systemctl list-dependencies sysinit.target --type=socket,mount
systemctl list-dependencies multi-user.target --state=active
systemctl list-dependencies sysinit.target --state=mounted --all
+systemctl list-paths
+systemctl list-paths --legend=no -a "systemd*"
# is-* verbs
# Should return 4 for a missing unit file
systemctl stop issue-24990
fi
+# %J in WantedBy= causes ABRT (#26467)
+cat >/run/systemd/system/test-WantedBy.service <<EOF
+[Service]
+ExecStart=true
+
+[Install]
+WantedBy=user-%i@%J.service
+EOF
+systemctl daemon-reload
+systemctl enable --now test-WantedBy.service || :
+systemctl daemon-reload
+
touch /testok
rm /failed
# Ensure that sandboxing doesn't stop creds from being accessible
echo "test" > /tmp/testdata
systemd-creds encrypt /tmp/testdata /tmp/testdata.encrypted --with-key=tpm2
+# LoadCredentialEncrypted
systemd-run -p PrivateDevices=yes -p LoadCredentialEncrypted=testdata.encrypted:/tmp/testdata.encrypted --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
+# SetCredentialEncrypted
+systemd-run -p PrivateDevices=yes -p SetCredentialEncrypted=testdata.encrypted:"$(cat /tmp/testdata.encrypted)" --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
rm /tmp/testdata
echo OK >/testok