Compare commits
21 Commits
f4cbbed6dd
...
ddc3d39198
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | ddc3d39198 | |
Lennart Poettering | b480a4c15e | |
Lennart Poettering | af3baf174a | |
Ryan Wilson | d8091e1281 | |
Lennart Poettering | 0df42ebcd6 | |
Daan De Meyer | 20c03ed72b | |
Daan De Meyer | 64cc7ba517 | |
Daan De Meyer | c4bc0fd6de | |
Daan De Meyer | a1d46e3078 | |
Daan De Meyer | 5619a61829 | |
Daan De Meyer | 4047b99c00 | |
Daan De Meyer | 5cca978dae | |
Yu Watanabe | dd2bf3141b | |
Vursc | eb03dffd97 | |
Zbigniew Jędrzejewski-Szmek | 97318131fd | |
Zbigniew Jędrzejewski-Szmek | 5ffff673ac | |
Zbigniew Jędrzejewski-Szmek | 1dabec0056 | |
Zbigniew Jędrzejewski-Szmek | daf72e8df1 | |
Zbigniew Jędrzejewski-Szmek | 0b676aab33 | |
Lennart Poettering | 8fd917a74d | |
Lennart Poettering | 6cda26f3d6 |
25
TODO
25
TODO
|
@ -129,6 +129,10 @@ Deprecations and removals:
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
|
* format-table: introduce new cell type for strings with ansi sequences in
|
||||||
|
them. display them in regular output mode (via strip_tab_ansi()), but
|
||||||
|
suppress them in json mode.
|
||||||
|
|
||||||
* machined: when registering a machine, also take a relative cgroup path,
|
* machined: when registering a machine, also take a relative cgroup path,
|
||||||
relative to the machine's unit. This is useful when registering unpriv
|
relative to the machine's unit. This is useful when registering unpriv
|
||||||
machines, as they might sit down the cgroup tree, below a cgroup delegation
|
machines, as they might sit down the cgroup tree, below a cgroup delegation
|
||||||
|
@ -217,12 +221,8 @@ Features:
|
||||||
services where mount propagation from the root fs is off, an still have
|
services where mount propagation from the root fs is off, an still have
|
||||||
confext/sysext propagated in.
|
confext/sysext propagated in.
|
||||||
|
|
||||||
* support F_DUDFD_QUERY for comparing fds in same_fd (requires kernel 6.10)
|
|
||||||
|
|
||||||
* generic interface for varlink for setting log level and stuff that all our daemons can implement
|
* generic interface for varlink for setting log level and stuff that all our daemons can implement
|
||||||
|
|
||||||
* use pty ioctl to get peer wherever possible (TIOCGPTPEER)
|
|
||||||
|
|
||||||
* maybe teach repart.d/ dropins a new setting MakeMountNodes= or so, which is
|
* maybe teach repart.d/ dropins a new setting MakeMountNodes= or so, which is
|
||||||
just like MakeDirectories=, but uses an access mode of 0000 and sets the +i
|
just like MakeDirectories=, but uses an access mode of 0000 and sets the +i
|
||||||
chattr bit. This is useful as protection against early uses of /var/ or /tmp/
|
chattr bit. This is useful as protection against early uses of /var/ or /tmp/
|
||||||
|
@ -253,8 +253,6 @@ Features:
|
||||||
* initrd: when transitioning from initrd to host, validate that
|
* initrd: when transitioning from initrd to host, validate that
|
||||||
/lib/modules/`uname -r` exists, refuse otherwise
|
/lib/modules/`uname -r` exists, refuse otherwise
|
||||||
|
|
||||||
* tmpfiles: add "owning" flag for lines that limits effect of --purge
|
|
||||||
|
|
||||||
* signed bpf loading: to address need for signature verification for bpf
|
* signed bpf loading: to address need for signature verification for bpf
|
||||||
programs when they are loaded, and given the bpf folks don't think this is
|
programs when they are loaded, and given the bpf folks don't think this is
|
||||||
realistic in kernel space, maybe add small daemon that facilitates this
|
realistic in kernel space, maybe add small daemon that facilitates this
|
||||||
|
@ -458,9 +456,6 @@ Features:
|
||||||
* introduce mntid_t, and make it 64bit, as apparently the kernel switched to
|
* introduce mntid_t, and make it 64bit, as apparently the kernel switched to
|
||||||
64bit mount ids
|
64bit mount ids
|
||||||
|
|
||||||
* use udev rule networkd ownership property to take ownership of network
|
|
||||||
interfaces nspawn creates
|
|
||||||
|
|
||||||
* mountfsd/nsresourced
|
* mountfsd/nsresourced
|
||||||
- userdb: maybe allow callers to map one uid to their own uid
|
- userdb: maybe allow callers to map one uid to their own uid
|
||||||
- bpflsm: allow writes if resulting UID on disk would be userns' owner UID
|
- bpflsm: allow writes if resulting UID on disk would be userns' owner UID
|
||||||
|
@ -647,6 +642,7 @@ Features:
|
||||||
- openpt_allocate_in_namespace()
|
- openpt_allocate_in_namespace()
|
||||||
- unit_attach_pid_to_cgroup_via_bus()
|
- unit_attach_pid_to_cgroup_via_bus()
|
||||||
- cg_attach() – requires new kernel feature
|
- cg_attach() – requires new kernel feature
|
||||||
|
- journald's process cache
|
||||||
|
|
||||||
* ddi must be listed as block device fstype
|
* ddi must be listed as block device fstype
|
||||||
|
|
||||||
|
@ -1470,9 +1466,6 @@ Features:
|
||||||
|
|
||||||
* in sd-id128: also parse UUIDs in RFC4122 URN syntax (i.e. chop off urn:uuid: prefix)
|
* in sd-id128: also parse UUIDs in RFC4122 URN syntax (i.e. chop off urn:uuid: prefix)
|
||||||
|
|
||||||
* DynamicUser= + StateDirectory= → use uid mapping mounts, too, in order to
|
|
||||||
make dirs appear under right UID.
|
|
||||||
|
|
||||||
* systemd-sysext: optionally, run it in initrd already, before transitioning
|
* systemd-sysext: optionally, run it in initrd already, before transitioning
|
||||||
into host, to open up possibility for services shipped like that.
|
into host, to open up possibility for services shipped like that.
|
||||||
|
|
||||||
|
@ -1644,14 +1637,6 @@ Features:
|
||||||
|
|
||||||
* maybe add kernel cmdline params: to force random seed crediting
|
* maybe add kernel cmdline params: to force random seed crediting
|
||||||
|
|
||||||
* introduce a new per-process uuid, similar to the boot id, the machine id, the
|
|
||||||
invocation id, that is derived from process creds, specifically a hashed
|
|
||||||
combination of AT_RANDOM + getpid() + the starttime from
|
|
||||||
/proc/self/status. Then add these ids implicitly when logging. Deriving this
|
|
||||||
uuid from these three things has the benefit that it can be derived easily
|
|
||||||
from /proc/$PID/ in a stable, and unique way that changes on both fork() and
|
|
||||||
exec().
|
|
||||||
|
|
||||||
* let's not GC a unit while its ratelimits are still pending
|
* let's not GC a unit while its ratelimits are still pending
|
||||||
|
|
||||||
* when killing due to service watchdog timeout maybe detect whether target
|
* when killing due to service watchdog timeout maybe detect whether target
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
title: TPM2 NV Index Assignment by systemd
|
||||||
|
category: Booting
|
||||||
|
layout: default
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
---
|
||||||
|
|
||||||
|
# TPM 2.0 NV Index Assignments
|
||||||
|
|
||||||
|
The Trusted Computing Group (TCG) maintains a [Registry of Reserved TPM 2.0
|
||||||
|
Handles and Localities](https://trustedcomputinggroup.org/resource/registry/)
|
||||||
|
which assigns TPM 2.0 NV index ranges (among ther things, see section 2.2) to
|
||||||
|
organizations (by convention only!). It has assigned the NV index range
|
||||||
|
**0x01800400-0x018005FF** to the systemd project. This NV index range is subdivided
|
||||||
|
and used by systemd for the following purposes:
|
||||||
|
|
||||||
|
## As Storage for a Disk Encryption PolicyAuthorizeNV Policy Hash
|
||||||
|
|
||||||
|
*Scope*: Dynamic allocation at OS installation time, one for each installed
|
||||||
|
Linux/systemd based OS that uses `systemd-pcrlock` based disk encryption policies.
|
||||||
|
|
||||||
|
*Subrange*: **0x01800400-0x0180041F**
|
||||||
|
|
||||||
|
*Number of NV Indexes*: **32**
|
||||||
|
|
||||||
|
*Size*: Stores one policy hash. Under the assumption SHA256 policy hashes are
|
||||||
|
used, this means **32 byte**.
|
||||||
|
|
||||||
|
## As Storage for Additional PCRs Implemented in NV Indexes
|
||||||
|
|
||||||
|
*Scope*: Static allocation by the systemd project, one for each additional NV
|
||||||
|
Indexed based PCR (systemd calls these "NvPCRs"). These can be shared between
|
||||||
|
multiple Linux/systemd based OSes installed on the same system.
|
||||||
|
|
||||||
|
*Subrange*: **0x01800420-0x01800423**
|
||||||
|
|
||||||
|
*Number of NV Indexes*: **4**
|
||||||
|
|
||||||
|
*Size*: Stores one PCR hash each (`TPMA_NT_EXTEND`). We'd expect that typically
|
||||||
|
SHA256 PCR hashes are used, hence this means **32 byte**.
|
||||||
|
|
||||||
|
*Detailed Assignments*:
|
||||||
|
|
||||||
|
| NVIndex | Purpose |
|
||||||
|
|------------|---------------------------------------------------------------|
|
||||||
|
| 0x01800420 | Used LUKS unlock mechanism (TPM2, PKCS11, FIDO2, …) |
|
||||||
|
| 0x01800421 | Product UUID |
|
||||||
|
| 0x01800422 | System Extension Images (sysexts) applied to the host |
|
||||||
|
| 0x01800423 | Configuration Extension Images (confexts) applied to the host |
|
||||||
|
|
||||||
|
## Currently Unused Range
|
||||||
|
|
||||||
|
The following range is currently not used by the systemd project, but might be
|
||||||
|
allocated later: **0x01800424-0x018005FF**
|
||||||
|
|
||||||
|
## Summary:
|
||||||
|
|
||||||
|
| NVIndex Range | Number | Purpose |
|
||||||
|
|-----------------------|--------|------------------------------------------------|
|
||||||
|
| 0x01800400-0x0180041F | 32 | Assigned to systemd, used for pcrlock policies |
|
||||||
|
| 0x01800420-0x01800423 | 4 | Assigned to systemd, used as additional PCRs |
|
||||||
|
| 0x01800424-0x018005FF | 476 | Assigned to systemd, currently unused |
|
||||||
|
|
||||||
|
# Relationship with TCG
|
||||||
|
|
||||||
|
This document is referenced by the aforementioned registry for details about
|
||||||
|
assignments of the NV Index range delegated to the systemd project. Hence,
|
||||||
|
particular care should be taken that this page is not moved, and its URL
|
||||||
|
remains stable as
|
||||||
|
[`https://systemd.io/TPM2_NVINDEX_ASSIGNMENTS`](https://systemd.io/TPM2_NVINDEX_ASSIGNMENTS).
|
|
@ -1149,6 +1149,11 @@ evdev:name:SIPODEV Lenovo HID Device:dmi:*:svnLENOVO:*:pvrLenovoideapadD330-10IG
|
||||||
evdev:name:SIPODEV Lenovo HID Device Consumer Control:dmi:*:svnLENOVO:*:pvrLenovoideapadD330-10IGM:*
|
evdev:name:SIPODEV Lenovo HID Device Consumer Control:dmi:*:svnLENOVO:*:pvrLenovoideapadD330-10IGM:*
|
||||||
KEYBOARD_KEY_c00ff=fn_esc # Fn+Tab (FnLk toggle)
|
KEYBOARD_KEY_c00ff=fn_esc # Fn+Tab (FnLk toggle)
|
||||||
|
|
||||||
|
# Lenovo Thinkbook 16 G6+ 2024
|
||||||
|
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn21LG:pvr*
|
||||||
|
KEYBOARD_KEY_0a=!9
|
||||||
|
KEYBOARD_KEY_0b=!0
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
# LG
|
# LG
|
||||||
###########################################################
|
###########################################################
|
||||||
|
|
|
@ -529,8 +529,9 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--secure-boot-auto-enroll=yes|no</option></term>
|
<term><option>--secure-boot-auto-enroll=yes|no</option></term>
|
||||||
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
|
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
|
||||||
<term><option>--private-key-source=<replaceable>TYPE[:NAME]</replaceable></option></term>
|
<term><option>--private-key-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
||||||
<term><option>--certificate=<replaceable>PATH</replaceable></option></term>
|
<term><option>--certificate=<replaceable>PATH</replaceable></option></term>
|
||||||
|
<term><option>--certificate-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
||||||
|
|
||||||
<listitem><para>Configure the ESP for secure boot auto-enrollment when invoking the
|
<listitem><para>Configure the ESP for secure boot auto-enrollment when invoking the
|
||||||
<command>install</command> command. Takes a boolean argument. Disabled by default. Enabling this
|
<command>install</command> command. Takes a boolean argument. Disabled by default. Enabling this
|
||||||
|
@ -542,9 +543,12 @@
|
||||||
|
|
||||||
<para>When specifying this option, a certificate and private key have to be provided as well using
|
<para>When specifying this option, a certificate and private key have to be provided as well using
|
||||||
the <option>--certificate=</option> and <option>--private-key=</option> options. The
|
the <option>--certificate=</option> and <option>--private-key=</option> options. The
|
||||||
<option>--certificate=</option> option takes a path to a PEM encoded X.509 certificate. The
|
<option>--certificate=</option> option takes a path to a PEM encoded X.509 certificate or a URI
|
||||||
<option>--private-key=</option> option can take a path or a URI that will be passed to the OpenSSL
|
that's passed to the OpenSSL provider configured with <option>--certificate-source</option> which
|
||||||
engine or provider, as specified by <option>--private-key-source=</option> as a
|
takes one of <literal>file</literal> or <literal>provider</literal>, with the latter being followed
|
||||||
|
by a specific provider identifier, separated with a colon, e.g. <literal>provider:pkcs11</literal>.
|
||||||
|
The <option>--private-key=</option> option can take a path or a URI that will be passed to the
|
||||||
|
OpenSSL engine or provider, as specified by <option>--private-key-source=</option> as a
|
||||||
<literal>type:name</literal> tuple, such as <literal>engine:pkcs11</literal>. The specified OpenSSL
|
<literal>type:name</literal> tuple, such as <literal>engine:pkcs11</literal>. The specified OpenSSL
|
||||||
signing engine or provider will be used to sign the EFI signature lists.</para>
|
signing engine or provider will be used to sign the EFI signature lists.</para>
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,16 @@
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>pcrpkey</command></term>
|
||||||
|
|
||||||
|
<listitem><para>This commands prints the public key either given with <option>--public-key=</option>,
|
||||||
|
or extracted from the certificate given with <option>--certificate=</option> or the private key given
|
||||||
|
with <option>--private-key=</option>.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -188,8 +198,9 @@
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
|
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
|
||||||
<term><option>--private-key-source=<replaceable>TYPE[:NAME]</replaceable></option></term>
|
<term><option>--private-key-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
||||||
<term><option>--certificate=<replaceable>PATH</replaceable></option></term>
|
<term><option>--certificate=<replaceable>PATH/URI</replaceable></option></term>
|
||||||
|
<term><option>--certificate-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
||||||
|
|
||||||
<listitem><para>As an alternative to <option>--public-key=</option> for the
|
<listitem><para>As an alternative to <option>--public-key=</option> for the
|
||||||
<command>sign</command> command, these switches can be used to sign with an hardware token. The
|
<command>sign</command> command, these switches can be used to sign with an hardware token. The
|
||||||
|
@ -197,6 +208,11 @@
|
||||||
provider, as specified by <option>--private-key-source=</option> as a type:name tuple, such as
|
provider, as specified by <option>--private-key-source=</option> as a type:name tuple, such as
|
||||||
engine:pkcs11. The specified OpenSSL signing engine or provider will be used to sign.</para>
|
engine:pkcs11. The specified OpenSSL signing engine or provider will be used to sign.</para>
|
||||||
|
|
||||||
|
<para>The <option>--certificate=</option> option also takes a path or a URI that will be passed to
|
||||||
|
the OpenSSL provider, as specified by <option>--certificate-source=</option> as a
|
||||||
|
<literal>type:name</literal> tuple, such as <literal>provider:pkcs11</literal>. Note that unlike
|
||||||
|
<option>--private-key-source=</option> this option only supports providers and not engines.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
|
@ -348,9 +348,9 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--private-key=</option></term>
|
<term><option>--private-key=</option></term>
|
||||||
|
|
||||||
<listitem><para>Takes a file system path. Configures the signing key to use when creating verity
|
<listitem><para>Takes a file system path or an engine or provider specific designation. Configures
|
||||||
signature partitions with the <varname>Verity=signature</varname> setting in partition files.
|
the signing key to use when creating verity signature partitions with the
|
||||||
</para>
|
<varname>Verity=signature</varname> setting in partition files.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -361,7 +361,7 @@
|
||||||
<listitem><para>Takes one of <literal>file</literal>, <literal>engine</literal> or
|
<listitem><para>Takes one of <literal>file</literal>, <literal>engine</literal> or
|
||||||
<literal>provider</literal>. In the latter two cases, it is followed by the name of a provider or
|
<literal>provider</literal>. In the latter two cases, it is followed by the name of a provider or
|
||||||
engine, separated by colon, that will be passed to OpenSSL's "engine" or "provider" logic.
|
engine, separated by colon, that will be passed to OpenSSL's "engine" or "provider" logic.
|
||||||
Configures the signing mechanism to use when creating verity signature partitions with the
|
Configures how to load the private key to use when creating verity signature partitions with the
|
||||||
<varname>Verity=signature</varname> setting in partition files.</para>
|
<varname>Verity=signature</varname> setting in partition files.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||||
|
@ -370,13 +370,24 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--certificate=</option></term>
|
<term><option>--certificate=</option></term>
|
||||||
|
|
||||||
<listitem><para>Takes a file system path. Configures the PEM encoded X.509 certificate to use when
|
<listitem><para>Takes a file system path or a provider specific designation. Configures the PEM
|
||||||
creating verity signature partitions with the <varname>Verity=signature</varname> setting in
|
encoded X.509 certificate to use when creating verity signature partitions with the
|
||||||
partition files.</para>
|
<varname>Verity=signature</varname> setting in partition files.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--certificate-source=</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes one of <literal>file</literal>, or <literal>provider</literal>. In the latter
|
||||||
|
case, it is followed by the name of a provider, separated by colon, that will be passed to OpenSSL's
|
||||||
|
"provider" logic. Configures how to load the X.509 certificate to use when creating verity signature
|
||||||
|
partitions with the <varname>Verity=signature</varname> setting in partition files.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--tpm2-device=</option></term>
|
<term><option>--tpm2-device=</option></term>
|
||||||
<term><option>--tpm2-pcrs=</option></term>
|
<term><option>--tpm2-pcrs=</option></term>
|
||||||
|
|
|
@ -85,11 +85,16 @@
|
||||||
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
|
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
|
||||||
<term><option>--private-key-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
<term><option>--private-key-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
||||||
<term><option>--certificate=<replaceable>PATH</replaceable></option></term>
|
<term><option>--certificate=<replaceable>PATH</replaceable></option></term>
|
||||||
|
<term><option>--certificate-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
|
||||||
|
|
||||||
<listitem><para>Set the Secure Boot private key and certificate for use with the
|
<listitem><para>Set the Secure Boot private key and certificate for use with the
|
||||||
<command>sign</command>. The <option>--certificate=</option> option takes a path to a PEM encoded
|
<command>sign</command>. The <option>--certificate=</option> option takes a path to a PEM encoded
|
||||||
X.509 certificate. The <option>--private-key=</option> option can take a path or a URI that will be
|
X.509 certificate or a URI that's passed to the OpenSSL provider configured with
|
||||||
passed to the OpenSSL engine or provider, as specified by <option>--private-key-source=</option> as a
|
<option>--certificate-source</option>. The <option>--certificate-source</option> takes one of
|
||||||
|
<literal>file</literal> or <literal>provider</literal>, with the latter being followed by a specific
|
||||||
|
provider identifier, separated with a colon, e.g. <literal>provider:pkcs11</literal>. The
|
||||||
|
<option>--private-key=</option> option can take a path or a URI that will be passed to the OpenSSL
|
||||||
|
engine or provider, as specified by <option>--private-key-source=</option> as a
|
||||||
<literal>type:name</literal> tuple, such as <literal>engine:pkcs11</literal>. The specified OpenSSL
|
<literal>type:name</literal> tuple, such as <literal>engine:pkcs11</literal>. The specified OpenSSL
|
||||||
signing engine or provider will be used to sign the PE binary.</para>
|
signing engine or provider will be used to sign the PE binary.</para>
|
||||||
|
|
||||||
|
|
|
@ -527,6 +527,17 @@
|
||||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>CertificateProvider=<replaceable>PROVIDER</replaceable></varname></term>
|
||||||
|
<term><option>--certificate-provider=<replaceable>PROVIDER</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>An OpenSSL provider to be used for loading the certificate used to sign the
|
||||||
|
resulting binary and PCR measurements. This option can only be used when using
|
||||||
|
<command>systemd-sbsign</command> as the signing tool.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>SignKernel=<replaceable>BOOL</replaceable></varname></term>
|
<term><varname>SignKernel=<replaceable>BOOL</replaceable></varname></term>
|
||||||
<term><option>--sign-kernel</option></term>
|
<term><option>--sign-kernel</option></term>
|
||||||
|
|
|
@ -2344,8 +2344,9 @@ subdir('src/ask-password')
|
||||||
subdir('src/backlight')
|
subdir('src/backlight')
|
||||||
subdir('src/battery-check')
|
subdir('src/battery-check')
|
||||||
subdir('src/binfmt')
|
subdir('src/binfmt')
|
||||||
|
subdir('src/bless-boot')
|
||||||
subdir('src/boot')
|
subdir('src/boot')
|
||||||
subdir('src/boot/efi')
|
subdir('src/bootctl')
|
||||||
subdir('src/busctl')
|
subdir('src/busctl')
|
||||||
subdir('src/cgls')
|
subdir('src/cgls')
|
||||||
subdir('src/cgroups-agent')
|
subdir('src/cgroups-agent')
|
||||||
|
@ -2380,6 +2381,7 @@ subdir('src/locale')
|
||||||
subdir('src/login')
|
subdir('src/login')
|
||||||
subdir('src/machine')
|
subdir('src/machine')
|
||||||
subdir('src/machine-id-setup')
|
subdir('src/machine-id-setup')
|
||||||
|
subdir('src/measure')
|
||||||
subdir('src/mountfsd')
|
subdir('src/mountfsd')
|
||||||
subdir('src/modules-load')
|
subdir('src/modules-load')
|
||||||
subdir('src/mount')
|
subdir('src/mount')
|
||||||
|
@ -2408,6 +2410,7 @@ subdir('src/rfkill')
|
||||||
subdir('src/rpm')
|
subdir('src/rpm')
|
||||||
subdir('src/run')
|
subdir('src/run')
|
||||||
subdir('src/run-generator')
|
subdir('src/run-generator')
|
||||||
|
subdir('src/sbsign')
|
||||||
subdir('src/shutdown')
|
subdir('src/shutdown')
|
||||||
subdir('src/sleep')
|
subdir('src/sleep')
|
||||||
subdir('src/socket-activate')
|
subdir('src/socket-activate')
|
||||||
|
|
|
@ -9,5 +9,6 @@ ToolsTreePackages=
|
||||||
libcap
|
libcap
|
||||||
libmicrohttpd
|
libmicrohttpd
|
||||||
python-jinja
|
python-jinja
|
||||||
|
python-pytest
|
||||||
tpm2-tss
|
tpm2-tss
|
||||||
util-linux-libs
|
util-linux-libs
|
||||||
|
|
|
@ -15,3 +15,4 @@ ToolsTreePackages=
|
||||||
pkgconfig(mount)
|
pkgconfig(mount)
|
||||||
tss2-devel
|
tss2-devel
|
||||||
python3-jinja2
|
python3-jinja2
|
||||||
|
python3-pytest
|
||||||
|
|
|
@ -15,3 +15,4 @@ ToolsTreePackages=
|
||||||
libmount-dev
|
libmount-dev
|
||||||
libtss2-dev
|
libtss2-dev
|
||||||
python3-jinja2
|
python3-jinja2
|
||||||
|
python3-pytest
|
||||||
|
|
|
@ -14,3 +14,4 @@ ToolsTreePackages=
|
||||||
pkgconfig(mount)
|
pkgconfig(mount)
|
||||||
tss2-devel
|
tss2-devel
|
||||||
python3-jinja2
|
python3-jinja2
|
||||||
|
python3-pytest
|
||||||
|
|
|
@ -1131,6 +1131,8 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_
|
||||||
* • If O_CREAT is used with XO_LABEL, any created file will be immediately relabelled.
|
* • If O_CREAT is used with XO_LABEL, any created file will be immediately relabelled.
|
||||||
*
|
*
|
||||||
* • If the path is specified NULL or empty, behaves like fd_reopen().
|
* • If the path is specified NULL or empty, behaves like fd_reopen().
|
||||||
|
*
|
||||||
|
* • If XO_NOCOW is specified will turn on the NOCOW btrfs flag on the file, if available.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (isempty(path)) {
|
if (isempty(path)) {
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
if get_option('link-boot-shared')
|
||||||
|
boot_link_with = [libshared]
|
||||||
|
else
|
||||||
|
boot_link_with = [
|
||||||
|
libshared_static,
|
||||||
|
libsystemd_static,
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
executables += [
|
||||||
|
libexec_template + {
|
||||||
|
'name' : 'systemd-bless-boot',
|
||||||
|
'public' : true,
|
||||||
|
'conditions' : [
|
||||||
|
'HAVE_BLKID',
|
||||||
|
'ENABLE_BOOTLOADER',
|
||||||
|
],
|
||||||
|
'sources' : files('bless-boot.c'),
|
||||||
|
'link_with' : boot_link_with,
|
||||||
|
'dependencies' : libblkid,
|
||||||
|
},
|
||||||
|
generator_template + {
|
||||||
|
'name' : 'systemd-bless-boot-generator',
|
||||||
|
'conditions' : [
|
||||||
|
'HAVE_BLKID',
|
||||||
|
'ENABLE_BOOTLOADER',
|
||||||
|
],
|
||||||
|
'sources' : files('bless-boot-generator.c'),
|
||||||
|
'link_with' : boot_link_with,
|
||||||
|
},
|
||||||
|
libexec_template + {
|
||||||
|
'name' : 'systemd-boot-check-no-failures',
|
||||||
|
'sources' : files('boot-check-no-failures.c'),
|
||||||
|
},
|
||||||
|
]
|
|
@ -1,324 +0,0 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
|
|
||||||
#if ENABLE_TPM
|
|
||||||
|
|
||||||
#include "macro-fundamental.h"
|
|
||||||
#include "measure.h"
|
|
||||||
#include "memory-util-fundamental.h"
|
|
||||||
#include "proto/cc-measurement.h"
|
|
||||||
#include "proto/tcg.h"
|
|
||||||
#include "tpm2-pcr.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
static EFI_STATUS tpm2_measure_to_pcr_and_tagged_event_log(
|
|
||||||
EFI_TCG2_PROTOCOL *tcg,
|
|
||||||
uint32_t pcrindex,
|
|
||||||
EFI_PHYSICAL_ADDRESS buffer,
|
|
||||||
uint64_t buffer_size,
|
|
||||||
uint32_t event_id,
|
|
||||||
const char16_t *description) {
|
|
||||||
|
|
||||||
_cleanup_free_ struct event {
|
|
||||||
EFI_TCG2_EVENT tcg_event;
|
|
||||||
EFI_TCG2_TAGGED_EVENT tcg_tagged_event;
|
|
||||||
} _packed_ *event = NULL;
|
|
||||||
size_t desc_len, event_size;
|
|
||||||
|
|
||||||
assert(tcg);
|
|
||||||
assert(description);
|
|
||||||
|
|
||||||
/* New style stuff we log as EV_EVENT_TAG with a recognizable event tag. */
|
|
||||||
|
|
||||||
desc_len = strsize16(description);
|
|
||||||
event_size = offsetof(EFI_TCG2_EVENT, Event) + offsetof(EFI_TCG2_TAGGED_EVENT, Event) + desc_len;
|
|
||||||
|
|
||||||
event = xmalloc(event_size);
|
|
||||||
*event = (struct event) {
|
|
||||||
.tcg_event = (EFI_TCG2_EVENT) {
|
|
||||||
.Size = event_size,
|
|
||||||
.Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER),
|
|
||||||
.Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION,
|
|
||||||
.Header.PCRIndex = pcrindex,
|
|
||||||
.Header.EventType = EV_EVENT_TAG,
|
|
||||||
},
|
|
||||||
.tcg_tagged_event = {
|
|
||||||
.EventId = event_id,
|
|
||||||
.EventSize = desc_len,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
memcpy(event->tcg_tagged_event.Event, description, desc_len);
|
|
||||||
|
|
||||||
return tcg->HashLogExtendEvent(
|
|
||||||
tcg,
|
|
||||||
0,
|
|
||||||
buffer, buffer_size,
|
|
||||||
&event->tcg_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static EFI_STATUS tpm2_measure_to_pcr_and_ipl_event_log(
|
|
||||||
EFI_TCG2_PROTOCOL *tcg,
|
|
||||||
uint32_t pcrindex,
|
|
||||||
EFI_PHYSICAL_ADDRESS buffer,
|
|
||||||
uint64_t buffer_size,
|
|
||||||
const char16_t *description) {
|
|
||||||
|
|
||||||
_cleanup_free_ EFI_TCG2_EVENT *tcg_event = NULL;
|
|
||||||
size_t desc_len;
|
|
||||||
|
|
||||||
assert(tcg);
|
|
||||||
assert(description);
|
|
||||||
|
|
||||||
/* We record older stuff as EV_IPL. Which sucks, because it makes it hard to recognize from the event
|
|
||||||
* log which of the events are ours. Measurement logs are kinda API hence this is hard to change for
|
|
||||||
* existing, established events. But for future additions, let's use EV_EVENT_TAG instead, with a tag
|
|
||||||
* of our choosing that makes clear what precisely we are measuring here. See above. */
|
|
||||||
|
|
||||||
desc_len = strsize16(description);
|
|
||||||
tcg_event = xmalloc(offsetof(EFI_TCG2_EVENT, Event) + desc_len);
|
|
||||||
*tcg_event = (EFI_TCG2_EVENT) {
|
|
||||||
.Size = offsetof(EFI_TCG2_EVENT, Event) + desc_len,
|
|
||||||
.Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER),
|
|
||||||
.Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION,
|
|
||||||
.Header.PCRIndex = pcrindex,
|
|
||||||
.Header.EventType = EV_IPL,
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(tcg_event->Event, description, desc_len);
|
|
||||||
|
|
||||||
return tcg->HashLogExtendEvent(
|
|
||||||
tcg,
|
|
||||||
0,
|
|
||||||
buffer, buffer_size,
|
|
||||||
tcg_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static EFI_STATUS cc_measure_to_mr_and_ipl_event_log(
|
|
||||||
EFI_CC_MEASUREMENT_PROTOCOL *cc,
|
|
||||||
uint32_t pcrindex,
|
|
||||||
EFI_PHYSICAL_ADDRESS buffer,
|
|
||||||
uint64_t buffer_size,
|
|
||||||
const char16_t *description) {
|
|
||||||
|
|
||||||
_cleanup_free_ EFI_CC_EVENT *event = NULL;
|
|
||||||
uint32_t mr;
|
|
||||||
EFI_STATUS err;
|
|
||||||
size_t desc_len;
|
|
||||||
|
|
||||||
assert(cc);
|
|
||||||
assert(description);
|
|
||||||
|
|
||||||
/* MapPcrToMrIndex service provides callers information on
|
|
||||||
* how the TPM PCR registers are mapped to the CC measurement
|
|
||||||
* registers (MR) in the vendor implementation. */
|
|
||||||
err = cc->MapPcrToMrIndex(cc, pcrindex, &mr);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return EFI_NOT_FOUND;
|
|
||||||
|
|
||||||
desc_len = strsize16(description);
|
|
||||||
event = xmalloc(offsetof(EFI_CC_EVENT, Event) + desc_len);
|
|
||||||
*event = (EFI_CC_EVENT) {
|
|
||||||
.Size = offsetof(EFI_CC_EVENT, Event) + desc_len,
|
|
||||||
.Header.HeaderSize = sizeof(EFI_CC_EVENT_HEADER),
|
|
||||||
.Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION,
|
|
||||||
.Header.MrIndex = mr,
|
|
||||||
.Header.EventType = EV_IPL,
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(event->Event, description, desc_len);
|
|
||||||
|
|
||||||
return cc->HashLogExtendEvent(
|
|
||||||
cc,
|
|
||||||
0,
|
|
||||||
buffer,
|
|
||||||
buffer_size,
|
|
||||||
event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) {
|
|
||||||
EFI_CC_BOOT_SERVICE_CAPABILITY capability = {
|
|
||||||
.Size = sizeof(capability),
|
|
||||||
};
|
|
||||||
EFI_STATUS err;
|
|
||||||
EFI_CC_MEASUREMENT_PROTOCOL *cc;
|
|
||||||
|
|
||||||
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_CC_MEASUREMENT_PROTOCOL), NULL, (void **) &cc);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
err = cc->GetCapability(cc, &capability);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!(capability.SupportedEventLogs & EFI_CC_EVENT_LOG_FORMAT_TCG_2))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
|
|
||||||
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
|
|
||||||
.Size = sizeof(capability),
|
|
||||||
};
|
|
||||||
EFI_STATUS err;
|
|
||||||
EFI_TCG2_PROTOCOL *tcg;
|
|
||||||
|
|
||||||
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
err = tcg->GetCapability(tcg, &capability);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (capability.StructureVersion.Major == 1 &&
|
|
||||||
capability.StructureVersion.Minor == 0) {
|
|
||||||
EFI_TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
|
|
||||||
(EFI_TCG_BOOT_SERVICE_CAPABILITY*) &capability;
|
|
||||||
if (caps_1_0->TPMPresentFlag)
|
|
||||||
return tcg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!capability.TPMPresentFlag)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return tcg;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tpm_present(void) {
|
|
||||||
return tcg2_interface_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
|
|
||||||
EFI_TCG2_PROTOCOL *tpm2;
|
|
||||||
EFI_STATUS err = EFI_SUCCESS;
|
|
||||||
|
|
||||||
assert(ret_measured);
|
|
||||||
|
|
||||||
tpm2 = tcg2_interface_check();
|
|
||||||
if (!tpm2) {
|
|
||||||
*ret_measured = false;
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tpm2_measure_to_pcr_and_ipl_event_log(tpm2, pcrindex, buffer, buffer_size, description);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
*ret_measured = true;
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static EFI_STATUS cc_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
|
|
||||||
EFI_CC_MEASUREMENT_PROTOCOL *cc;
|
|
||||||
EFI_STATUS err = EFI_SUCCESS;
|
|
||||||
|
|
||||||
assert(ret_measured);
|
|
||||||
|
|
||||||
cc = cc_interface_check();
|
|
||||||
if (!cc) {
|
|
||||||
*ret_measured = false;
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cc_measure_to_mr_and_ipl_event_log(cc, pcrindex, buffer, buffer_size, description);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
*ret_measured = true;
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_STATUS tpm_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
|
|
||||||
EFI_STATUS err;
|
|
||||||
bool tpm_ret_measured, cc_ret_measured;
|
|
||||||
|
|
||||||
assert(description || pcrindex == UINT32_MAX);
|
|
||||||
|
|
||||||
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
|
|
||||||
* something, or false if measurement was turned off. */
|
|
||||||
|
|
||||||
if (pcrindex == UINT32_MAX) { /* PCR disabled? */
|
|
||||||
if (ret_measured)
|
|
||||||
*ret_measured = false;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Measure into both CC and TPM if both are available to avoid a problem like CVE-2021-42299 */
|
|
||||||
err = cc_log_event(pcrindex, buffer, buffer_size, description, &cc_ret_measured);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = tcg2_log_ipl_event(pcrindex, buffer, buffer_size, description, &tpm_ret_measured);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (ret_measured)
|
|
||||||
*ret_measured = tpm_ret_measured || cc_ret_measured;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_STATUS tpm_log_tagged_event(
|
|
||||||
uint32_t pcrindex,
|
|
||||||
EFI_PHYSICAL_ADDRESS buffer,
|
|
||||||
size_t buffer_size,
|
|
||||||
uint32_t event_id,
|
|
||||||
const char16_t *description,
|
|
||||||
bool *ret_measured) {
|
|
||||||
|
|
||||||
EFI_TCG2_PROTOCOL *tpm2;
|
|
||||||
EFI_STATUS err;
|
|
||||||
|
|
||||||
assert(description || pcrindex == UINT32_MAX);
|
|
||||||
assert(event_id > 0);
|
|
||||||
|
|
||||||
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
|
|
||||||
* something, or false if measurement was turned off. */
|
|
||||||
|
|
||||||
tpm2 = tcg2_interface_check();
|
|
||||||
if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */
|
|
||||||
if (ret_measured)
|
|
||||||
*ret_measured = false;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tpm2_measure_to_pcr_and_tagged_event_log(tpm2, pcrindex, buffer, buffer_size, event_id, description);
|
|
||||||
if (!err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
*ret_measured = true;
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_STATUS tpm_log_ipl_event_ascii(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char *description, bool *ret_measured) {
|
|
||||||
_cleanup_free_ char16_t *c = NULL;
|
|
||||||
|
|
||||||
if (description)
|
|
||||||
c = xstr8_to_16(description);
|
|
||||||
|
|
||||||
return tpm_log_ipl_event(pcrindex, buffer, buffer_size, c, ret_measured);
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured) {
|
|
||||||
EFI_STATUS err;
|
|
||||||
|
|
||||||
/* Measures a load options string into the TPM2, i.e. the kernel command line */
|
|
||||||
|
|
||||||
err = tpm_log_ipl_event(
|
|
||||||
TPM2_PCR_KERNEL_CONFIG,
|
|
||||||
POINTER_TO_PHYSICAL_ADDRESS(load_options),
|
|
||||||
strsize16(load_options),
|
|
||||||
load_options,
|
|
||||||
ret_measured);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
return log_error_status(
|
|
||||||
err,
|
|
||||||
"Unable to add load options (i.e. kernel command) line measurement to PCR %i: %m",
|
|
||||||
TPM2_PCR_KERNEL_CONFIG);
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,430 +0,0 @@
|
||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
|
|
||||||
efi_config_h_dir = meson.current_build_dir()
|
|
||||||
efi_addon = ''
|
|
||||||
|
|
||||||
libefitest = static_library(
|
|
||||||
'efitest',
|
|
||||||
files(
|
|
||||||
'bcd.c',
|
|
||||||
'efi-string.c',
|
|
||||||
),
|
|
||||||
build_by_default : false,
|
|
||||||
include_directories : [
|
|
||||||
basic_includes,
|
|
||||||
include_directories('.'),
|
|
||||||
],
|
|
||||||
dependencies : userspace)
|
|
||||||
|
|
||||||
efitest_base = {
|
|
||||||
'link_with' : [
|
|
||||||
libefitest,
|
|
||||||
libshared,
|
|
||||||
],
|
|
||||||
}
|
|
||||||
efi_test_template = test_template + efitest_base
|
|
||||||
efi_fuzz_template = fuzz_template + efitest_base
|
|
||||||
|
|
||||||
executables += [
|
|
||||||
efi_test_template + {
|
|
||||||
'sources' : files('test-bcd.c'),
|
|
||||||
'dependencies' : libzstd_cflags,
|
|
||||||
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_ZSTD'],
|
|
||||||
},
|
|
||||||
efi_test_template + {
|
|
||||||
'sources' : files('test-efi-string.c'),
|
|
||||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
|
||||||
},
|
|
||||||
efi_fuzz_template + {
|
|
||||||
'sources' : files('fuzz-bcd.c'),
|
|
||||||
},
|
|
||||||
efi_fuzz_template + {
|
|
||||||
'sources' : files('fuzz-efi-string.c'),
|
|
||||||
},
|
|
||||||
efi_fuzz_template + {
|
|
||||||
'sources' : files('fuzz-efi-osrel.c'),
|
|
||||||
},
|
|
||||||
efi_fuzz_template + {
|
|
||||||
'sources' : files('fuzz-efi-printf.c'),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if conf.get('ENABLE_BOOTLOADER') != 1
|
|
||||||
subdir_done()
|
|
||||||
endif
|
|
||||||
|
|
||||||
efi_conf = configuration_data()
|
|
||||||
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
|
|
||||||
|
|
||||||
foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
|
|
||||||
c = get_option('efi-' + ctype).split(',')
|
|
||||||
efi_conf.set(ctype.underscorify().to_upper(), 'EFI_TEXT_ATTR(@0@, @1@)'.format(
|
|
||||||
'EFI_' + c[0].strip().underscorify().to_upper(),
|
|
||||||
'EFI_' + c[1].strip().underscorify().to_upper()))
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
efi_conf.set_quoted('PROJECT_VERSION', project_major_version)
|
|
||||||
efi_conf.set_quoted('VERSION_TAG', version_tag)
|
|
||||||
efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
|
|
||||||
|
|
||||||
if meson.is_cross_build() and get_option('sbat-distro') == 'auto'
|
|
||||||
warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.')
|
|
||||||
elif get_option('sbat-distro') != ''
|
|
||||||
efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
|
|
||||||
if get_option('sbat-distro-generation') < 1
|
|
||||||
error('SBAT Distro Generation must be a positive integer')
|
|
||||||
endif
|
|
||||||
efi_conf.set('SBAT_DISTRO_GENERATION', get_option('sbat-distro-generation'))
|
|
||||||
foreach sbatvar : [['sbat-distro', 'ID'],
|
|
||||||
['sbat-distro-summary', 'NAME'],
|
|
||||||
['sbat-distro-url', 'BUG_REPORT_URL']]
|
|
||||||
value = get_option(sbatvar[0])
|
|
||||||
if (value == '' or value == 'auto') and not meson.is_cross_build()
|
|
||||||
cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1])
|
|
||||||
value = run_command(sh, '-c', cmd, check: true).stdout().strip()
|
|
||||||
endif
|
|
||||||
if value == ''
|
|
||||||
error('Required @0@ option not set and autodetection failed'.format(sbatvar[0]))
|
|
||||||
endif
|
|
||||||
efi_conf.set_quoted(sbatvar[0].underscorify().to_upper(), value)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
pkgname = get_option('sbat-distro-pkgname')
|
|
||||||
if pkgname == ''
|
|
||||||
pkgname = meson.project_name()
|
|
||||||
endif
|
|
||||||
efi_conf.set_quoted('SBAT_DISTRO_PKGNAME', pkgname)
|
|
||||||
|
|
||||||
pkgver = get_option('sbat-distro-version')
|
|
||||||
if pkgver == ''
|
|
||||||
# This is determined during build, not configuration, so we can't display it yet.
|
|
||||||
efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION')
|
|
||||||
else
|
|
||||||
efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)},
|
|
||||||
section : 'UEFI')
|
|
||||||
|
|
||||||
if efi_conf.get('SBAT_DISTRO', '') != ''
|
|
||||||
summary({
|
|
||||||
'SBAT distro': efi_conf.get('SBAT_DISTRO'),
|
|
||||||
'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'),
|
|
||||||
'SBAT distro version': efi_conf.get('SBAT_DISTRO_VERSION'),
|
|
||||||
'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'),
|
|
||||||
'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')},
|
|
||||||
section : 'UEFI')
|
|
||||||
endif
|
|
||||||
|
|
||||||
configure_file(
|
|
||||||
output : 'efi_config.h',
|
|
||||||
configuration : efi_conf)
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
efi_includes = [
|
|
||||||
build_dir_include,
|
|
||||||
fundamental_include,
|
|
||||||
include_directories('.'),
|
|
||||||
]
|
|
||||||
|
|
||||||
efi_c_args = [
|
|
||||||
'-DSD_BOOT=1',
|
|
||||||
'-ffreestanding',
|
|
||||||
'-fno-strict-aliasing',
|
|
||||||
'-fshort-wchar',
|
|
||||||
'-include', 'efi_config.h',
|
|
||||||
]
|
|
||||||
|
|
||||||
efi_c_args += cc.get_supported_arguments(
|
|
||||||
'-fwide-exec-charset=UCS2',
|
|
||||||
# gcc docs says this is required for ms_abi to work correctly.
|
|
||||||
'-maccumulate-outgoing-args',
|
|
||||||
'-mstack-protector-guard=global',
|
|
||||||
)
|
|
||||||
|
|
||||||
# Debug information has little value in release builds as no normal human being knows
|
|
||||||
# how to attach a debugger to EFI binaries running on real hardware. Anyone who does
|
|
||||||
# certainly has the means to do their own dev build.
|
|
||||||
if get_option('mode') == 'developer' and get_option('debug')
|
|
||||||
efi_c_args += '-DEFI_DEBUG'
|
|
||||||
endif
|
|
||||||
|
|
||||||
efi_c_ld_args = [
|
|
||||||
'-lgcc',
|
|
||||||
'-nostdlib',
|
|
||||||
'-static-pie',
|
|
||||||
'-Wl,--entry=efi_main',
|
|
||||||
'-Wl,--fatal-warnings',
|
|
||||||
|
|
||||||
# These flags should be passed by -static-pie, but for whatever reason the flag translation
|
|
||||||
# is not enabled on all architectures. Not passing `-static` would just allow the linker to
|
|
||||||
# use dynamic libraries, (which we can't/don't use anyway). But if `-pie` is missing and the
|
|
||||||
# gcc build does not default to `-pie` we get a regular (no-pie) binary that will be
|
|
||||||
# rightfully rejected by elf2efi. Note that meson also passes `-pie` to the linker driver,
|
|
||||||
# but it is overridden by our `-static-pie`. We also need to pass these directly to the
|
|
||||||
# linker as `-static`+`-pie` seem to get translated differently.
|
|
||||||
'-Wl,-static,-pie,--no-dynamic-linker,-z,text',
|
|
||||||
|
|
||||||
# EFI has 4KiB pages.
|
|
||||||
'-z', 'common-page-size=4096',
|
|
||||||
'-z', 'max-page-size=4096',
|
|
||||||
|
|
||||||
'-z', 'noexecstack',
|
|
||||||
'-z', 'relro',
|
|
||||||
'-z', 'separate-code',
|
|
||||||
]
|
|
||||||
|
|
||||||
efi_c_ld_args += cc.get_supported_link_arguments(
|
|
||||||
# binutils >= 2.38
|
|
||||||
'-Wl,-z,nopack-relative-relocs',
|
|
||||||
)
|
|
||||||
|
|
||||||
# efi_c_args is explicitly passed to targets so that they can override distro-provided flags
|
|
||||||
# that should not be used for EFI binaries.
|
|
||||||
efi_disabled_c_args = cc.get_supported_arguments(
|
|
||||||
'-fcf-protection=none',
|
|
||||||
'-fno-asynchronous-unwind-tables',
|
|
||||||
'-fno-exceptions',
|
|
||||||
'-fno-unwind-tables',
|
|
||||||
)
|
|
||||||
efi_override_options = [
|
|
||||||
'b_coverage=false',
|
|
||||||
'b_pgo=off',
|
|
||||||
]
|
|
||||||
|
|
||||||
if get_option('b_sanitize') == 'undefined'
|
|
||||||
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize-link-runtime')
|
|
||||||
else
|
|
||||||
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize=all')
|
|
||||||
efi_override_options += 'b_sanitize=none'
|
|
||||||
endif
|
|
||||||
|
|
||||||
efi_c_args += efi_disabled_c_args
|
|
||||||
efi_c_ld_args += efi_disabled_c_args
|
|
||||||
|
|
||||||
if cc.get_id() == 'clang'
|
|
||||||
# clang is too picky sometimes.
|
|
||||||
efi_c_args += '-Wno-unused-command-line-argument'
|
|
||||||
efi_c_ld_args += '-Wno-unused-command-line-argument'
|
|
||||||
endif
|
|
||||||
|
|
||||||
efi_arch_c_args = {
|
|
||||||
'aarch64' : ['-mgeneral-regs-only'],
|
|
||||||
'arm' : ['-mgeneral-regs-only'],
|
|
||||||
# Until -mgeneral-regs-only is supported in LoongArch, use the following option instead:
|
|
||||||
'loongarch64' : ['-mno-lsx', '-mno-lasx'],
|
|
||||||
# Pass -m64/32 explicitly to make building on x32 work.
|
|
||||||
'x86_64' : ['-m64', '-march=x86-64', '-mno-red-zone', '-mgeneral-regs-only'],
|
|
||||||
'x86' : ['-m32', '-march=i686', '-mgeneral-regs-only', '-malign-double'],
|
|
||||||
}
|
|
||||||
efi_arch_c_ld_args = {
|
|
||||||
# libgcc is not compiled with -fshort-wchar, but it does not use it anyways,
|
|
||||||
# so it's fine to link against it.
|
|
||||||
'arm' : cc.get_supported_link_arguments('-Wl,--no-wchar-size-warning'),
|
|
||||||
'x86_64' : ['-m64'],
|
|
||||||
'x86' : ['-m32'],
|
|
||||||
}
|
|
||||||
|
|
||||||
linker_sanity_code = 'void a(void) {}; void _start(void) { a(); }'
|
|
||||||
linker_sanity_args = ['-nostdlib', '-Wl,--fatal-warnings']
|
|
||||||
if not cc.links(linker_sanity_code,
|
|
||||||
name : 'linker supports -static-pie',
|
|
||||||
args : [linker_sanity_args, '-static-pie'])
|
|
||||||
error('Linker does not support -static-pie.')
|
|
||||||
endif
|
|
||||||
|
|
||||||
# https://github.com/llvm/llvm-project/issues/67152
|
|
||||||
if not cc.links(linker_sanity_code,
|
|
||||||
name : 'linker supports LTO with -nostdlib',
|
|
||||||
args : [linker_sanity_args, '-flto'])
|
|
||||||
efi_c_args += '-fno-lto'
|
|
||||||
efi_c_ld_args += '-fno-lto'
|
|
||||||
endif
|
|
||||||
|
|
||||||
# https://github.com/llvm/llvm-project/issues/61101
|
|
||||||
if efi_cpu_family_alt == 'x86' and not cc.links(linker_sanity_code,
|
|
||||||
name : 'linker supports LTO with -nostdlib (x86)',
|
|
||||||
args : [linker_sanity_args, '-flto', '-m32'])
|
|
||||||
efi_arch_c_args += { 'x86' : efi_arch_c_args['x86'] + '-fno-lto' }
|
|
||||||
efi_arch_c_ld_args += { 'x86' : efi_arch_c_ld_args['x86'] + '-fno-lto' }
|
|
||||||
endif
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
libefi_sources = files(
|
|
||||||
'chid.c',
|
|
||||||
'console.c',
|
|
||||||
'device-path-util.c',
|
|
||||||
'devicetree.c',
|
|
||||||
'drivers.c',
|
|
||||||
'efi-string.c',
|
|
||||||
'efivars.c',
|
|
||||||
'export-vars.c',
|
|
||||||
'graphics.c',
|
|
||||||
'initrd.c',
|
|
||||||
'log.c',
|
|
||||||
'measure.c',
|
|
||||||
'part-discovery.c',
|
|
||||||
'pe.c',
|
|
||||||
'random-seed.c',
|
|
||||||
'secure-boot.c',
|
|
||||||
'shim.c',
|
|
||||||
'smbios.c',
|
|
||||||
'ticks.c',
|
|
||||||
'util.c',
|
|
||||||
'vmm.c',
|
|
||||||
)
|
|
||||||
|
|
||||||
systemd_boot_sources = files(
|
|
||||||
'boot.c',
|
|
||||||
)
|
|
||||||
|
|
||||||
stub_sources = files(
|
|
||||||
'cpio.c',
|
|
||||||
'linux.c',
|
|
||||||
'splash.c',
|
|
||||||
'stub.c',
|
|
||||||
)
|
|
||||||
|
|
||||||
addon_sources = files(
|
|
||||||
'addon.c',
|
|
||||||
)
|
|
||||||
|
|
||||||
if get_option('b_sanitize') == 'undefined'
|
|
||||||
libefi_sources += files('ubsan.c')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if host_machine.cpu_family() in ['x86', 'x86_64']
|
|
||||||
stub_sources += files('linux_x86.c')
|
|
||||||
endif
|
|
||||||
|
|
||||||
# BCD parser only makes sense on arches that Windows supports.
|
|
||||||
if host_machine.cpu_family() in ['aarch64', 'arm', 'x86_64', 'x86']
|
|
||||||
systemd_boot_sources += files('bcd.c')
|
|
||||||
endif
|
|
||||||
|
|
||||||
boot_targets = []
|
|
||||||
efi_elf_binaries = []
|
|
||||||
efi_archspecs = [
|
|
||||||
{
|
|
||||||
'arch' : efi_arch,
|
|
||||||
'c_args' : [
|
|
||||||
efi_c_args,
|
|
||||||
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch + '"',
|
|
||||||
efi_arch_c_args.get(host_machine.cpu_family(), []),
|
|
||||||
],
|
|
||||||
'link_args' : [
|
|
||||||
efi_c_ld_args,
|
|
||||||
efi_arch_c_ld_args.get(host_machine.cpu_family(), []),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
if efi_arch_alt != ''
|
|
||||||
efi_archspecs += {
|
|
||||||
'arch' : efi_arch_alt,
|
|
||||||
'c_args' : [
|
|
||||||
efi_c_args,
|
|
||||||
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch_alt + '"',
|
|
||||||
efi_arch_c_args.get(efi_cpu_family_alt, []),
|
|
||||||
],
|
|
||||||
'link_args' : [
|
|
||||||
efi_c_ld_args,
|
|
||||||
efi_arch_c_ld_args.get(efi_cpu_family_alt, []),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
endif
|
|
||||||
|
|
||||||
foreach archspec : efi_archspecs
|
|
||||||
libefi = static_library(
|
|
||||||
'efi' + archspec['arch'],
|
|
||||||
fundamental_sources,
|
|
||||||
libefi_sources,
|
|
||||||
version_h,
|
|
||||||
include_directories : efi_includes,
|
|
||||||
c_args : archspec['c_args'],
|
|
||||||
gnu_symbol_visibility : 'hidden',
|
|
||||||
override_options : efi_override_options,
|
|
||||||
pic : true)
|
|
||||||
|
|
||||||
kwargs = {
|
|
||||||
'include_directories' : efi_includes,
|
|
||||||
'c_args' : archspec['c_args'],
|
|
||||||
'link_args' : archspec['link_args'],
|
|
||||||
'gnu_symbol_visibility' : 'hidden',
|
|
||||||
'override_options' : efi_override_options,
|
|
||||||
'pie' : true,
|
|
||||||
}
|
|
||||||
|
|
||||||
efi_elf_binaries += executable(
|
|
||||||
'systemd-boot' + archspec['arch'],
|
|
||||||
sources : [systemd_boot_sources, version_h],
|
|
||||||
link_with : libefi,
|
|
||||||
name_suffix : 'elf',
|
|
||||||
kwargs : kwargs)
|
|
||||||
|
|
||||||
efi_elf_binaries += executable(
|
|
||||||
'linux' + archspec['arch'],
|
|
||||||
sources : [stub_sources, version_h],
|
|
||||||
link_with : libefi,
|
|
||||||
name_suffix : 'elf.stub',
|
|
||||||
kwargs : kwargs)
|
|
||||||
|
|
||||||
efi_elf_binaries += executable(
|
|
||||||
'addon' + archspec['arch'],
|
|
||||||
sources : [addon_sources, version_h],
|
|
||||||
name_suffix : 'elf.stub',
|
|
||||||
kwargs : kwargs)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
foreach efi_elf_binary : efi_elf_binaries
|
|
||||||
name = efi_elf_binary.name()
|
|
||||||
name += name.startswith('systemd-boot') ? '.efi' : '.efi.stub'
|
|
||||||
|
|
||||||
# For the addon, given it's empty, we need to explicitly reserve space in the header to account for
|
|
||||||
# the sections that ukify will add.
|
|
||||||
if name.startswith('linux')
|
|
||||||
minimum_sections = get_option('efi-stub-extra-sections')
|
|
||||||
elif name.startswith('addon')
|
|
||||||
minimum_sections = get_option('efi-addon-extra-sections')
|
|
||||||
else
|
|
||||||
minimum_sections = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
exe = custom_target(
|
|
||||||
name,
|
|
||||||
output : name,
|
|
||||||
input : efi_elf_binary,
|
|
||||||
install : true,
|
|
||||||
install_dir : bootlibdir,
|
|
||||||
install_tag : 'systemd-boot',
|
|
||||||
command : [
|
|
||||||
elf2efi_py,
|
|
||||||
'--version-major=' + project_major_version,
|
|
||||||
'--version-minor=' + project_minor_version,
|
|
||||||
'--efi-major=1',
|
|
||||||
'--efi-minor=1',
|
|
||||||
'--subsystem=10',
|
|
||||||
'--minimum-sections=@0@'.format(minimum_sections),
|
|
||||||
'--copy-sections=.sbat,.sdmagic,.osrel',
|
|
||||||
'@INPUT@',
|
|
||||||
'@OUTPUT@',
|
|
||||||
])
|
|
||||||
boot_targets += exe
|
|
||||||
if name.startswith('linux')
|
|
||||||
boot_stubs += exe
|
|
||||||
endif
|
|
||||||
|
|
||||||
# This is supposed to match exactly one time
|
|
||||||
if name == 'addon@0@.efi.stub'.format(efi_arch)
|
|
||||||
efi_addon = exe.full_path()
|
|
||||||
endif
|
|
||||||
|
|
||||||
test('check-alignment-@0@'.format(name),
|
|
||||||
check_efi_alignment_py,
|
|
||||||
args : exe.full_path(),
|
|
||||||
suite : 'efi')
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
alias_target('systemd-boot', boot_targets)
|
|
1349
src/boot/measure.c
1349
src/boot/measure.c
File diff suppressed because it is too large
Load Diff
|
@ -1,77 +1,430 @@
|
||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
bootctl_sources = files(
|
efi_config_h_dir = meson.current_build_dir()
|
||||||
'bootctl-install.c',
|
efi_addon = ''
|
||||||
'bootctl-random-seed.c',
|
|
||||||
'bootctl-reboot-to-firmware.c',
|
|
||||||
'bootctl-set-efivar.c',
|
|
||||||
'bootctl-status.c',
|
|
||||||
'bootctl-systemd-efi-options.c',
|
|
||||||
'bootctl-uki.c',
|
|
||||||
'bootctl-util.c',
|
|
||||||
'bootctl.c',
|
|
||||||
)
|
|
||||||
|
|
||||||
if get_option('link-boot-shared')
|
libefitest = static_library(
|
||||||
boot_link_with = [libshared]
|
'efitest',
|
||||||
else
|
files(
|
||||||
boot_link_with = [
|
'bcd.c',
|
||||||
libshared_static,
|
'efi-string.c',
|
||||||
libsystemd_static,
|
),
|
||||||
]
|
build_by_default : false,
|
||||||
endif
|
include_directories : [
|
||||||
|
basic_includes,
|
||||||
|
include_directories('.'),
|
||||||
|
],
|
||||||
|
dependencies : userspace)
|
||||||
|
|
||||||
|
efitest_base = {
|
||||||
|
'link_with' : [
|
||||||
|
libefitest,
|
||||||
|
libshared,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
efi_test_template = test_template + efitest_base
|
||||||
|
efi_fuzz_template = fuzz_template + efitest_base
|
||||||
|
|
||||||
executables += [
|
executables += [
|
||||||
executable_template + {
|
efi_test_template + {
|
||||||
'name' : 'bootctl',
|
'sources' : files('test-bcd.c'),
|
||||||
'public' : true,
|
'dependencies' : libzstd_cflags,
|
||||||
'conditions' : [
|
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_ZSTD'],
|
||||||
'HAVE_BLKID',
|
|
||||||
],
|
|
||||||
'sources' : bootctl_sources,
|
|
||||||
'link_with' : boot_link_with,
|
|
||||||
'dependencies' : [libblkid, libopenssl],
|
|
||||||
},
|
},
|
||||||
libexec_template + {
|
efi_test_template + {
|
||||||
'name' : 'systemd-bless-boot',
|
'sources' : files('test-efi-string.c'),
|
||||||
'public' : true,
|
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||||
'conditions' : [
|
|
||||||
'HAVE_BLKID',
|
|
||||||
'ENABLE_BOOTLOADER',
|
|
||||||
],
|
|
||||||
'sources' : files('bless-boot.c'),
|
|
||||||
'link_with' : boot_link_with,
|
|
||||||
'dependencies' : libblkid,
|
|
||||||
},
|
},
|
||||||
generator_template + {
|
efi_fuzz_template + {
|
||||||
'name' : 'systemd-bless-boot-generator',
|
'sources' : files('fuzz-bcd.c'),
|
||||||
'conditions' : [
|
|
||||||
'HAVE_BLKID',
|
|
||||||
'ENABLE_BOOTLOADER',
|
|
||||||
],
|
|
||||||
'sources' : files('bless-boot-generator.c'),
|
|
||||||
'link_with' : boot_link_with,
|
|
||||||
},
|
},
|
||||||
libexec_template + {
|
efi_fuzz_template + {
|
||||||
'name' : 'systemd-measure',
|
'sources' : files('fuzz-efi-string.c'),
|
||||||
'conditions' : [
|
|
||||||
'HAVE_BLKID',
|
|
||||||
'HAVE_OPENSSL',
|
|
||||||
'HAVE_TPM2',
|
|
||||||
],
|
|
||||||
'sources' : files('measure.c'),
|
|
||||||
'dependencies' : libopenssl,
|
|
||||||
},
|
},
|
||||||
libexec_template + {
|
efi_fuzz_template + {
|
||||||
'name' : 'systemd-sbsign',
|
'sources' : files('fuzz-efi-osrel.c'),
|
||||||
'conditions' : [
|
|
||||||
'HAVE_OPENSSL',
|
|
||||||
],
|
|
||||||
'sources' : files('sbsign.c'),
|
|
||||||
'dependencies' : libopenssl,
|
|
||||||
},
|
},
|
||||||
libexec_template + {
|
efi_fuzz_template + {
|
||||||
'name' : 'systemd-boot-check-no-failures',
|
'sources' : files('fuzz-efi-printf.c'),
|
||||||
'sources' : files('boot-check-no-failures.c'),
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if conf.get('ENABLE_BOOTLOADER') != 1
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
efi_conf = configuration_data()
|
||||||
|
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
|
||||||
|
|
||||||
|
foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
|
||||||
|
c = get_option('efi-' + ctype).split(',')
|
||||||
|
efi_conf.set(ctype.underscorify().to_upper(), 'EFI_TEXT_ATTR(@0@, @1@)'.format(
|
||||||
|
'EFI_' + c[0].strip().underscorify().to_upper(),
|
||||||
|
'EFI_' + c[1].strip().underscorify().to_upper()))
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
efi_conf.set_quoted('PROJECT_VERSION', project_major_version)
|
||||||
|
efi_conf.set_quoted('VERSION_TAG', version_tag)
|
||||||
|
efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
|
||||||
|
|
||||||
|
if meson.is_cross_build() and get_option('sbat-distro') == 'auto'
|
||||||
|
warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.')
|
||||||
|
elif get_option('sbat-distro') != ''
|
||||||
|
efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
|
||||||
|
if get_option('sbat-distro-generation') < 1
|
||||||
|
error('SBAT Distro Generation must be a positive integer')
|
||||||
|
endif
|
||||||
|
efi_conf.set('SBAT_DISTRO_GENERATION', get_option('sbat-distro-generation'))
|
||||||
|
foreach sbatvar : [['sbat-distro', 'ID'],
|
||||||
|
['sbat-distro-summary', 'NAME'],
|
||||||
|
['sbat-distro-url', 'BUG_REPORT_URL']]
|
||||||
|
value = get_option(sbatvar[0])
|
||||||
|
if (value == '' or value == 'auto') and not meson.is_cross_build()
|
||||||
|
cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1])
|
||||||
|
value = run_command(sh, '-c', cmd, check: true).stdout().strip()
|
||||||
|
endif
|
||||||
|
if value == ''
|
||||||
|
error('Required @0@ option not set and autodetection failed'.format(sbatvar[0]))
|
||||||
|
endif
|
||||||
|
efi_conf.set_quoted(sbatvar[0].underscorify().to_upper(), value)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
pkgname = get_option('sbat-distro-pkgname')
|
||||||
|
if pkgname == ''
|
||||||
|
pkgname = meson.project_name()
|
||||||
|
endif
|
||||||
|
efi_conf.set_quoted('SBAT_DISTRO_PKGNAME', pkgname)
|
||||||
|
|
||||||
|
pkgver = get_option('sbat-distro-version')
|
||||||
|
if pkgver == ''
|
||||||
|
# This is determined during build, not configuration, so we can't display it yet.
|
||||||
|
efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION')
|
||||||
|
else
|
||||||
|
efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)},
|
||||||
|
section : 'UEFI')
|
||||||
|
|
||||||
|
if efi_conf.get('SBAT_DISTRO', '') != ''
|
||||||
|
summary({
|
||||||
|
'SBAT distro': efi_conf.get('SBAT_DISTRO'),
|
||||||
|
'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'),
|
||||||
|
'SBAT distro version': efi_conf.get('SBAT_DISTRO_VERSION'),
|
||||||
|
'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'),
|
||||||
|
'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')},
|
||||||
|
section : 'UEFI')
|
||||||
|
endif
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
output : 'efi_config.h',
|
||||||
|
configuration : efi_conf)
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
efi_includes = [
|
||||||
|
build_dir_include,
|
||||||
|
fundamental_include,
|
||||||
|
include_directories('.'),
|
||||||
|
]
|
||||||
|
|
||||||
|
efi_c_args = [
|
||||||
|
'-DSD_BOOT=1',
|
||||||
|
'-ffreestanding',
|
||||||
|
'-fno-strict-aliasing',
|
||||||
|
'-fshort-wchar',
|
||||||
|
'-include', 'efi_config.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
efi_c_args += cc.get_supported_arguments(
|
||||||
|
'-fwide-exec-charset=UCS2',
|
||||||
|
# gcc docs says this is required for ms_abi to work correctly.
|
||||||
|
'-maccumulate-outgoing-args',
|
||||||
|
'-mstack-protector-guard=global',
|
||||||
|
)
|
||||||
|
|
||||||
|
# Debug information has little value in release builds as no normal human being knows
|
||||||
|
# how to attach a debugger to EFI binaries running on real hardware. Anyone who does
|
||||||
|
# certainly has the means to do their own dev build.
|
||||||
|
if get_option('mode') == 'developer' and get_option('debug')
|
||||||
|
efi_c_args += '-DEFI_DEBUG'
|
||||||
|
endif
|
||||||
|
|
||||||
|
efi_c_ld_args = [
|
||||||
|
'-lgcc',
|
||||||
|
'-nostdlib',
|
||||||
|
'-static-pie',
|
||||||
|
'-Wl,--entry=efi_main',
|
||||||
|
'-Wl,--fatal-warnings',
|
||||||
|
|
||||||
|
# These flags should be passed by -static-pie, but for whatever reason the flag translation
|
||||||
|
# is not enabled on all architectures. Not passing `-static` would just allow the linker to
|
||||||
|
# use dynamic libraries, (which we can't/don't use anyway). But if `-pie` is missing and the
|
||||||
|
# gcc build does not default to `-pie` we get a regular (no-pie) binary that will be
|
||||||
|
# rightfully rejected by elf2efi. Note that meson also passes `-pie` to the linker driver,
|
||||||
|
# but it is overridden by our `-static-pie`. We also need to pass these directly to the
|
||||||
|
# linker as `-static`+`-pie` seem to get translated differently.
|
||||||
|
'-Wl,-static,-pie,--no-dynamic-linker,-z,text',
|
||||||
|
|
||||||
|
# EFI has 4KiB pages.
|
||||||
|
'-z', 'common-page-size=4096',
|
||||||
|
'-z', 'max-page-size=4096',
|
||||||
|
|
||||||
|
'-z', 'noexecstack',
|
||||||
|
'-z', 'relro',
|
||||||
|
'-z', 'separate-code',
|
||||||
|
]
|
||||||
|
|
||||||
|
efi_c_ld_args += cc.get_supported_link_arguments(
|
||||||
|
# binutils >= 2.38
|
||||||
|
'-Wl,-z,nopack-relative-relocs',
|
||||||
|
)
|
||||||
|
|
||||||
|
# efi_c_args is explicitly passed to targets so that they can override distro-provided flags
|
||||||
|
# that should not be used for EFI binaries.
|
||||||
|
efi_disabled_c_args = cc.get_supported_arguments(
|
||||||
|
'-fcf-protection=none',
|
||||||
|
'-fno-asynchronous-unwind-tables',
|
||||||
|
'-fno-exceptions',
|
||||||
|
'-fno-unwind-tables',
|
||||||
|
)
|
||||||
|
efi_override_options = [
|
||||||
|
'b_coverage=false',
|
||||||
|
'b_pgo=off',
|
||||||
|
]
|
||||||
|
|
||||||
|
if get_option('b_sanitize') == 'undefined'
|
||||||
|
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize-link-runtime')
|
||||||
|
else
|
||||||
|
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize=all')
|
||||||
|
efi_override_options += 'b_sanitize=none'
|
||||||
|
endif
|
||||||
|
|
||||||
|
efi_c_args += efi_disabled_c_args
|
||||||
|
efi_c_ld_args += efi_disabled_c_args
|
||||||
|
|
||||||
|
if cc.get_id() == 'clang'
|
||||||
|
# clang is too picky sometimes.
|
||||||
|
efi_c_args += '-Wno-unused-command-line-argument'
|
||||||
|
efi_c_ld_args += '-Wno-unused-command-line-argument'
|
||||||
|
endif
|
||||||
|
|
||||||
|
efi_arch_c_args = {
|
||||||
|
'aarch64' : ['-mgeneral-regs-only'],
|
||||||
|
'arm' : ['-mgeneral-regs-only'],
|
||||||
|
# Until -mgeneral-regs-only is supported in LoongArch, use the following option instead:
|
||||||
|
'loongarch64' : ['-mno-lsx', '-mno-lasx'],
|
||||||
|
# Pass -m64/32 explicitly to make building on x32 work.
|
||||||
|
'x86_64' : ['-m64', '-march=x86-64', '-mno-red-zone', '-mgeneral-regs-only'],
|
||||||
|
'x86' : ['-m32', '-march=i686', '-mgeneral-regs-only', '-malign-double'],
|
||||||
|
}
|
||||||
|
efi_arch_c_ld_args = {
|
||||||
|
# libgcc is not compiled with -fshort-wchar, but it does not use it anyways,
|
||||||
|
# so it's fine to link against it.
|
||||||
|
'arm' : cc.get_supported_link_arguments('-Wl,--no-wchar-size-warning'),
|
||||||
|
'x86_64' : ['-m64'],
|
||||||
|
'x86' : ['-m32'],
|
||||||
|
}
|
||||||
|
|
||||||
|
linker_sanity_code = 'void a(void) {}; void _start(void) { a(); }'
|
||||||
|
linker_sanity_args = ['-nostdlib', '-Wl,--fatal-warnings']
|
||||||
|
if not cc.links(linker_sanity_code,
|
||||||
|
name : 'linker supports -static-pie',
|
||||||
|
args : [linker_sanity_args, '-static-pie'])
|
||||||
|
error('Linker does not support -static-pie.')
|
||||||
|
endif
|
||||||
|
|
||||||
|
# https://github.com/llvm/llvm-project/issues/67152
|
||||||
|
if not cc.links(linker_sanity_code,
|
||||||
|
name : 'linker supports LTO with -nostdlib',
|
||||||
|
args : [linker_sanity_args, '-flto'])
|
||||||
|
efi_c_args += '-fno-lto'
|
||||||
|
efi_c_ld_args += '-fno-lto'
|
||||||
|
endif
|
||||||
|
|
||||||
|
# https://github.com/llvm/llvm-project/issues/61101
|
||||||
|
if efi_cpu_family_alt == 'x86' and not cc.links(linker_sanity_code,
|
||||||
|
name : 'linker supports LTO with -nostdlib (x86)',
|
||||||
|
args : [linker_sanity_args, '-flto', '-m32'])
|
||||||
|
efi_arch_c_args += { 'x86' : efi_arch_c_args['x86'] + '-fno-lto' }
|
||||||
|
efi_arch_c_ld_args += { 'x86' : efi_arch_c_ld_args['x86'] + '-fno-lto' }
|
||||||
|
endif
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
libefi_sources = files(
|
||||||
|
'chid.c',
|
||||||
|
'console.c',
|
||||||
|
'device-path-util.c',
|
||||||
|
'devicetree.c',
|
||||||
|
'drivers.c',
|
||||||
|
'efi-string.c',
|
||||||
|
'efivars.c',
|
||||||
|
'export-vars.c',
|
||||||
|
'graphics.c',
|
||||||
|
'initrd.c',
|
||||||
|
'log.c',
|
||||||
|
'measure.c',
|
||||||
|
'part-discovery.c',
|
||||||
|
'pe.c',
|
||||||
|
'random-seed.c',
|
||||||
|
'secure-boot.c',
|
||||||
|
'shim.c',
|
||||||
|
'smbios.c',
|
||||||
|
'ticks.c',
|
||||||
|
'util.c',
|
||||||
|
'vmm.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
systemd_boot_sources = files(
|
||||||
|
'boot.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
stub_sources = files(
|
||||||
|
'cpio.c',
|
||||||
|
'linux.c',
|
||||||
|
'splash.c',
|
||||||
|
'stub.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
addon_sources = files(
|
||||||
|
'addon.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
if get_option('b_sanitize') == 'undefined'
|
||||||
|
libefi_sources += files('ubsan.c')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if host_machine.cpu_family() in ['x86', 'x86_64']
|
||||||
|
stub_sources += files('linux_x86.c')
|
||||||
|
endif
|
||||||
|
|
||||||
|
# BCD parser only makes sense on arches that Windows supports.
|
||||||
|
if host_machine.cpu_family() in ['aarch64', 'arm', 'x86_64', 'x86']
|
||||||
|
systemd_boot_sources += files('bcd.c')
|
||||||
|
endif
|
||||||
|
|
||||||
|
boot_targets = []
|
||||||
|
efi_elf_binaries = []
|
||||||
|
efi_archspecs = [
|
||||||
|
{
|
||||||
|
'arch' : efi_arch,
|
||||||
|
'c_args' : [
|
||||||
|
efi_c_args,
|
||||||
|
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch + '"',
|
||||||
|
efi_arch_c_args.get(host_machine.cpu_family(), []),
|
||||||
|
],
|
||||||
|
'link_args' : [
|
||||||
|
efi_c_ld_args,
|
||||||
|
efi_arch_c_ld_args.get(host_machine.cpu_family(), []),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
if efi_arch_alt != ''
|
||||||
|
efi_archspecs += {
|
||||||
|
'arch' : efi_arch_alt,
|
||||||
|
'c_args' : [
|
||||||
|
efi_c_args,
|
||||||
|
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch_alt + '"',
|
||||||
|
efi_arch_c_args.get(efi_cpu_family_alt, []),
|
||||||
|
],
|
||||||
|
'link_args' : [
|
||||||
|
efi_c_ld_args,
|
||||||
|
efi_arch_c_ld_args.get(efi_cpu_family_alt, []),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
|
||||||
|
foreach archspec : efi_archspecs
|
||||||
|
libefi = static_library(
|
||||||
|
'efi' + archspec['arch'],
|
||||||
|
fundamental_sources,
|
||||||
|
libefi_sources,
|
||||||
|
version_h,
|
||||||
|
include_directories : efi_includes,
|
||||||
|
c_args : archspec['c_args'],
|
||||||
|
gnu_symbol_visibility : 'hidden',
|
||||||
|
override_options : efi_override_options,
|
||||||
|
pic : true)
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
'include_directories' : efi_includes,
|
||||||
|
'c_args' : archspec['c_args'],
|
||||||
|
'link_args' : archspec['link_args'],
|
||||||
|
'gnu_symbol_visibility' : 'hidden',
|
||||||
|
'override_options' : efi_override_options,
|
||||||
|
'pie' : true,
|
||||||
|
}
|
||||||
|
|
||||||
|
efi_elf_binaries += executable(
|
||||||
|
'systemd-boot' + archspec['arch'],
|
||||||
|
sources : [systemd_boot_sources, version_h],
|
||||||
|
link_with : libefi,
|
||||||
|
name_suffix : 'elf',
|
||||||
|
kwargs : kwargs)
|
||||||
|
|
||||||
|
efi_elf_binaries += executable(
|
||||||
|
'linux' + archspec['arch'],
|
||||||
|
sources : [stub_sources, version_h],
|
||||||
|
link_with : libefi,
|
||||||
|
name_suffix : 'elf.stub',
|
||||||
|
kwargs : kwargs)
|
||||||
|
|
||||||
|
efi_elf_binaries += executable(
|
||||||
|
'addon' + archspec['arch'],
|
||||||
|
sources : [addon_sources, version_h],
|
||||||
|
name_suffix : 'elf.stub',
|
||||||
|
kwargs : kwargs)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
foreach efi_elf_binary : efi_elf_binaries
|
||||||
|
name = efi_elf_binary.name()
|
||||||
|
name += name.startswith('systemd-boot') ? '.efi' : '.efi.stub'
|
||||||
|
|
||||||
|
# For the addon, given it's empty, we need to explicitly reserve space in the header to account for
|
||||||
|
# the sections that ukify will add.
|
||||||
|
if name.startswith('linux')
|
||||||
|
minimum_sections = get_option('efi-stub-extra-sections')
|
||||||
|
elif name.startswith('addon')
|
||||||
|
minimum_sections = get_option('efi-addon-extra-sections')
|
||||||
|
else
|
||||||
|
minimum_sections = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe = custom_target(
|
||||||
|
name,
|
||||||
|
output : name,
|
||||||
|
input : efi_elf_binary,
|
||||||
|
install : true,
|
||||||
|
install_dir : bootlibdir,
|
||||||
|
install_tag : 'systemd-boot',
|
||||||
|
command : [
|
||||||
|
elf2efi_py,
|
||||||
|
'--version-major=' + project_major_version,
|
||||||
|
'--version-minor=' + project_minor_version,
|
||||||
|
'--efi-major=1',
|
||||||
|
'--efi-minor=1',
|
||||||
|
'--subsystem=10',
|
||||||
|
'--minimum-sections=@0@'.format(minimum_sections),
|
||||||
|
'--copy-sections=.sbat,.sdmagic,.osrel',
|
||||||
|
'@INPUT@',
|
||||||
|
'@OUTPUT@',
|
||||||
|
])
|
||||||
|
boot_targets += exe
|
||||||
|
if name.startswith('linux')
|
||||||
|
boot_stubs += exe
|
||||||
|
endif
|
||||||
|
|
||||||
|
# This is supposed to match exactly one time
|
||||||
|
if name == 'addon@0@.efi.stub'.format(efi_arch)
|
||||||
|
efi_addon = exe.full_path()
|
||||||
|
endif
|
||||||
|
|
||||||
|
test('check-alignment-@0@'.format(name),
|
||||||
|
check_efi_alignment_py,
|
||||||
|
args : exe.full_path(),
|
||||||
|
suite : 'efi')
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
alias_target('systemd-boot', boot_targets)
|
||||||
|
|
|
@ -956,10 +956,26 @@ int verb_install(int argc, char *argv[], void *userdata) {
|
||||||
graceful = !install && arg_graceful; /* support graceful mode for updates */
|
graceful = !install && arg_graceful; /* support graceful mode for updates */
|
||||||
|
|
||||||
if (arg_secure_boot_auto_enroll) {
|
if (arg_secure_boot_auto_enroll) {
|
||||||
r = openssl_load_x509_certificate(arg_certificate, &certificate);
|
if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
|
||||||
|
r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = openssl_load_x509_certificate(
|
||||||
|
arg_certificate_source_type,
|
||||||
|
arg_certificate_source,
|
||||||
|
arg_certificate,
|
||||||
|
&certificate);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
|
return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
|
||||||
|
|
||||||
|
if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
|
||||||
|
r = parse_path_argument(arg_private_key, /* suppress_root= */ false, &arg_private_key);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse private key path %s: %m", arg_private_key);
|
||||||
|
}
|
||||||
|
|
||||||
r = openssl_load_private_key(
|
r = openssl_load_private_key(
|
||||||
arg_private_key_source_type,
|
arg_private_key_source_type,
|
||||||
arg_private_key_source,
|
arg_private_key_source,
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue