Compare commits

...

20 Commits

Author SHA1 Message Date
Lennart Poettering 6fa44d08e8
Merge c6c73d561a into b480a4c15e 2024-11-08 02:38:54 -08:00
Lennart Poettering b480a4c15e update TODO 2024-11-08 10:10:11 +01:00
Lennart Poettering af3baf174a fs-util: add comment about XO_NOCOW 2024-11-08 09:21:25 +01:00
Ryan Wilson d8091e1281 Fix PrivatePIDs=yes integration test for kernels with no /proc/scsi 2024-11-08 13:38:35 +09:00
Lennart Poettering 0df42ebcd6 sd-varlink: allow that method handles call sd_varlink_close()
It's fine if a method handler closes the connection, deal with it
gracefully.
2024-11-07 22:30:42 +01:00
Daan De Meyer 20c03ed72b
tree-wide: Introduce --certificate-source= option (#35057)
This allows loading the X.509 certificate from an OpenSSL provider
instead of a file system path. This allows loading certficates directly
from hardware tokens instead of having to export them to a file on
disk first.










































<!-- devel-freezer =
{"comment-id":"2460915782","freezing-tag":"v257-rc1"} -->
2024-11-07 21:51:00 +01:00
Daan De Meyer 64cc7ba517 ukify: Introduce --certificate-provider= option
This translates to --certificate-source=provider:<provider> for
signing tools invoked by ukify.
2024-11-07 20:33:08 +01:00
Daan De Meyer c4bc0fd6de measure: Add pcrpkey verb
This verb writes a public key to stdout extracted from either a public key
path, from a certificate (path or provider) or from a private key (path,
engine, provider). We'll use this in ukify to get rid of the use of the
python cryptography module to convert a private key or certificate to a
public key.
2024-11-07 20:33:08 +01:00
Daan De Meyer a1d46e3078 tree-wide: Introduce --certificate-source= option
This allows loading the X.509 certificate from an OpenSSL provider
instead of a file system path. This allows loading certficates directly
from hardware tokens instead of having to export them to a file on
disk first.
2024-11-07 20:30:47 +01:00
Daan De Meyer 5619a61829 openssl-util: Set expected object type to private keys
Configures the store to only try to fetch private keys and nothing
else.
2024-11-07 20:24:59 +01:00
Daan De Meyer 4047b99c00 bootctl: Validate private key path 2024-11-07 20:24:59 +01:00
Daan De Meyer 5cca978dae mkosi: Add pytest to tools 2024-11-07 20:24:59 +01:00
Yu Watanabe dd2bf3141b
Split and rename src/boot (#35068) 2024-11-08 04:13:45 +09:00
Vursc eb03dffd97 hwdb: fix broken numpad paren keys on Lenovo Thinkbook 16 G6+ 2024 2024-11-08 04:09:55 +09:00
Zbigniew Jędrzejewski-Szmek 97318131fd Rename src/boot/efi to just src/boot
I very much dislike the approach in which we were mixing Linux and UEFI C code
in the same subdirectory. No code was shared between two environments. This
layout was created in e7dd673d1e, with the
justification of "being more consistent with the rest of systemd", but I don't
see how it's supposed to be so.

Originally, when the C code was just a single bootctl.c file, this wasn't so
bad. But over time the userspace code grew quite a bit. With the moves done in
previuos commits, the intermediate subdirectory is now empty except for the
efi/ subdir, and this additional subdirectory level doesn't have a good
justification. The components is called "systemd-boot", not "systemd-efi", and
we can remove one level of indentation.
2024-11-07 14:52:06 +01:00
Zbigniew Jędrzejewski-Szmek 5ffff673ac Move systemd-sbsign to its own source subdirectory
It's already two files, and I expect that more will come. It's nicer to give
its own subdirectory to maintain consistent structure.
2024-11-07 14:51:43 +01:00
Zbigniew Jędrzejewski-Szmek 1dabec0056 Move systemd-measure to its own source subdirectory
We have other subdirectories with just a single C file. And I expect
that systemd-measure will only grow over time, adding new functionality.
It's nicer to give its own subdirectory to maintain consistent structure.
2024-11-07 14:50:53 +01:00
Zbigniew Jędrzejewski-Szmek daf72e8df1 Move bless-boot components to their own source subdirectory 2024-11-07 14:50:41 +01:00
Zbigniew Jędrzejewski-Szmek 0b676aab33 Move bootctl to its own source subdirectory
It's been split into a bunch of files and deserves its own subdirectory
similarly to systemctl.
2024-11-07 14:15:00 +01:00
Lennart Poettering c6c73d561a storagetm: make the spinner stop by deactivating plymouth after we output our message
As suggested here:

https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/223#note_2171647
2024-05-06 18:52:23 +02:00
129 changed files with 2485 additions and 2049 deletions

25
TODO
View File

@ -129,6 +129,10 @@ Deprecations and removals:
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,
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
@ -217,12 +221,8 @@ Features:
services where mount propagation from the root fs is off, an still have
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
* use pty ioctl to get peer wherever possible (TIOCGPTPEER)
* 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
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
/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
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
@ -458,9 +456,6 @@ Features:
* introduce mntid_t, and make it 64bit, as apparently the kernel switched to
64bit mount ids
* use udev rule networkd ownership property to take ownership of network
interfaces nspawn creates
* mountfsd/nsresourced
- 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
@ -647,6 +642,7 @@ Features:
- openpt_allocate_in_namespace()
- unit_attach_pid_to_cgroup_via_bus()
- cg_attach() requires new kernel feature
- journald's process cache
* 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)
* 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
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
* 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
* when killing due to service watchdog timeout maybe detect whether target

View File

@ -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:*
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
###########################################################

View File

@ -529,8 +529,9 @@
<varlistentry>
<term><option>--secure-boot-auto-enroll=yes|no</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-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</replaceable>]</option></term>
<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
@ -542,9 +543,12 @@
<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
<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 passed to the OpenSSL
engine or provider, as specified by <option>--private-key-source=</option> as a
<option>--certificate=</option> option takes a path to a PEM encoded X.509 certificate or a URI
that's passed to the OpenSSL provider configured with <option>--certificate-source</option> which
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
signing engine or provider will be used to sign the EFI signature lists.</para>

View File

@ -104,6 +104,16 @@
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
</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>
</refsect1>
@ -188,8 +198,9 @@
<varlistentry>
<term><option>--private-key=<replaceable>PATH/URI</replaceable></option></term>
<term><option>--private-key-source=<replaceable>TYPE[:NAME]</replaceable></option></term>
<term><option>--certificate=<replaceable>PATH</replaceable></option></term>
<term><option>--private-key-source=<replaceable>TYPE</replaceable>[:<replaceable>NAME</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
<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
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>
</varlistentry>

View File

@ -348,9 +348,9 @@
<varlistentry>
<term><option>--private-key=</option></term>
<listitem><para>Takes a file system path. Configures the signing key to use when creating verity
signature partitions with the <varname>Verity=signature</varname> setting in partition files.
</para>
<listitem><para>Takes a file system path or an engine or provider specific designation. Configures
the signing key 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="v252"/></listitem>
</varlistentry>
@ -361,7 +361,7 @@
<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
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>
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
@ -370,13 +370,24 @@
<varlistentry>
<term><option>--certificate=</option></term>
<listitem><para>Takes a file system path. Configures the PEM encoded X.509 certificate to use when
creating verity signature partitions with the <varname>Verity=signature</varname> setting in
partition files.</para>
<listitem><para>Takes a file system path or a provider specific designation. Configures the PEM
encoded 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="v252"/></listitem>
</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>
<term><option>--tpm2-device=</option></term>
<term><option>--tpm2-pcrs=</option></term>

View File

@ -85,11 +85,16 @@
<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>--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
<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
passed to the OpenSSL engine or provider, as specified by <option>--private-key-source=</option> as a
X.509 certificate or a URI that's passed to the OpenSSL provider configured with
<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
signing engine or provider will be used to sign the PE binary.</para>

View File

@ -527,6 +527,17 @@
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</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>
<term><varname>SignKernel=<replaceable>BOOL</replaceable></varname></term>
<term><option>--sign-kernel</option></term>

View File

@ -2344,8 +2344,9 @@ subdir('src/ask-password')
subdir('src/backlight')
subdir('src/battery-check')
subdir('src/binfmt')
subdir('src/bless-boot')
subdir('src/boot')
subdir('src/boot/efi')
subdir('src/bootctl')
subdir('src/busctl')
subdir('src/cgls')
subdir('src/cgroups-agent')
@ -2380,6 +2381,7 @@ subdir('src/locale')
subdir('src/login')
subdir('src/machine')
subdir('src/machine-id-setup')
subdir('src/measure')
subdir('src/mountfsd')
subdir('src/modules-load')
subdir('src/mount')
@ -2408,6 +2410,7 @@ subdir('src/rfkill')
subdir('src/rpm')
subdir('src/run')
subdir('src/run-generator')
subdir('src/sbsign')
subdir('src/shutdown')
subdir('src/sleep')
subdir('src/socket-activate')

View File

@ -9,5 +9,6 @@ ToolsTreePackages=
libcap
libmicrohttpd
python-jinja
python-pytest
tpm2-tss
util-linux-libs

View File

@ -15,3 +15,4 @@ ToolsTreePackages=
pkgconfig(mount)
tss2-devel
python3-jinja2
python3-pytest

View File

@ -15,3 +15,4 @@ ToolsTreePackages=
libmount-dev
libtss2-dev
python3-jinja2
python3-pytest

View File

@ -14,3 +14,4 @@ ToolsTreePackages=
pkgconfig(mount)
tss2-devel
python3-jinja2
python3-pytest

View File

@ -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 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)) {

View File

@ -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'),
},
]

View File

@ -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

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -1,77 +1,430 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
bootctl_sources = files(
'bootctl-install.c',
'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',
)
efi_config_h_dir = meson.current_build_dir()
efi_addon = ''
if get_option('link-boot-shared')
boot_link_with = [libshared]
else
boot_link_with = [
libshared_static,
libsystemd_static,
]
endif
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 += [
executable_template + {
'name' : 'bootctl',
'public' : true,
'conditions' : [
'HAVE_BLKID',
],
'sources' : bootctl_sources,
'link_with' : boot_link_with,
'dependencies' : [libblkid, libopenssl],
efi_test_template + {
'sources' : files('test-bcd.c'),
'dependencies' : libzstd_cflags,
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_ZSTD'],
},
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,
efi_test_template + {
'sources' : files('test-efi-string.c'),
'conditions' : ['ENABLE_BOOTLOADER'],
},
generator_template + {
'name' : 'systemd-bless-boot-generator',
'conditions' : [
'HAVE_BLKID',
'ENABLE_BOOTLOADER',
],
'sources' : files('bless-boot-generator.c'),
'link_with' : boot_link_with,
efi_fuzz_template + {
'sources' : files('fuzz-bcd.c'),
},
libexec_template + {
'name' : 'systemd-measure',
'conditions' : [
'HAVE_BLKID',
'HAVE_OPENSSL',
'HAVE_TPM2',
],
'sources' : files('measure.c'),
'dependencies' : libopenssl,
efi_fuzz_template + {
'sources' : files('fuzz-efi-string.c'),
},
libexec_template + {
'name' : 'systemd-sbsign',
'conditions' : [
'HAVE_OPENSSL',
],
'sources' : files('sbsign.c'),
'dependencies' : libopenssl,
efi_fuzz_template + {
'sources' : files('fuzz-efi-osrel.c'),
},
libexec_template + {
'name' : 'systemd-boot-check-no-failures',
'sources' : files('boot-check-no-failures.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)

View File

@ -956,10 +956,26 @@ int verb_install(int argc, char *argv[], void *userdata) {
graceful = !install && arg_graceful; /* support graceful mode for updates */
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)
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(
arg_private_key_source_type,
arg_private_key_source,

Some files were not shown because too many files have changed in this diff Show More