mirror of
https://github.com/systemd/systemd.git
synced 2024-10-27 01:55:22 +03:00
Merge pull request #33567 from poettering/boot-fixlets
sd-boot,sd-stub: a variety of smaller fixes
This commit is contained in:
commit
4ac314a81f
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>systemd-measure</refname>
|
<refname>systemd-measure</refname>
|
||||||
<refpurpose>Pre-calculate and sign expected TPM2 PCR values for booted unified kernel images</refpurpose>
|
<refpurpose>Pre-calculate and sign expected TPM2 PCR 11 values for booted unified kernel images</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
<term><command>status</command></term>
|
<term><command>status</command></term>
|
||||||
|
|
||||||
<listitem><para>This is the default command if none is specified. This queries the local system's
|
<listitem><para>This is the default command if none is specified. This queries the local system's
|
||||||
TPM2 PCR 11+12+13 values and displays them. The data is written in a similar format as the
|
TPM2 PCR 11 values and displays them. The data is written in a similar format as the
|
||||||
<command>calculate</command> command below, and may be used to quickly compare expectation with
|
<command>calculate</command> command below, and may be used to quickly compare expectation with
|
||||||
reality.</para>
|
reality.</para>
|
||||||
|
|
||||||
@ -76,9 +76,9 @@
|
|||||||
kernel image consisting of the components specified with <option>--linux=</option>,
|
kernel image consisting of the components specified with <option>--linux=</option>,
|
||||||
<option>--osrel=</option>, <option>--cmdline=</option>, <option>--initrd=</option>,
|
<option>--osrel=</option>, <option>--cmdline=</option>, <option>--initrd=</option>,
|
||||||
<option>--ucode=</option>, <option>--splash=</option>, <option>--dtb=</option>,
|
<option>--ucode=</option>, <option>--splash=</option>, <option>--dtb=</option>,
|
||||||
<option>--uname=</option>, <option>--sbat=</option>, <option>--pcrpkey=</option> see below.
|
<option>--uname=</option>, <option>--sbat=</option>, <option>--pcrpkey=</option> see below. Only
|
||||||
Only <option>--linux=</option> is mandatory. (Alternatively, specify <option>--current</option> to use the current values of PCR
|
<option>--linux=</option> is mandatory. (Alternatively, specify <option>--current</option> to use the
|
||||||
register 11 instead.)</para>
|
current values of PCR register 11 instead.)</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v252"/>
|
<xi:include href="version-info.xml" xpointer="v252"/>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
104
man/ukify.xml
104
man/ukify.xml
@ -292,6 +292,29 @@
|
|||||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>OSRelease=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></varname></term>
|
||||||
|
<term><option>--os-release=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>The os-release description (the <literal>.osrel</literal> section). The argument
|
||||||
|
may be a literal string, or <literal>@</literal> followed by a path name. If not specified, the
|
||||||
|
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file
|
||||||
|
will be picked up from the host system.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>Cmdline=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></varname></term>
|
||||||
|
<term><option>--cmdline=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>The kernel command line (the <literal>.cmdline</literal> section). The argument may
|
||||||
|
be a literal string, or <literal>@</literal> followed by a path name. If not specified, no command
|
||||||
|
line will be embedded.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Initrd=<replaceable>INITRD</replaceable>...</varname></term>
|
<term><varname>Initrd=<replaceable>INITRD</replaceable>...</varname></term>
|
||||||
<term><option>--initrd=<replaceable>LINUX</replaceable></option></term>
|
<term><option>--initrd=<replaceable>LINUX</replaceable></option></term>
|
||||||
@ -314,24 +337,12 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Cmdline=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></varname></term>
|
<term><varname>Splash=<replaceable>PATH</replaceable></varname></term>
|
||||||
<term><option>--cmdline=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
|
<term><option>--splash=<replaceable>PATH</replaceable></option></term>
|
||||||
|
|
||||||
<listitem><para>The kernel command line (the <literal>.cmdline</literal> section). The argument may
|
<listitem><para>A picture to display during boot (the <literal>.splash</literal> section). The
|
||||||
be a literal string, or <literal>@</literal> followed by a path name. If not specified, no command
|
argument is a path to a BMP file. If not specified, the section will not be present.
|
||||||
line will be embedded.</para>
|
</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>OSRelease=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></varname></term>
|
|
||||||
<term><option>--os-release=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
|
|
||||||
|
|
||||||
<listitem><para>The os-release description (the <literal>.osrel</literal> section). The argument
|
|
||||||
may be a literal string, or <literal>@</literal> followed by a path name. If not specified, the
|
|
||||||
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file
|
|
||||||
will be picked up from the host system.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -348,16 +359,35 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Splash=<replaceable>PATH</replaceable></varname></term>
|
<term><varname>Uname=<replaceable>VERSION</replaceable></varname></term>
|
||||||
<term><option>--splash=<replaceable>PATH</replaceable></option></term>
|
<term><option>--uname=<replaceable>VERSION</replaceable></option></term>
|
||||||
|
|
||||||
<listitem><para>A picture to display during boot (the <literal>.splash</literal> section). The
|
<listitem><para>Specify the kernel version (as in <command>uname -r</command>, the
|
||||||
argument is a path to a BMP file. If not specified, the section will not be present.
|
<literal>.uname</literal> section). If not specified, an attempt will be made to extract the
|
||||||
</para>
|
version string from the kernel image. It is recommended to pass this explicitly if known, because
|
||||||
|
the extraction is based on heuristics and not very reliable. If not specified and extraction fails,
|
||||||
|
the section will not be present.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>SBAT=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></varname></term>
|
||||||
|
<term><option>--sbat=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>SBAT metadata associated with the UKI or addon. SBAT policies are useful to revoke
|
||||||
|
whole groups of UKIs or addons with a single, static policy update that does not take space in
|
||||||
|
DBX/MOKX. If not specified manually, a default metadata entry consisting of
|
||||||
|
<literal>uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/</literal>
|
||||||
|
for UKIs and
|
||||||
|
<literal>uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html</literal>
|
||||||
|
for addons will be used, to ensure it is always possible to revoke them. For more information on
|
||||||
|
SBAT see <ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>PCRPKey=<replaceable>PATH</replaceable></varname></term>
|
<term><varname>PCRPKey=<replaceable>PATH</replaceable></varname></term>
|
||||||
<term><option>--pcrpkey=<replaceable>PATH</replaceable></option></term>
|
<term><option>--pcrpkey=<replaceable>PATH</replaceable></option></term>
|
||||||
@ -370,19 +400,6 @@
|
|||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>Uname=<replaceable>VERSION</replaceable></varname></term>
|
|
||||||
<term><option>--uname=<replaceable>VERSION</replaceable></option></term>
|
|
||||||
|
|
||||||
<listitem><para>Specify the kernel version (as in <command>uname -r</command>, the
|
|
||||||
<literal>.uname</literal> section). If not specified, an attempt will be made to extract the
|
|
||||||
version string from the kernel image. It is recommended to pass this explicitly if known, because
|
|
||||||
the extraction is based on heuristics and not very reliable. If not specified and extraction fails,
|
|
||||||
the section will not be present.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>PCRBanks=<replaceable>PATH</replaceable></varname></term>
|
<term><varname>PCRBanks=<replaceable>PATH</replaceable></varname></term>
|
||||||
<term><option>--pcr-banks=<replaceable>PATH</replaceable></option></term>
|
<term><option>--pcr-banks=<replaceable>PATH</replaceable></option></term>
|
||||||
@ -488,23 +505,6 @@
|
|||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>SBAT=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></varname></term>
|
|
||||||
<term><option>--sbat=<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
|
|
||||||
|
|
||||||
<listitem><para>SBAT metadata associated with the UKI or addon. SBAT policies are useful to revoke
|
|
||||||
whole groups of UKIs or addons with a single, static policy update that does not take space in
|
|
||||||
DBX/MOKX. If not specified manually, a default metadata entry consisting of
|
|
||||||
<literal>uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/</literal>
|
|
||||||
for UKIs and
|
|
||||||
<literal>uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html</literal>
|
|
||||||
for addons will be used, to ensure it is always possible to revoke them. For more information on
|
|
||||||
SBAT see <ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim documentation</ulink>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
|
@ -620,16 +620,21 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static EFI_STATUS set_reboot_into_firmware(void) {
|
static EFI_STATUS set_reboot_into_firmware(void) {
|
||||||
uint64_t osind = 0;
|
|
||||||
EFI_STATUS err;
|
EFI_STATUS err;
|
||||||
|
|
||||||
|
uint64_t osind = 0;
|
||||||
(void) efivar_get_uint64_le(MAKE_GUID_PTR(EFI_GLOBAL_VARIABLE), u"OsIndications", &osind);
|
(void) efivar_get_uint64_le(MAKE_GUID_PTR(EFI_GLOBAL_VARIABLE), u"OsIndications", &osind);
|
||||||
|
|
||||||
|
if (FLAGS_SET(osind, EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
osind |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
osind |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||||
|
|
||||||
err = efivar_set_uint64_le(MAKE_GUID_PTR(EFI_GLOBAL_VARIABLE), u"OsIndications", osind, EFI_VARIABLE_NON_VOLATILE);
|
err = efivar_set_uint64_le(MAKE_GUID_PTR(EFI_GLOBAL_VARIABLE), u"OsIndications", osind, EFI_VARIABLE_NON_VOLATILE);
|
||||||
if (err != EFI_SUCCESS)
|
if (err != EFI_SUCCESS)
|
||||||
log_error_status(err, "Error setting OsIndications: %m");
|
return log_error_status(err, "Error setting OsIndications, ignoring: %m");
|
||||||
return err;
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn_ static EFI_STATUS poweroff_system(void) {
|
_noreturn_ static EFI_STATUS poweroff_system(void) {
|
||||||
@ -881,6 +886,7 @@ static bool menu_run(
|
|||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case KEYPRESS(0, SCAN_UP, 0):
|
case KEYPRESS(0, SCAN_UP, 0):
|
||||||
|
case KEYPRESS(0, SCAN_VOLUME_UP, 0): /* Handle phones/tablets that only have a volume up/down rocker + power key (and otherwise just touchscreen input) */
|
||||||
case KEYPRESS(0, 0, 'k'):
|
case KEYPRESS(0, 0, 'k'):
|
||||||
case KEYPRESS(0, 0, 'K'):
|
case KEYPRESS(0, 0, 'K'):
|
||||||
if (idx_highlight > 0)
|
if (idx_highlight > 0)
|
||||||
@ -888,6 +894,7 @@ static bool menu_run(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KEYPRESS(0, SCAN_DOWN, 0):
|
case KEYPRESS(0, SCAN_DOWN, 0):
|
||||||
|
case KEYPRESS(0, SCAN_VOLUME_DOWN, 0):
|
||||||
case KEYPRESS(0, 0, 'j'):
|
case KEYPRESS(0, 0, 'j'):
|
||||||
case KEYPRESS(0, 0, 'J'):
|
case KEYPRESS(0, 0, 'J'):
|
||||||
if (idx_highlight < config->n_entries-1)
|
if (idx_highlight < config->n_entries-1)
|
||||||
@ -925,9 +932,10 @@ static bool menu_run(
|
|||||||
|
|
||||||
case KEYPRESS(0, 0, '\n'):
|
case KEYPRESS(0, 0, '\n'):
|
||||||
case KEYPRESS(0, 0, '\r'):
|
case KEYPRESS(0, 0, '\r'):
|
||||||
case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
|
case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
|
||||||
case KEYPRESS(0, SCAN_F3, '\r'): /* Teclast X98+ II firmware sends malformed events */
|
case KEYPRESS(0, SCAN_F3, '\r'): /* Teclast X98+ II firmware sends malformed events */
|
||||||
case KEYPRESS(0, SCAN_RIGHT, 0):
|
case KEYPRESS(0, SCAN_RIGHT, 0):
|
||||||
|
case KEYPRESS(0, SCAN_SUSPEND, 0): /* Handle phones/tablets with only a power key + volume up/down rocker (and otherwise just touchscreen input) */
|
||||||
action = ACTION_RUN;
|
action = ACTION_RUN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1658,15 +1666,21 @@ static void config_load_type1_entries(
|
|||||||
continue;
|
continue;
|
||||||
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
|
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!endswith_no_case(f->FileName, u".conf"))
|
if (!endswith_no_case(f->FileName, u".conf"))
|
||||||
continue;
|
continue;
|
||||||
if (startswith(f->FileName, u"auto-"))
|
if (startswith_no_case(f->FileName, u"auto-"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
|
err = file_read(entries_dir,
|
||||||
if (err == EFI_SUCCESS)
|
f->FileName,
|
||||||
boot_entry_add_type1(config, device, root_dir, u"\\loader\\entries", f->FileName, content, loaded_image_path);
|
/* offset= */ 0,
|
||||||
|
/* size= */ 0,
|
||||||
|
&content,
|
||||||
|
/* ret_size= */ NULL);
|
||||||
|
if (err != EFI_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
boot_entry_add_type1(config, device, root_dir, u"\\loader\\entries", f->FileName, content, loaded_image_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2081,6 +2095,139 @@ static void config_add_entry_windows(Config *config, EFI_HANDLE *device, EFI_FIL
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void boot_entry_add_type2(
|
||||||
|
Config *config,
|
||||||
|
EFI_HANDLE *device,
|
||||||
|
EFI_FILE *dir,
|
||||||
|
const uint16_t *filename) {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SECTION_CMDLINE,
|
||||||
|
SECTION_OSREL,
|
||||||
|
_SECTION_MAX,
|
||||||
|
};
|
||||||
|
static const char * const section_names[_SECTION_MAX + 1] = {
|
||||||
|
[SECTION_CMDLINE] = ".cmdline",
|
||||||
|
[SECTION_OSREL] = ".osrel",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
EFI_STATUS err;
|
||||||
|
|
||||||
|
assert(config);
|
||||||
|
assert(device);
|
||||||
|
assert(dir);
|
||||||
|
assert(filename);
|
||||||
|
|
||||||
|
/* Look for .osrel and .cmdline sections in the .efi binary */
|
||||||
|
PeSectionVector sections[_SECTION_MAX] = {};
|
||||||
|
err = pe_file_locate_sections(dir, filename, section_names, sections);
|
||||||
|
if (err != EFI_SUCCESS || !PE_SECTION_VECTOR_IS_SET(sections + SECTION_OSREL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_cleanup_free_ char *content = NULL;
|
||||||
|
err = file_read(dir,
|
||||||
|
filename,
|
||||||
|
sections[SECTION_OSREL].file_offset,
|
||||||
|
sections[SECTION_OSREL].size,
|
||||||
|
&content,
|
||||||
|
/* ret_size= */ NULL);
|
||||||
|
if (err != EFI_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_cleanup_free_ char16_t *os_pretty_name = NULL, *os_image_id = NULL, *os_name = NULL, *os_id = NULL,
|
||||||
|
*os_image_version = NULL, *os_version = NULL, *os_version_id = NULL, *os_build_id = NULL;
|
||||||
|
char *line, *key, *value;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
/* read properties from the embedded os-release file */
|
||||||
|
while ((line = line_get_key_value(content, "=", &pos, &key, &value)))
|
||||||
|
if (streq8(key, "PRETTY_NAME")) {
|
||||||
|
free(os_pretty_name);
|
||||||
|
os_pretty_name = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "IMAGE_ID")) {
|
||||||
|
free(os_image_id);
|
||||||
|
os_image_id = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "NAME")) {
|
||||||
|
free(os_name);
|
||||||
|
os_name = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "ID")) {
|
||||||
|
free(os_id);
|
||||||
|
os_id = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "IMAGE_VERSION")) {
|
||||||
|
free(os_image_version);
|
||||||
|
os_image_version = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "VERSION")) {
|
||||||
|
free(os_version);
|
||||||
|
os_version = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "VERSION_ID")) {
|
||||||
|
free(os_version_id);
|
||||||
|
os_version_id = xstr8_to_16(value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "BUILD_ID")) {
|
||||||
|
free(os_build_id);
|
||||||
|
os_build_id = xstr8_to_16(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char16_t *good_name, *good_version, *good_sort_key;
|
||||||
|
if (!bootspec_pick_name_version_sort_key(
|
||||||
|
os_pretty_name,
|
||||||
|
os_image_id,
|
||||||
|
os_name,
|
||||||
|
os_id,
|
||||||
|
os_image_version,
|
||||||
|
os_version,
|
||||||
|
os_version_id,
|
||||||
|
os_build_id,
|
||||||
|
&good_name,
|
||||||
|
&good_version,
|
||||||
|
&good_sort_key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BootEntry *entry = xnew(BootEntry, 1);
|
||||||
|
*entry = (BootEntry) {
|
||||||
|
.id = xstrdup16(filename),
|
||||||
|
.type = LOADER_UNIFIED_LINUX,
|
||||||
|
.title = xstrdup16(good_name),
|
||||||
|
.version = xstrdup16(good_version),
|
||||||
|
.device = device,
|
||||||
|
.loader = xasprintf("\\EFI\\Linux\\%ls", filename),
|
||||||
|
.sort_key = xstrdup16(good_sort_key),
|
||||||
|
.key = 'l',
|
||||||
|
.tries_done = -1,
|
||||||
|
.tries_left = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
strtolower16(entry->id);
|
||||||
|
config_add_entry(config, entry);
|
||||||
|
boot_entry_parse_tries(entry, u"\\EFI\\Linux", filename, u".efi");
|
||||||
|
|
||||||
|
if (!PE_SECTION_VECTOR_IS_SET(sections + SECTION_CMDLINE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
content = mfree(content);
|
||||||
|
|
||||||
|
/* read the embedded cmdline file */
|
||||||
|
size_t cmdline_len;
|
||||||
|
err = file_read(dir,
|
||||||
|
filename,
|
||||||
|
sections[SECTION_CMDLINE].file_offset,
|
||||||
|
sections[SECTION_CMDLINE].size,
|
||||||
|
&content,
|
||||||
|
&cmdline_len);
|
||||||
|
if (err == EFI_SUCCESS) {
|
||||||
|
entry->options = xstrn8_to_16(content, cmdline_len);
|
||||||
|
mangle_stub_cmdline(entry->options);
|
||||||
|
entry->options_implied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void config_load_type2_entries(
|
static void config_load_type2_entries(
|
||||||
Config *config,
|
Config *config,
|
||||||
EFI_HANDLE *device,
|
EFI_HANDLE *device,
|
||||||
@ -2102,26 +2249,6 @@ static void config_load_type2_entries(
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
enum {
|
|
||||||
SECTION_CMDLINE,
|
|
||||||
SECTION_OSREL,
|
|
||||||
_SECTION_MAX,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * const section_names[_SECTION_MAX + 1] = {
|
|
||||||
[SECTION_CMDLINE] = ".cmdline",
|
|
||||||
[SECTION_OSREL] = ".osrel",
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
_cleanup_free_ char16_t *os_pretty_name = NULL, *os_image_id = NULL, *os_name = NULL, *os_id = NULL,
|
|
||||||
*os_image_version = NULL, *os_version = NULL, *os_version_id = NULL, *os_build_id = NULL;
|
|
||||||
const char16_t *good_name, *good_version, *good_sort_key;
|
|
||||||
_cleanup_free_ char *content = NULL;
|
|
||||||
PeSectionVector sections[_SECTION_MAX] = {};
|
|
||||||
char *line, *key, *value;
|
|
||||||
size_t pos = 0;
|
|
||||||
|
|
||||||
err = readdir(linux_dir, &f, &f_size);
|
err = readdir(linux_dir, &f, &f_size);
|
||||||
if (err != EFI_SUCCESS || !f)
|
if (err != EFI_SUCCESS || !f)
|
||||||
break;
|
break;
|
||||||
@ -2132,108 +2259,10 @@ static void config_load_type2_entries(
|
|||||||
continue;
|
continue;
|
||||||
if (!endswith_no_case(f->FileName, u".efi"))
|
if (!endswith_no_case(f->FileName, u".efi"))
|
||||||
continue;
|
continue;
|
||||||
if (startswith(f->FileName, u"auto-"))
|
if (startswith_no_case(f->FileName, u"auto-"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* look for .osrel and .cmdline sections in the .efi binary */
|
boot_entry_add_type2(config, device, linux_dir, f->FileName);
|
||||||
err = pe_file_locate_sections(linux_dir, f->FileName, section_names, sections);
|
|
||||||
if (err != EFI_SUCCESS || !PE_SECTION_VECTOR_IS_SET(sections + SECTION_OSREL))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
err = file_read(linux_dir,
|
|
||||||
f->FileName,
|
|
||||||
sections[SECTION_OSREL].file_offset,
|
|
||||||
sections[SECTION_OSREL].size,
|
|
||||||
&content,
|
|
||||||
NULL);
|
|
||||||
if (err != EFI_SUCCESS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* read properties from the embedded os-release file */
|
|
||||||
while ((line = line_get_key_value(content, "=", &pos, &key, &value)))
|
|
||||||
if (streq8(key, "PRETTY_NAME")) {
|
|
||||||
free(os_pretty_name);
|
|
||||||
os_pretty_name = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "IMAGE_ID")) {
|
|
||||||
free(os_image_id);
|
|
||||||
os_image_id = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "NAME")) {
|
|
||||||
free(os_name);
|
|
||||||
os_name = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "ID")) {
|
|
||||||
free(os_id);
|
|
||||||
os_id = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "IMAGE_VERSION")) {
|
|
||||||
free(os_image_version);
|
|
||||||
os_image_version = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "VERSION")) {
|
|
||||||
free(os_version);
|
|
||||||
os_version = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "VERSION_ID")) {
|
|
||||||
free(os_version_id);
|
|
||||||
os_version_id = xstr8_to_16(value);
|
|
||||||
|
|
||||||
} else if (streq8(key, "BUILD_ID")) {
|
|
||||||
free(os_build_id);
|
|
||||||
os_build_id = xstr8_to_16(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bootspec_pick_name_version_sort_key(
|
|
||||||
os_pretty_name,
|
|
||||||
os_image_id,
|
|
||||||
os_name,
|
|
||||||
os_id,
|
|
||||||
os_image_version,
|
|
||||||
os_version,
|
|
||||||
os_version_id,
|
|
||||||
os_build_id,
|
|
||||||
&good_name,
|
|
||||||
&good_version,
|
|
||||||
&good_sort_key))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BootEntry *entry = xnew(BootEntry, 1);
|
|
||||||
*entry = (BootEntry) {
|
|
||||||
.id = xstrdup16(f->FileName),
|
|
||||||
.type = LOADER_UNIFIED_LINUX,
|
|
||||||
.title = xstrdup16(good_name),
|
|
||||||
.version = xstrdup16(good_version),
|
|
||||||
.device = device,
|
|
||||||
.loader = xasprintf("\\EFI\\Linux\\%ls", f->FileName),
|
|
||||||
.sort_key = xstrdup16(good_sort_key),
|
|
||||||
.key = 'l',
|
|
||||||
.tries_done = -1,
|
|
||||||
.tries_left = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
strtolower16(entry->id);
|
|
||||||
config_add_entry(config, entry);
|
|
||||||
boot_entry_parse_tries(entry, u"\\EFI\\Linux", f->FileName, u".efi");
|
|
||||||
|
|
||||||
if (!PE_SECTION_VECTOR_IS_SET(sections + SECTION_CMDLINE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
content = mfree(content);
|
|
||||||
|
|
||||||
/* read the embedded cmdline file */
|
|
||||||
size_t cmdline_len;
|
|
||||||
err = file_read(linux_dir,
|
|
||||||
f->FileName,
|
|
||||||
sections[SECTION_CMDLINE].file_offset,
|
|
||||||
sections[SECTION_CMDLINE].size,
|
|
||||||
&content,
|
|
||||||
&cmdline_len);
|
|
||||||
if (err == EFI_SUCCESS) {
|
|
||||||
entry->options = xstrn8_to_16(content, cmdline_len);
|
|
||||||
mangle_stub_cmdline(entry->options);
|
|
||||||
entry->options_implied = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,22 +178,22 @@ static bool pe_section_name_equal(const char *a, const char *b) {
|
|||||||
static void pe_locate_sections(
|
static void pe_locate_sections(
|
||||||
const PeSectionHeader section_table[],
|
const PeSectionHeader section_table[],
|
||||||
size_t n_section_table,
|
size_t n_section_table,
|
||||||
const char * const sections[],
|
const char *const section_names[],
|
||||||
size_t validate_base,
|
size_t validate_base,
|
||||||
PeSectionVector *ret_sections) {
|
PeSectionVector sections[]) {
|
||||||
|
|
||||||
assert(section_table || n_section_table == 0);
|
assert(section_table || n_section_table == 0);
|
||||||
|
assert(section_names);
|
||||||
assert(sections);
|
assert(sections);
|
||||||
assert(ret_sections);
|
|
||||||
|
|
||||||
/* Searches for the sections listed in 'sections[]' within the section table. Validates the resulted
|
/* Searches for the sections listed in 'sections[]' within the section table. Validates the resulted
|
||||||
* data. If 'validate_base' is non-zero also takes base offset when loaded into memory into account for
|
* data. If 'validate_base' is non-zero also takes base offset when loaded into memory into account for
|
||||||
* qchecking for overflows. */
|
* qchecking for overflows. */
|
||||||
|
|
||||||
for (size_t i = 0; sections[i]; i++)
|
for (size_t i = 0; section_names[i]; i++)
|
||||||
FOREACH_ARRAY(j, section_table, n_section_table) {
|
FOREACH_ARRAY(j, section_table, n_section_table) {
|
||||||
|
|
||||||
if (!pe_section_name_equal((const char*) j->Name, sections[i]))
|
if (!pe_section_name_equal((const char*) j->Name, section_names[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Overflow check: ignore sections that are impossibly large, relative to the file
|
/* Overflow check: ignore sections that are impossibly large, relative to the file
|
||||||
@ -220,7 +220,7 @@ static void pe_locate_sections(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* At this time, the sizes and offsets have been validated. Store them away */
|
/* At this time, the sizes and offsets have been validated. Store them away */
|
||||||
ret_sections[i] = (PeSectionVector) {
|
sections[i] = (PeSectionVector) {
|
||||||
.size = j->VirtualSize,
|
.size = j->VirtualSize,
|
||||||
.file_offset = j->PointerToRawData,
|
.file_offset = j->PointerToRawData,
|
||||||
.memory_offset = j->VirtualAddress,
|
.memory_offset = j->VirtualAddress,
|
||||||
@ -232,17 +232,19 @@ static void pe_locate_sections(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const PeFileHeader *pe) {
|
static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const PeFileHeader *pe) {
|
||||||
static const char *sections[] = { ".compat", NULL };
|
|
||||||
PeSectionVector vector = {};
|
|
||||||
|
|
||||||
/* The kernel may provide alternative PE entry points for different PE architectures. This allows
|
/* The kernel may provide alternative PE entry points for different PE architectures. This allows
|
||||||
* booting a 64-bit kernel on 32-bit EFI that is otherwise running on a 64-bit CPU. The locations of any
|
* booting a 64-bit kernel on 32-bit EFI that is otherwise running on a 64-bit CPU. The locations of any
|
||||||
* such compat entry points are located in a special PE section. */
|
* such compat entry points are located in a special PE section. */
|
||||||
|
|
||||||
|
assert(dos);
|
||||||
|
assert(pe);
|
||||||
|
|
||||||
|
static const char *const section_names[] = { ".compat", NULL };
|
||||||
|
PeSectionVector vector = {};
|
||||||
pe_locate_sections(
|
pe_locate_sections(
|
||||||
(const PeSectionHeader *) ((const uint8_t *) dos + section_table_offset(dos, pe)),
|
(const PeSectionHeader *) ((const uint8_t *) dos + section_table_offset(dos, pe)),
|
||||||
pe->FileHeader.NumberOfSections,
|
pe->FileHeader.NumberOfSections,
|
||||||
sections,
|
section_names,
|
||||||
PTR_TO_SIZE(dos),
|
PTR_TO_SIZE(dos),
|
||||||
&vector);
|
&vector);
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const
|
|||||||
size_t addr = vector.memory_offset, size = vector.size;
|
size_t addr = vector.memory_offset, size = vector.size;
|
||||||
|
|
||||||
while (size >= sizeof(LinuxPeCompat1) && addr % alignof(LinuxPeCompat1) == 0) {
|
while (size >= sizeof(LinuxPeCompat1) && addr % alignof(LinuxPeCompat1) == 0) {
|
||||||
LinuxPeCompat1 *compat = (LinuxPeCompat1 *) ((uint8_t *) dos + addr);
|
const LinuxPeCompat1 *compat = (const LinuxPeCompat1 *) ((const uint8_t *) dos + addr);
|
||||||
|
|
||||||
if (compat->type == 0 || compat->size == 0 || compat->size > size)
|
if (compat->type == 0 || compat->size == 0 || compat->size > size)
|
||||||
break;
|
break;
|
||||||
@ -308,16 +310,16 @@ EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address) {
|
|||||||
|
|
||||||
EFI_STATUS pe_memory_locate_sections(
|
EFI_STATUS pe_memory_locate_sections(
|
||||||
const void *base,
|
const void *base,
|
||||||
const char* const sections[],
|
const char *const section_names[],
|
||||||
PeSectionVector *ret_sections) {
|
PeSectionVector sections[]) {
|
||||||
|
|
||||||
const DosFileHeader *dos;
|
const DosFileHeader *dos;
|
||||||
const PeFileHeader *pe;
|
const PeFileHeader *pe;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
assert(base);
|
assert(base);
|
||||||
|
assert(section_names);
|
||||||
assert(sections);
|
assert(sections);
|
||||||
assert(ret_sections);
|
|
||||||
|
|
||||||
dos = (const DosFileHeader *) base;
|
dos = (const DosFileHeader *) base;
|
||||||
if (!verify_dos(dos))
|
if (!verify_dos(dos))
|
||||||
@ -331,9 +333,9 @@ EFI_STATUS pe_memory_locate_sections(
|
|||||||
pe_locate_sections(
|
pe_locate_sections(
|
||||||
(const PeSectionHeader *) ((const uint8_t *) base + offset),
|
(const PeSectionHeader *) ((const uint8_t *) base + offset),
|
||||||
pe->FileHeader.NumberOfSections,
|
pe->FileHeader.NumberOfSections,
|
||||||
sections,
|
section_names,
|
||||||
PTR_TO_SIZE(base),
|
PTR_TO_SIZE(base),
|
||||||
ret_sections);
|
sections);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -341,8 +343,8 @@ EFI_STATUS pe_memory_locate_sections(
|
|||||||
EFI_STATUS pe_file_locate_sections(
|
EFI_STATUS pe_file_locate_sections(
|
||||||
EFI_FILE *dir,
|
EFI_FILE *dir,
|
||||||
const char16_t *path,
|
const char16_t *path,
|
||||||
const char * const sections[],
|
const char *const section_names[],
|
||||||
PeSectionVector *ret_sections) {
|
PeSectionVector sections[]) {
|
||||||
_cleanup_free_ PeSectionHeader *section_table = NULL;
|
_cleanup_free_ PeSectionHeader *section_table = NULL;
|
||||||
_cleanup_(file_closep) EFI_FILE *handle = NULL;
|
_cleanup_(file_closep) EFI_FILE *handle = NULL;
|
||||||
DosFileHeader dos;
|
DosFileHeader dos;
|
||||||
@ -352,8 +354,8 @@ EFI_STATUS pe_file_locate_sections(
|
|||||||
|
|
||||||
assert(dir);
|
assert(dir);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
assert(section_names);
|
||||||
assert(sections);
|
assert(sections);
|
||||||
assert(ret_sections);
|
|
||||||
|
|
||||||
err = dir->Open(dir, &handle, (char16_t *) path, EFI_FILE_MODE_READ, 0ULL);
|
err = dir->Open(dir, &handle, (char16_t *) path, EFI_FILE_MODE_READ, 0ULL);
|
||||||
if (err != EFI_SUCCESS)
|
if (err != EFI_SUCCESS)
|
||||||
@ -402,9 +404,9 @@ EFI_STATUS pe_file_locate_sections(
|
|||||||
pe_locate_sections(
|
pe_locate_sections(
|
||||||
section_table,
|
section_table,
|
||||||
pe.FileHeader.NumberOfSections,
|
pe.FileHeader.NumberOfSections,
|
||||||
sections,
|
section_names,
|
||||||
/* validate_base= */ 0, /* don't validate base */
|
/* validate_base= */ 0, /* don't validate base */
|
||||||
ret_sections);
|
sections);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@ static inline bool PE_SECTION_VECTOR_IS_SET(const PeSectionVector *v) {
|
|||||||
|
|
||||||
EFI_STATUS pe_memory_locate_sections(
|
EFI_STATUS pe_memory_locate_sections(
|
||||||
const void *base,
|
const void *base,
|
||||||
const char * const sections[],
|
const char *const section_names[],
|
||||||
PeSectionVector *ret_sections);
|
PeSectionVector sections[]);
|
||||||
|
|
||||||
EFI_STATUS pe_file_locate_sections(
|
EFI_STATUS pe_file_locate_sections(
|
||||||
EFI_FILE *dir,
|
EFI_FILE *dir,
|
||||||
const char16_t *path,
|
const char16_t *path,
|
||||||
const char * const sections[],
|
const char *const section_names[],
|
||||||
PeSectionVector *ret_sections);
|
PeSectionVector sections[]);
|
||||||
|
|
||||||
EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address);
|
EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address);
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "efivars.h"
|
#include "efivars.h"
|
||||||
|
|
||||||
|
/* Never try to read more than 16G into memory (and on 32bit 1G) */
|
||||||
|
#define FILE_READ_MAX MIN(SIZE_MAX/4, UINT64_C(16)*1024U*1024U*1024U)
|
||||||
|
|
||||||
void convert_efi_path(char16_t *path) {
|
void convert_efi_path(char16_t *path) {
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
@ -39,19 +42,17 @@ static bool shall_be_whitespace(char16_t c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char16_t* mangle_stub_cmdline(char16_t *cmdline) {
|
char16_t* mangle_stub_cmdline(char16_t *cmdline) {
|
||||||
char16_t *p, *q, *e;
|
|
||||||
|
|
||||||
if (!cmdline)
|
if (!cmdline)
|
||||||
return cmdline;
|
return cmdline;
|
||||||
|
|
||||||
p = q = cmdline;
|
|
||||||
|
|
||||||
/* Skip initial whitespace */
|
/* Skip initial whitespace */
|
||||||
while (shall_be_whitespace(*p))
|
const char16_t *p = cmdline;
|
||||||
|
while (*p != 0 && shall_be_whitespace(*p))
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
/* Turn inner control characters into proper spaces */
|
/* Turn inner control characters into proper spaces */
|
||||||
for (e = p; *p != 0; p++) {
|
char16_t *e = cmdline;
|
||||||
|
for (char16_t *q = cmdline; *p != 0; p++) {
|
||||||
if (shall_be_whitespace(*p)) {
|
if (shall_be_whitespace(*p)) {
|
||||||
*(q++) = ' ';
|
*(q++) = ' ';
|
||||||
continue;
|
continue;
|
||||||
@ -107,7 +108,7 @@ EFI_STATUS chunked_read(EFI_FILE *file, size_t *size, void *buf) {
|
|||||||
EFI_STATUS file_read(
|
EFI_STATUS file_read(
|
||||||
EFI_FILE *dir,
|
EFI_FILE *dir,
|
||||||
const char16_t *name,
|
const char16_t *name,
|
||||||
uint64_t off,
|
uint64_t offset,
|
||||||
size_t size,
|
size_t size,
|
||||||
char **ret,
|
char **ret,
|
||||||
size_t *ret_size) {
|
size_t *ret_size) {
|
||||||
@ -131,14 +132,17 @@ EFI_STATUS file_read(
|
|||||||
if (err != EFI_SUCCESS)
|
if (err != EFI_SUCCESS)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (info->FileSize > SIZE_MAX)
|
if (info->FileSize > SIZE_MAX) /* overflow check */
|
||||||
return EFI_BAD_BUFFER_SIZE;
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
|
|
||||||
size = info->FileSize;
|
size = info->FileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (off > 0) {
|
if (size > FILE_READ_MAX) /* make sure we don't read unbounded data into RAM */
|
||||||
err = handle->SetPosition(handle, off);
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
|
|
||||||
|
if (offset > 0) {
|
||||||
|
err = handle->SetPosition(handle, offset);
|
||||||
if (err != EFI_SUCCESS)
|
if (err != EFI_SUCCESS)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ char16_t *xstr8_to_path(const char *stra);
|
|||||||
char16_t *mangle_stub_cmdline(char16_t *cmdline);
|
char16_t *mangle_stub_cmdline(char16_t *cmdline);
|
||||||
|
|
||||||
EFI_STATUS chunked_read(EFI_FILE *file, size_t *size, void *buf);
|
EFI_STATUS chunked_read(EFI_FILE *file, size_t *size, void *buf);
|
||||||
EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, uint64_t off, size_t size, char **content, size_t *content_size);
|
EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, uint64_t offset, size_t size, char **content, size_t *content_size);
|
||||||
|
|
||||||
static inline void file_closep(EFI_FILE **handle) {
|
static inline void file_closep(EFI_FILE **handle) {
|
||||||
if (!*handle)
|
if (!*handle)
|
||||||
|
@ -1017,14 +1017,6 @@ static int validate_stub(void) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = compare_reported_pcr_nr(TPM2_PCR_KERNEL_CONFIG, EFI_LOADER_VARIABLE(StubPcrKernelParameters), "kernel parameters");
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = compare_reported_pcr_nr(TPM2_PCR_SYSEXTS, EFI_LOADER_VARIABLE(StubPcrInitRDSysExts), "initrd system extension images");
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
STRV_FOREACH(bank, arg_banks) {
|
STRV_FOREACH(bank, arg_banks) {
|
||||||
_cleanup_free_ char *b = NULL, *p = NULL;
|
_cleanup_free_ char *b = NULL, *p = NULL;
|
||||||
|
|
||||||
@ -1049,12 +1041,6 @@ static int validate_stub(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int verb_status(int argc, char *argv[], void *userdata) {
|
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||||
static const uint32_t relevant_pcrs[] = {
|
|
||||||
TPM2_PCR_KERNEL_BOOT,
|
|
||||||
TPM2_PCR_KERNEL_CONFIG,
|
|
||||||
TPM2_PCR_SYSEXTS,
|
|
||||||
};
|
|
||||||
|
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1062,72 +1048,69 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (size_t i = 0; i < ELEMENTSOF(relevant_pcrs); i++) {
|
STRV_FOREACH(bank, arg_banks) {
|
||||||
|
_cleanup_free_ char *b = NULL, *p = NULL, *s = NULL;
|
||||||
|
_cleanup_free_ void *h = NULL;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
STRV_FOREACH(bank, arg_banks) {
|
b = strdup(*bank);
|
||||||
_cleanup_free_ char *b = NULL, *p = NULL, *s = NULL;
|
if (!b)
|
||||||
_cleanup_free_ void *h = NULL;
|
return log_oom();
|
||||||
size_t l;
|
|
||||||
|
|
||||||
b = strdup(*bank);
|
if (asprintf(&p, "/sys/class/tpm/tpm0/pcr-%s/%" PRIu32, ascii_strlower(b), (uint32_t) TPM2_PCR_KERNEL_BOOT) < 0)
|
||||||
if (!b)
|
return log_oom();
|
||||||
|
|
||||||
|
r = read_virtual_file(p, 4096, &s, NULL);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
continue;
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to read '%s': %m", p);
|
||||||
|
|
||||||
|
r = unhexmem(strstrip(s), &h, &l);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to decode PCR value '%s': %m", s);
|
||||||
|
|
||||||
|
if (arg_json_format_flags & SD_JSON_FORMAT_OFF) {
|
||||||
|
_cleanup_free_ char *f = NULL;
|
||||||
|
|
||||||
|
f = hexmem(h, l);
|
||||||
|
if (!h)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
if (asprintf(&p, "/sys/class/tpm/tpm0/pcr-%s/%" PRIu32, ascii_strlower(b), relevant_pcrs[i]) < 0)
|
if (bank == arg_banks) {
|
||||||
return log_oom();
|
/* before the first line for each PCR, write a short descriptive text to
|
||||||
|
* stderr, and leave the primary content on stdout */
|
||||||
r = read_virtual_file(p, 4096, &s, NULL);
|
fflush(stdout);
|
||||||
if (r == -ENOENT)
|
fprintf(stderr, "%s# PCR[%" PRIu32 "] %s%s%s\n",
|
||||||
continue;
|
ansi_grey(),
|
||||||
if (r < 0)
|
(uint32_t) TPM2_PCR_KERNEL_BOOT,
|
||||||
return log_error_errno(r, "Failed to read '%s': %m", p);
|
tpm2_pcr_index_to_string(TPM2_PCR_KERNEL_BOOT),
|
||||||
|
memeqzero(h, l) ? " (NOT SET!)" : "",
|
||||||
r = unhexmem(strstrip(s), &h, &l);
|
ansi_normal());
|
||||||
if (r < 0)
|
fflush(stderr);
|
||||||
return log_error_errno(r, "Failed to decode PCR value '%s': %m", s);
|
|
||||||
|
|
||||||
if (arg_json_format_flags & SD_JSON_FORMAT_OFF) {
|
|
||||||
_cleanup_free_ char *f = NULL;
|
|
||||||
|
|
||||||
f = hexmem(h, l);
|
|
||||||
if (!h)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (bank == arg_banks) {
|
|
||||||
/* before the first line for each PCR, write a short descriptive text to
|
|
||||||
* stderr, and leave the primary content on stdout */
|
|
||||||
fflush(stdout);
|
|
||||||
fprintf(stderr, "%s# PCR[%" PRIu32 "] %s%s%s\n",
|
|
||||||
ansi_grey(),
|
|
||||||
relevant_pcrs[i],
|
|
||||||
tpm2_pcr_index_to_string(relevant_pcrs[i]),
|
|
||||||
memeqzero(h, l) ? " (NOT SET!)" : "",
|
|
||||||
ansi_normal());
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%" PRIu32 ":%s=%s\n", relevant_pcrs[i], b, f);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *bv = NULL, *a = NULL;
|
|
||||||
|
|
||||||
r = sd_json_buildo(
|
|
||||||
&bv,
|
|
||||||
SD_JSON_BUILD_PAIR("pcr", SD_JSON_BUILD_INTEGER(relevant_pcrs[i])),
|
|
||||||
SD_JSON_BUILD_PAIR("hash", SD_JSON_BUILD_HEX(h, l)));
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to build JSON object: %m");
|
|
||||||
|
|
||||||
a = sd_json_variant_ref(sd_json_variant_by_key(v, b));
|
|
||||||
|
|
||||||
r = sd_json_variant_append_array(&a, bv);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to append PCR entry to JSON array: %m");
|
|
||||||
|
|
||||||
r = sd_json_variant_set_field(&v, b, a);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to add bank info to object: %m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("%" PRIu32 ":%s=%s\n", (uint32_t) TPM2_PCR_KERNEL_BOOT, b, f);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *bv = NULL, *a = NULL;
|
||||||
|
|
||||||
|
r = sd_json_buildo(
|
||||||
|
&bv,
|
||||||
|
SD_JSON_BUILD_PAIR("pcr", SD_JSON_BUILD_INTEGER(TPM2_PCR_KERNEL_BOOT)),
|
||||||
|
SD_JSON_BUILD_PAIR("hash", SD_JSON_BUILD_HEX(h, l)));
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to build JSON object: %m");
|
||||||
|
|
||||||
|
a = sd_json_variant_ref(sd_json_variant_by_key(v, b));
|
||||||
|
|
||||||
|
r = sd_json_variant_append_array(&a, bv);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to append PCR entry to JSON array: %m");
|
||||||
|
|
||||||
|
r = sd_json_variant_set_field(&v, b, a);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to add bank info to object: %m");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1264,6 +1264,13 @@ CONFIG_ITEMS = [
|
|||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
ConfigItem(
|
||||||
|
('--config', '-c'),
|
||||||
|
metavar = 'PATH',
|
||||||
|
type = pathlib.Path,
|
||||||
|
help = 'configuration file',
|
||||||
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
'--linux',
|
'--linux',
|
||||||
type = pathlib.Path,
|
type = pathlib.Path,
|
||||||
@ -1271,6 +1278,20 @@ CONFIG_ITEMS = [
|
|||||||
config_key = 'UKI/Linux',
|
config_key = 'UKI/Linux',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
ConfigItem(
|
||||||
|
'--os-release',
|
||||||
|
metavar = 'TEXT|@PATH',
|
||||||
|
help = 'path to os-release file [.osrel section]',
|
||||||
|
config_key = 'UKI/OSRelease',
|
||||||
|
),
|
||||||
|
|
||||||
|
ConfigItem(
|
||||||
|
'--cmdline',
|
||||||
|
metavar = 'TEXT|@PATH',
|
||||||
|
help = 'kernel command line [.cmdline section]',
|
||||||
|
config_key = 'UKI/Cmdline',
|
||||||
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
'--initrd',
|
'--initrd',
|
||||||
metavar = 'INITRD',
|
metavar = 'INITRD',
|
||||||
@ -1290,24 +1311,11 @@ CONFIG_ITEMS = [
|
|||||||
),
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
('--config', '-c'),
|
'--splash',
|
||||||
metavar = 'PATH',
|
metavar = 'BMP',
|
||||||
type = pathlib.Path,
|
type = pathlib.Path,
|
||||||
help = 'configuration file',
|
help = 'splash image bitmap file [.splash section]',
|
||||||
),
|
config_key = 'UKI/Splash',
|
||||||
|
|
||||||
ConfigItem(
|
|
||||||
'--cmdline',
|
|
||||||
metavar = 'TEXT|@PATH',
|
|
||||||
help = 'kernel command line [.cmdline section]',
|
|
||||||
config_key = 'UKI/Cmdline',
|
|
||||||
),
|
|
||||||
|
|
||||||
ConfigItem(
|
|
||||||
'--os-release',
|
|
||||||
metavar = 'TEXT|@PATH',
|
|
||||||
help = 'path to os-release file [.osrel section]',
|
|
||||||
config_key = 'UKI/OSRelease',
|
|
||||||
),
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
@ -1317,13 +1325,23 @@ CONFIG_ITEMS = [
|
|||||||
help = 'Device Tree file [.dtb section]',
|
help = 'Device Tree file [.dtb section]',
|
||||||
config_key = 'UKI/DeviceTree',
|
config_key = 'UKI/DeviceTree',
|
||||||
),
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
'--splash',
|
'--uname',
|
||||||
metavar = 'BMP',
|
metavar='VERSION',
|
||||||
type = pathlib.Path,
|
help='"uname -r" information [.uname section]',
|
||||||
help = 'splash image bitmap file [.splash section]',
|
config_key = 'UKI/Uname',
|
||||||
config_key = 'UKI/Splash',
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
ConfigItem(
|
||||||
|
'--sbat',
|
||||||
|
metavar = 'TEXT|@PATH',
|
||||||
|
help = 'SBAT policy [.sbat section]',
|
||||||
|
default = [],
|
||||||
|
action = 'append',
|
||||||
|
config_key = 'UKI/SBAT',
|
||||||
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
'--pcrpkey',
|
'--pcrpkey',
|
||||||
metavar = 'KEY',
|
metavar = 'KEY',
|
||||||
@ -1331,11 +1349,14 @@ CONFIG_ITEMS = [
|
|||||||
help = 'embedded public key to seal secrets to [.pcrpkey section]',
|
help = 'embedded public key to seal secrets to [.pcrpkey section]',
|
||||||
config_key = 'UKI/PCRPKey',
|
config_key = 'UKI/PCRPKey',
|
||||||
),
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
'--uname',
|
'--section',
|
||||||
metavar='VERSION',
|
dest = 'sections',
|
||||||
help='"uname -r" information [.uname section]',
|
metavar = 'NAME:TEXT|@PATH',
|
||||||
config_key = 'UKI/Uname',
|
action = 'append',
|
||||||
|
default = [],
|
||||||
|
help = 'section as name and contents [NAME section] or section to print',
|
||||||
),
|
),
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
@ -1353,24 +1374,6 @@ CONFIG_ITEMS = [
|
|||||||
config_key = 'UKI/Stub',
|
config_key = 'UKI/Stub',
|
||||||
),
|
),
|
||||||
|
|
||||||
ConfigItem(
|
|
||||||
'--sbat',
|
|
||||||
metavar = 'TEXT|@PATH',
|
|
||||||
help = 'SBAT policy [.sbat section]',
|
|
||||||
default = [],
|
|
||||||
action = 'append',
|
|
||||||
config_key = 'UKI/SBAT',
|
|
||||||
),
|
|
||||||
|
|
||||||
ConfigItem(
|
|
||||||
'--section',
|
|
||||||
dest = 'sections',
|
|
||||||
metavar = 'NAME:TEXT|@PATH',
|
|
||||||
action = 'append',
|
|
||||||
default = [],
|
|
||||||
help = 'section as name and contents [NAME section] or section to print',
|
|
||||||
),
|
|
||||||
|
|
||||||
ConfigItem(
|
ConfigItem(
|
||||||
'--pcr-banks',
|
'--pcr-banks',
|
||||||
metavar = 'BANK…',
|
metavar = 'BANK…',
|
||||||
@ -1636,7 +1639,7 @@ def finalize_options(opts):
|
|||||||
elif len(opts.positional) == 1 and opts.positional[0] in VERBS:
|
elif len(opts.positional) == 1 and opts.positional[0] in VERBS:
|
||||||
opts.verb = opts.positional[0]
|
opts.verb = opts.positional[0]
|
||||||
elif opts.linux or opts.initrd:
|
elif opts.linux or opts.initrd:
|
||||||
raise ValueError('--linux/--initrd options cannot be used with positional arguments')
|
raise ValueError('--linux=/--initrd= options cannot be used with positional arguments')
|
||||||
else:
|
else:
|
||||||
print("Assuming obsolete command line syntax with no verb. Please use 'build'.")
|
print("Assuming obsolete command line syntax with no verb. Please use 'build'.")
|
||||||
if opts.positional:
|
if opts.positional:
|
||||||
|
Loading…
Reference in New Issue
Block a user