boot,stub: explicitly measure select SMBIOS objects (#42233)

This is supposed to protect our SMBIOS type 11 importing for
credentials. Note that firmwares are supposed to measure SMBIOS anyway
to PCR 1. Alas firmware doesn't really do that in various cases. Hence
let's do so again, for select objects.

This closes a gap where some of the input for OS (i.e. system
credentials places in smbios11) isn't measured properly.

(I really want this to get into v261, because this will fuck up the PCRs
a bit more, and we already have the new separator measurement in v261,
hence there's value in getting this merged at the same time, so that we
don't break the measurements a 2nd time)
This commit is contained in:
Luca Boccassi
2026-05-21 21:44:42 +01:00
committed by GitHub
16 changed files with 345 additions and 68 deletions
-8
View File
@@ -1212,12 +1212,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later
- in pid1: include ExecStart= cmdlines (and other Exec*= cmdlines) in polkit
request, so that policies can match against command lines.
- in sd-boot and sd-stub measure the SMBIOS vendor strings to some PCR (at
least some subset of them that look like systemd stuff), because apparently
some firmware does not, but systemd honours it. avoid duplicate measurement
by sd-boot and sd-stub by adding LoaderFeatures/StubFeatures flag for this,
so that sd-stub can avoid it if sd-boot already did it.
- in sd-id128: also parse UUIDs in RFC4122 URN syntax (i.e. chop off urn:uuid: prefix)
- in sd-stub: optionally add support for a new PE section .keyring or so that
@@ -1745,8 +1739,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later
- measure all log-in attempts into a new nvpcr
- measure credentials picked up from SMBIOS to some suitable PCR
- measure GPT and LUKS headers somewhere when we use them (i.e. in
systemd-gpt-auto-generator/systemd-repart and in systemd-cryptsetup?)
+13
View File
@@ -145,6 +145,8 @@ Variables will be listed below using the Linux efivarfs naming,
* `1 << 19` → The boot loader supports the `LoaderEntryPreferred` variable when set.
* `1 << 20` → The boot loader reports the firmware-configured keyboard layout in the
EFI variable `LoaderKeyboardLayout-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f`.
* `1 << 21` → The boot loader measures SMBIOS information into a TPM2 PCR and reports the PCR index in the
EFI variable `LoaderPcrSMBIOS-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f`.
* The EFI variable `LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f`
contains binary random data,
@@ -184,6 +186,17 @@ Variables will be listed below using the Linux efivarfs naming,
uses this as a lowest-priority fallback keyboard layout
when no explicit configuration is provided.
* The EFI variable `LoaderPcrSMBIOS-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f`
contains the index of the TPM2 PCR (as a decimal ASCII string formatted as a
NUL-terminated UTF-16 string, e.g. `1`) into which the boot loader measured
select SMBIOS structures: type 1 (system information, with the volatile
"Wake-up Type" field zeroed out), type 2 (baseboard information) and type 11
(OEM strings). This is a volatile (non-persistent) variable, set only if a
measurement was successfully completed, and remains unset otherwise. Both
`systemd-boot` and `systemd-stub` perform this measurement; whichever runs
first sets the variable, and its presence suppresses a second measurement of
the same data into the same PCR during the same boot.
If `LoaderTimeInitUSec` and `LoaderTimeExecUSec` are set, `systemd-analyze`
will include them in its boot-time analysis. If `LoaderDevicePartUUID` is set,
systemd will mount the ESP that was used for the boot to `/boot`, but only if
+47
View File
@@ -91,6 +91,45 @@ must be employed when designing a system that uses this feature.
## PCR Measurements Made by `systemd-boot` (UEFI)
### PCR 1, `EV_EVENT_TAG`, SMBIOS information
Select SMBIOS structures provided by the firmware are measured into PCR 1 (the
TCG-defined register for platform configuration data), one tagged event per
structure:
* SMBIOS type 1 (system information). The volatile "Wake-up Type" field is
zeroed before measuring, since it varies depending on how the machine was
powered on (cold boot, resume from sleep, AC restore, …) and would otherwise
make the measurement non-reproducible.
* SMBIOS type 2 (baseboard information).
* SMBIOS type 11 (OEM strings). There may be more than one such structure; all
are measured.
Note that these measurements are – strictly speaking – redundant, since
firmwares are supposed to measure SMBIOS data anyway on their own. However, it
has been found this is not the case on many real-life implementations. Since in
particular SMBIOS type 11 may carry highly relevant input for the OS
(e.g. system credentials), an explicit measurement is made here to ensure all
parameters for the OS are comprehensively measured even on flaky firmwares.
→ **Event Tag** `0xd5cb7cbc` for type 1, `0xe0d47bc8` for type 2, `0xc0b3bd23`
for type 11.
→ **Description** in the event log record is `smbios:type1`, `smbios:type2` or
`smbios:type11` respectively, in UTF-16.
→ **Measured hash** covers the raw bytes of the SMBIOS structure (formatted area
plus trailing string set), with the type 1 "Wake-up Type" field zeroed out as
described above.
This measurement is also performed by `systemd-stub` (see below), so that systems
that boot a UKI directly, bypassing `systemd-boot`, still get it. Whichever
component runs first performs the measurement and sets the volatile
`LoaderPcrSMBIOS` EFI variable to the PCR index used; its presence suppresses a
second measurement of the same data into the same PCR during the same boot. Note
that the firmware itself typically also extends PCR 1, so its final value is not
solely determined by this measurement.
### PCR 5, `EV_EVENT_TAG`, `loader.conf`
The content of `systemd-boot`'s configuration file, `loader/loader.conf`, is
@@ -120,6 +159,14 @@ trailing NUL bytes).
## PCR Measurements Made by `systemd-stub` (UEFI)
### PCR 1, `EV_EVENT_TAG`, SMBIOS information
Identical to the SMBIOS measurement described above for `systemd-boot`. When
`systemd-stub` is invoked by `systemd-boot`, the measurement has typically already
been made (tracked via the `LoaderPcrSMBIOS` EFI variable) and is not repeated;
when the UKI is booted directly by the firmware, `systemd-stub` performs it
itself.
### PCR 11, `EV_IPL`, PE section name
A measurement is made for each PE section of the UKI that is defined by the
+13
View File
@@ -622,6 +622,19 @@ extra /6a9857a393724b7a981ebb5b8495b9ea/1.2.3/baz.confext.raw</programlist
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderPcrSMBIOS</varname></term>
<listitem><para>The PCR register index select SMBIOS structures are measured into — type 1
(system information, with the volatile "Wake-up Type" field zeroed out), type 2 (baseboard
information) and type 11 (OEM strings). Formatted as decimal ASCII string (e.g.
<literal>1</literal>). Set by the boot loader if a measurement was successfully completed, and remains
unset otherwise. (Note that <command>systemd-stub</command> performs the same measurement when booted
directly, bypassing the boot loader.)</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderImageIdentifier</varname></term>
+14
View File
@@ -664,6 +664,20 @@
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderPcrSMBIOS</varname></term>
<listitem><para>The PCR register index select SMBIOS structures are measured into — type 1
(system information, with the volatile "Wake-up Type" field zeroed out), type 2 (baseboard
information) and type 11 (OEM strings). Formatted as decimal ASCII string (e.g.
<literal>1</literal>). This variable is set if a measurement was successfully completed, and remains
unset otherwise. <command>systemd-stub</command> performs this measurement only if it has not already
been done in the same boot (e.g. by the boot loader), as indicated by this variable being set
already.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderBootSecret</varname></term>
+6
View File
@@ -17,6 +17,7 @@
#include "iovec-util.h"
#include "line-edit.h"
#include "measure.h"
#include "measure-smbios.h"
#include "memory-util.h"
#include "part-discovery.h"
#include "pe.h"
@@ -3267,6 +3268,7 @@ static void export_loader_variables(
EFI_LOADER_FEATURE_TYPE1_UKI_URL |
EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS |
EFI_LOADER_FEATURE_KEYBOARD_LAYOUT |
EFI_LOADER_FEATURE_SMBIOS_MEASURED |
0;
assert(loaded_image);
@@ -3434,6 +3436,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
export_common_variables(loaded_image);
export_loader_variables(loaded_image, init_usec);
/* Measure SMBIOS data into PCR 1. This is done early, and suppressed if sd-stub later runs in
* the same boot (and vice versa), via the LoaderPcrSMBIOS EFI variable. */
measure_smbios();
(void) load_drivers(image, loaded_image, root_dir);
_cleanup_free_ char16_t *loaded_image_path = NULL;
+96
View File
@@ -0,0 +1,96 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "efi-efivars.h"
#include "efi-log.h"
#include "measure.h"
#include "measure-smbios.h"
#include "smbios.h"
#include "tpm2-pcr.h"
#include "util.h"
static void measure_smbios_raw(
const void *p,
size_t size,
uint32_t event_id,
const char16_t *description,
bool *measured) {
EFI_STATUS err;
bool m = false;
assert(p);
assert(description);
assert(measured);
err = tpm_log_tagged_event(
TPM2_PCR_PLATFORM_CONFIG,
POINTER_TO_PHYSICAL_ADDRESS(p),
size,
event_id,
description,
&m);
if (err != EFI_SUCCESS)
log_error_status(err, "Unable to measure SMBIOS structure (%ls), ignoring: %m", description);
*measured = *measured || m;
}
static void measure_smbios_type1(const SmbiosHeader *header, size_t size, bool *measured) {
assert(header);
assert(measured);
/* The wake-up type field varies depending on how the machine was powered on (cold boot, resume
* from sleep, AC restore, …), which would make the measurement non-reproducible. Hence measure a
* copy with that field zeroed out. */
assert(size >= sizeof(SmbiosTableType1));
_cleanup_free_ SmbiosTableType1 *copy = xmemdup(header, size);
copy->wake_up_type = 0;
measure_smbios_raw(copy, size, SMBIOS_TYPE1_EVENT_TAG_ID, u"smbios:type1", measured);
}
static bool measure_smbios_object(const SmbiosHeader *header, size_t size, void *userdata) {
bool *measured = ASSERT_PTR(userdata);
switch (header->type) {
case 1: /* System Information */
measure_smbios_type1(header, size, measured);
break;
case 2: /* Baseboard Information */
measure_smbios_raw(header, size, SMBIOS_TYPE2_EVENT_TAG_ID, u"smbios:type2", measured);
break;
case 11: /* OEM Strings */
measure_smbios_raw(header, size, SMBIOS_TYPE11_EVENT_TAG_ID, u"smbios:type11", measured);
break;
default:
break;
}
return true; /* Keep iterating: there may be more than one matching structure (e.g. type 11). */
}
void measure_smbios(void) {
bool measured = false;
if (!tpm_present())
return;
/* If the measurement was already done this boot (e.g. by sd-boot before it chainloaded us), don't
* do it again — re-extending PCR 1 would invalidate the value. */
if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderPcrSMBIOS", /* ret_data= */ NULL, /* ret_size= */ NULL) == EFI_SUCCESS)
return;
/* Measure SMBIOS type 1 (system information), type 2 (baseboard information) and type 11 (OEM
* strings) into PCR 1, in a single pass over the SMBIOS table. */
smbios_foreach(measure_smbios_object, &measured);
/* If we measured something, tell the OS which PCR we used (and suppress a second pass). */
if (measured)
(void) efivar_set_uint64_str16(MAKE_GUID_PTR(LOADER), u"LoaderPcrSMBIOS", TPM2_PCR_PLATFORM_CONFIG, /* flags= */ 0);
}
+8
View File
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* Measures SMBIOS type 1 (system information, with the volatile "Wake-up Type" field masked) and all
* type 11 (OEM strings) structures into PCR 1, and records the PCR index in the transient
* LoaderPcrSMBIOS EFI variable. Called by both sd-boot and sd-stub; the presence of LoaderPcrSMBIOS
* suppresses a redundant second measurement when both run during the same boot. */
void measure_smbios(void);
+1
View File
@@ -323,6 +323,7 @@ libefi_sources = files(
'hii.c',
'initrd.c',
'measure.c',
'measure-smbios.c',
'part-discovery.c',
'pe.c',
'random-seed.c',
+77 -45
View File
@@ -39,12 +39,6 @@ typedef struct {
uint64_t table_address;
} _packed_ Smbios3EntryPoint;
typedef struct {
uint8_t type;
uint8_t length;
uint8_t handle[2];
} _packed_ SmbiosHeader;
typedef struct {
SmbiosHeader header;
uint8_t vendor;
@@ -56,18 +50,6 @@ typedef struct {
uint8_t bios_characteristics_ext[2];
} _packed_ SmbiosTableType0;
typedef struct {
SmbiosHeader header;
uint8_t manufacturer;
uint8_t product_name;
uint8_t version;
uint8_t serial_number;
EFI_GUID uuid;
uint8_t wake_up_type;
uint8_t sku_number;
uint8_t family;
} _packed_ SmbiosTableType1;
typedef struct {
SmbiosHeader header;
uint8_t manufacturer;
@@ -103,6 +85,44 @@ static const void* find_smbios_configuration_table(uint64_t *ret_size) {
return NULL;
}
/* Given 'p' pointing at a structure header with 'size' bytes left in the table from there onwards,
* returns a pointer just past the end of this structure (i.e. the start of the next one), accounting
* for the formatted area and the trailing string set (terminated by a double NUL byte). Returns NULL
* if the structure is malformed or runs past the end of the table. */
static const uint8_t* smbios_structure_end(const uint8_t *p, uint64_t size) {
assert(p);
if (size < sizeof(SmbiosHeader))
return NULL;
const SmbiosHeader *header = (const SmbiosHeader *) p;
if (size < header->length)
return NULL;
/* Skip over formatted area. */
const uint8_t *q = p + header->length;
size -= header->length;
/* Special case: if there are no strings appended, we'll see two NUL bytes. */
if (size >= 2 && q[0] == 0 && q[1] == 0)
return q + 2;
/* Skip over a populated string table. */
bool first = true;
for (;;) {
const uint8_t *e = memchr(q, 0, size);
if (!e)
return NULL;
if (!first && e == q) /* Double NUL byte means we've reached the end of the string table. */
return q + 1;
size -= e + 1 - q;
q = e + 1;
first = false;
}
}
static const SmbiosHeader* get_smbios_table(uint8_t type, size_t min_size, uint64_t *ret_size_left) {
uint64_t size;
const uint8_t *p = find_smbios_configuration_table(&size);
@@ -132,34 +152,12 @@ static const SmbiosHeader* get_smbios_table(uint8_t type, size_t min_size, uint6
return header; /* Yay! */
}
/* Skip over formatted area. */
size -= header->length;
p += header->length;
const uint8_t *next = smbios_structure_end(p, size);
if (!next)
goto not_found;
/* Special case: if there are no strings appended, we'll see two NUL bytes, skip over them */
if (size >= 2 && p[0] == 0 && p[1] == 0) {
size -= 2;
p += 2;
continue;
}
/* Skip over a populated string table. */
bool first = true;
for (;;) {
const uint8_t *e = memchr(p, 0, size);
if (!e)
goto not_found;
if (!first && e == p) {/* Double NUL byte means we've reached the end of the string table. */
p++;
size--;
break;
}
size -= e + 1 - p;
p = e + 1;
first = false;
}
size -= next - p;
p = next;
}
not_found:
@@ -169,6 +167,40 @@ not_found:
return NULL;
}
void smbios_foreach(SmbiosForeachFunc func, void *userdata) {
assert(func);
uint64_t size;
const uint8_t *p = find_smbios_configuration_table(&size);
if (!p)
return;
/* Walks the SMBIOS table exactly once, invoking 'func' for every structure. 'func' receives the
* structure's header (which carries its type) and the structure's total length (formatted area +
* trailing string set); returning false stops the iteration early. */
for (;;) {
if (size < sizeof(SmbiosHeader))
return;
const SmbiosHeader *header = (const SmbiosHeader *) p;
/* End of table. */
if (header->type == 127)
return;
const uint8_t *next = smbios_structure_end(p, size);
if (!next)
return;
if (!func(header, next - p, userdata))
return;
size -= next - p;
p = next;
}
}
bool smbios_in_hypervisor(void) {
/* Look up BIOS Information (Type 0). */
const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0, sizeof(SmbiosTableType0), /* ret_size_left= */ NULL);
+25
View File
@@ -3,10 +3,35 @@
#include "efi.h"
typedef struct {
uint8_t type;
uint8_t length;
uint8_t handle[2];
} _packed_ SmbiosHeader;
typedef struct {
SmbiosHeader header;
uint8_t manufacturer;
uint8_t product_name;
uint8_t version;
uint8_t serial_number;
EFI_GUID uuid;
uint8_t wake_up_type;
uint8_t sku_number;
uint8_t family;
} _packed_ SmbiosTableType1;
bool smbios_in_hypervisor(void);
const char* smbios_find_oem_string(const char *name, const char *after);
/* Invoked by smbios_foreach() for each SMBIOS structure. 'header' points at the structure (which
* carries its type), and 'size' is the structure's total length (formatted area + trailing string
* set). Returning false stops the iteration. */
typedef bool (*SmbiosForeachFunc)(const SmbiosHeader *header, size_t size, void *userdata);
void smbios_foreach(SmbiosForeachFunc func, void *userdata);
typedef struct RawSmbiosInfo {
const char *manufacturer;
const char *product_name;
+6
View File
@@ -14,6 +14,7 @@
#include "iovec-util.h"
#include "linux.h"
#include "measure.h"
#include "measure-smbios.h"
#include "memory-util.h"
#include "part-discovery.h"
#include "pe.h"
@@ -116,6 +117,7 @@ static void export_stub_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, unsig
EFI_STUB_FEATURE_MULTI_PROFILE_UKI | /* We grok the "@1" profile command line argument */
EFI_STUB_FEATURE_REPORT_STUB_PARTITION | /* We set StubDevicePartUUID + StubImageIdentifier */
EFI_STUB_FEATURE_REPORT_URL | /* We set StubDeviceURL + LoaderDeviceURL */
EFI_STUB_FEATURE_SMBIOS_MEASURED | /* We measure SMBIOS data into PCR 1 */
0;
assert(loaded_image);
@@ -1252,6 +1254,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
export_common_variables(loaded_image);
export_stub_variables(loaded_image, profile);
/* Measure SMBIOS data into PCR 1, unless sd-boot already did so in the same boot (tracked via
* the LoaderPcrSMBIOS EFI variable). */
measure_smbios();
/* First load the base device tree, then fix it up using addons - global first, then per-UKI. */
install_embedded_devicetree(loaded_image, sections, &dt_state);
install_addon_devicetrees(&dt_state, dt_addons, n_dt_addons, &parameters_measured);
+2
View File
@@ -408,6 +408,7 @@ int verb_status(int argc, char *argv[], uintptr_t _data, void *userdata) {
{ EFI_LOADER_FEATURE_TYPE1_UKI_URL, "Support Type #1 uki-url field" },
{ EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS, "Loader reports active TPM2 PCR banks" },
{ EFI_LOADER_FEATURE_KEYBOARD_LAYOUT, "Loader reports firmware keyboard layout" },
{ EFI_LOADER_FEATURE_SMBIOS_MEASURED, "Loader measures SMBIOS information" },
};
static const struct {
uint64_t flag;
@@ -425,6 +426,7 @@ int verb_status(int argc, char *argv[], uintptr_t _data, void *userdata) {
{ EFI_STUB_FEATURE_CMDLINE_SMBIOS, "Pick up .cmdline from SMBIOS Type 11" },
{ EFI_STUB_FEATURE_DEVICETREE_ADDONS, "Pick up .dtb from addons" },
{ EFI_STUB_FEATURE_MULTI_PROFILE_UKI, "Stub understands profile selector" },
{ EFI_STUB_FEATURE_SMBIOS_MEASURED, "Stub measures SMBIOS information" },
};
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL, *stub_path = NULL,
*current_entry = NULL, *oneshot_entry = NULL, *preferred_entry = NULL, *default_entry = NULL, *sysfail_entry = NULL,
+2
View File
@@ -30,6 +30,7 @@
#define EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS (UINT64_C(1) << 18)
#define EFI_LOADER_FEATURE_ENTRY_PREFERRED (UINT64_C(1) << 19)
#define EFI_LOADER_FEATURE_KEYBOARD_LAYOUT (UINT64_C(1) << 20)
#define EFI_LOADER_FEATURE_SMBIOS_MEASURED (UINT64_C(1) << 21)
/* Features of the stub, i.e. systemd-stub */
#define EFI_STUB_FEATURE_REPORT_BOOT_PARTITION (UINT64_C(1) << 0)
@@ -44,6 +45,7 @@
#define EFI_STUB_FEATURE_MULTI_PROFILE_UKI (UINT64_C(1) << 9)
#define EFI_STUB_FEATURE_REPORT_STUB_PARTITION (UINT64_C(1) << 10)
#define EFI_STUB_FEATURE_REPORT_URL (UINT64_C(1) << 11)
#define EFI_STUB_FEATURE_SMBIOS_MEASURED (UINT64_C(1) << 12)
typedef enum SecureBootMode {
SECURE_BOOT_UNSUPPORTED,
+9
View File
@@ -56,3 +56,12 @@ enum {
/* The tag used for EV_EVENT_TAG event log records covering the selected UKI profile */
#define UKI_PROFILE_EVENT_TAG_ID UINT32_C(0x13aed6db)
/* The tag used for EV_EVENT_TAG event log records covering the SMBIOS type 1 (system information) structure */
#define SMBIOS_TYPE1_EVENT_TAG_ID UINT32_C(0xd5cb7cbc)
/* The tag used for EV_EVENT_TAG event log records covering the SMBIOS type 2 (baseboard information) structure */
#define SMBIOS_TYPE2_EVENT_TAG_ID UINT32_C(0xe0d47bc8)
/* The tag used for EV_EVENT_TAG event log records covering SMBIOS type 11 (OEM strings) structures */
#define SMBIOS_TYPE11_EVENT_TAG_ID UINT32_C(0xc0b3bd23)
+26 -15
View File
@@ -8,6 +8,7 @@
#include "sd-varlink.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "ask-password-api.h"
#include "bitfield.h"
#include "blockdev-util.h"
@@ -29,7 +30,9 @@
#include "format-table.h"
#include "format-util.h"
#include "fs-util.h"
#include "glyph-util.h"
#include "gpt.h"
#include "help-util.h"
#include "hexdecoct.h"
#include "initrd-util.h"
#include "json-util.h"
@@ -45,7 +48,6 @@
#include "pcrextend-util.h"
#include "pcrlock-firmware.h"
#include "pe-binary.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "recovery-key.h"
#include "sort-util.h"
@@ -744,6 +746,23 @@ static int event_log_record_extract_firmware_description(EventLogRecord *rec) {
break;
}
/* SMBIOS structures measured by sd-boot/sd-stub. The tagged event payload is just a
* constant identifying string ("smbios:typeN"), hence don't show it. */
case SMBIOS_TYPE1_EVENT_TAG_ID:
if (!strextend_with_separator(&rec->description, ", ", "systemd: SMBIOS system information (type 1)"))
return log_oom();
break;
case SMBIOS_TYPE2_EVENT_TAG_ID:
if (!strextend_with_separator(&rec->description, ", ", "systemd: SMBIOS baseboard information (type 2)"))
return log_oom();
break;
case SMBIOS_TYPE11_EVENT_TAG_ID:
if (!strextend_with_separator(&rec->description, ", ", "systemd: SMBIOS OEM strings (type 11)"))
return log_oom();
break;
default: {
_cleanup_free_ char *s = NULL;
@@ -5132,14 +5151,9 @@ static int verb_lock_raw(int argc, char *argv[], uintptr_t _data, void *userdata
}
static int help(void) {
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *commands = NULL, *protections = NULL, *options = NULL;
int r;
r = terminal_urlify_man("systemd-pcrlock", "8", &link);
if (r < 0)
return log_oom();
r = verbs_get_help_table(&commands);
if (r < 0)
return r;
@@ -5154,28 +5168,25 @@ static int help(void) {
(void) table_sync_column_widths(0, commands, protections, options);
printf("%s [OPTIONS...] COMMAND ...\n"
"\n%sManage a TPM2 PCR lock.%s\n",
program_invocation_short_name,
ansi_highlight(),
ansi_normal());
help_cmdline("[OPTIONS...] COMMAND ...");
help_abstract("Manage a TPM2 PCR lock.");
printf("\n%sCommands:%s\n", ansi_underline(), ansi_normal());
help_section("Commands");
r = table_print_or_warn(commands);
if (r < 0)
return r;
printf("\n%sProtections:%s\n", ansi_underline(), ansi_normal());
help_section("Protections");
r = table_print_or_warn(protections);
if (r < 0)
return r;
printf("\n%sOptions:%s\n", ansi_underline(), ansi_normal());
help_section("Options");
r = table_print_or_warn(options);
if (r < 0)
return r;
printf("\nSee the %s for details.\n", link);
help_man_page_reference("systemd-pcrlock", "8");
return 0;
}