mirror of
https://github.com/systemd/systemd
synced 2024-10-15 04:24:19 +00:00
Merge pull request #31872 from tfg13/main
stub+ukify: Add support for UKI .ucode section
This commit is contained in:
commit
bf49f3bb44
|
@ -75,9 +75,9 @@
|
|||
<listitem><para>Pre-calculate the expected values seen in PCR register 11 after boot-up of a unified
|
||||
kernel image consisting of the components specified with <option>--linux=</option>,
|
||||
<option>--osrel=</option>, <option>--cmdline=</option>, <option>--initrd=</option>,
|
||||
<option>--splash=</option>, <option>--dtb=</option>, <option>--uname=</option>,
|
||||
<option>--sbat=</option>, <option>--pcrpkey=</option> see below. Only <option>--linux=</option> is
|
||||
mandatory. (Alternatively, specify <option>--current</option> to use the current values of PCR
|
||||
<option>--ucode=</option>, <option>--splash=</option>, <option>--dtb=</option>,
|
||||
<option>--uname=</option>, <option>--sbat=</option>, <option>--pcrpkey=</option> see below.
|
||||
Only <option>--linux=</option> is mandatory. (Alternatively, specify <option>--current</option> to use the current values of PCR
|
||||
register 11 instead.)</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v252"/>
|
||||
|
@ -118,6 +118,7 @@
|
|||
<term><option>--osrel=<replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--cmdline=<replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--initrd=<replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--ucode=<replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--splash=<replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--dtb=<replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--uname=<replaceable>PATH</replaceable></option></term>
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
|
||||
<listitem><para>An <literal>.initrd</literal> section with the initrd.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.ucode</literal> section with an initrd containing microcode, to be handed
|
||||
to the kernel before any other initrd. This initrd must not be compressed.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.splash</literal> section with an image (in the Windows
|
||||
<filename>.BMP</filename> format) to show on screen before invoking the kernel.</para></listitem>
|
||||
|
||||
|
@ -233,7 +236,7 @@
|
|||
core kernel, the embedded initrd and kernel command line (see above for a full list).</para>
|
||||
|
||||
<para>Also note that the Linux kernel will measure all initrds it receives into TPM PCR 9. This means
|
||||
every type of initrd will be measured two or three times: the initrd embedded in the kernel image will be
|
||||
every type of initrd will be measured two or three times: the initrds embedded in the kernel image will be
|
||||
measured to PCR 4, PCR 9 and PCR 11; the initrd synthesized from credentials (and the one synthesized
|
||||
from configuration extensions) will be measured to both PCR 9 and PCR 12; the initrd synthesized from
|
||||
system extensions will be measured to both PCR 4 and PCR 9. Let's summarize the OS resources and the PCRs
|
||||
|
@ -274,6 +277,11 @@
|
|||
<entry>4 + 9 + 11</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Microcode initrd (embedded in unified PE binary)</entry>
|
||||
<entry>4 + 9 + 11</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Default kernel command line (embedded in unified PE binary)</entry>
|
||||
<entry>4 + 11</entry>
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
|
||||
<para>Additional sections will be inserted into the UKI, either automatically or only if a specific
|
||||
option is provided. See the discussions of
|
||||
<varname>Microcode=</varname>/<option>--microcode=</option>,
|
||||
<varname>Cmdline=</varname>/<option>--cmdline=</option>,
|
||||
<varname>OSRelease=</varname>/<option>--os-release=</option>,
|
||||
<varname>DeviceTree=</varname>/<option>--devicetree=</option>,
|
||||
|
@ -302,6 +303,16 @@
|
|||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Microcode=<replaceable>UCODE</replaceable></varname></term>
|
||||
<term><option>--microcode=<replaceable>UCODE</replaceable></option></term>
|
||||
|
||||
<listitem><para>Path to initrd containing microcode updates. If not specified, the section
|
||||
will not be present.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></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>
|
||||
|
|
|
@ -26,28 +26,27 @@ DECLARE_NOALLOC_SECTION(".sdmagic", "#### LoaderInfo: systemd-stub " GIT_VERSION
|
|||
|
||||
DECLARE_SBAT(SBAT_STUB_SECTION_TEXT);
|
||||
|
||||
static EFI_STATUS combine_initrd(
|
||||
EFI_PHYSICAL_ADDRESS initrd_base, size_t initrd_size,
|
||||
const void * const extra_initrds[], const size_t extra_initrd_sizes[], size_t n_extra_initrds,
|
||||
/* Combine initrds by concatenation in memory */
|
||||
static EFI_STATUS combine_initrds(
|
||||
const void * const initrds[], const size_t initrd_sizes[], size_t n_initrds,
|
||||
Pages *ret_initr_pages, size_t *ret_initrd_size) {
|
||||
|
||||
size_t n;
|
||||
size_t n = 0;
|
||||
|
||||
assert(ret_initr_pages);
|
||||
assert(ret_initrd_size);
|
||||
|
||||
/* Combines four initrds into one, by simple concatenation in memory */
|
||||
|
||||
n = ALIGN4(initrd_size); /* main initrd might not be padded yet */
|
||||
|
||||
for (size_t i = 0; i < n_extra_initrds; i++) {
|
||||
if (!extra_initrds[i])
|
||||
for (size_t i = 0; i < n_initrds; i++) {
|
||||
if (!initrds[i])
|
||||
continue;
|
||||
|
||||
if (n > SIZE_MAX - extra_initrd_sizes[i])
|
||||
/* some initrds (the ones from UKI sections) need padding,
|
||||
* pad all to be safe */
|
||||
size_t initrd_size = ALIGN4(initrd_sizes[i]);
|
||||
if (n > SIZE_MAX - initrd_size)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
n += extra_initrd_sizes[i];
|
||||
n += initrd_size;
|
||||
}
|
||||
|
||||
_cleanup_pages_ Pages pages = xmalloc_pages(
|
||||
|
@ -56,27 +55,21 @@ static EFI_STATUS combine_initrd(
|
|||
EFI_SIZE_TO_PAGES(n),
|
||||
UINT32_MAX /* Below 4G boundary. */);
|
||||
uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr);
|
||||
if (initrd_base != 0) {
|
||||
for (size_t i = 0; i < n_initrds; i++) {
|
||||
if (!initrds[i])
|
||||
continue;
|
||||
|
||||
size_t pad;
|
||||
|
||||
/* Order matters, the real initrd must come first, since it might include microcode updates
|
||||
* which the kernel only looks for in the first cpio archive */
|
||||
p = mempcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
|
||||
p = mempcpy(p, initrds[i], initrd_sizes[i]);
|
||||
|
||||
pad = ALIGN4(initrd_size) - initrd_size;
|
||||
pad = ALIGN4(initrd_sizes[i]) - initrd_sizes[i];
|
||||
if (pad > 0) {
|
||||
memzero(p, pad);
|
||||
p += pad;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n_extra_initrds; i++) {
|
||||
if (!extra_initrds[i])
|
||||
continue;
|
||||
|
||||
p = mempcpy(p, extra_initrds[i], extra_initrd_sizes[i]);
|
||||
}
|
||||
|
||||
assert(PHYSICAL_ADDRESS_TO_POINTER(pages.addr + n) == p);
|
||||
|
||||
*ret_initr_pages = pages;
|
||||
|
@ -503,8 +496,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
|||
void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL;
|
||||
char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL;
|
||||
_cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL;
|
||||
size_t linux_size, initrd_size, dt_size, n_dts_addons_global = 0, n_dts_addons_uki = 0;
|
||||
EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base;
|
||||
size_t linux_size, initrd_size, ucode_size, dt_size, n_dts_addons_global = 0, n_dts_addons_uki = 0;
|
||||
EFI_PHYSICAL_ADDRESS linux_base, initrd_base, ucode_base, dt_base;
|
||||
_cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
|
||||
|
@ -792,12 +785,18 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
|||
initrd_size = szs[UNIFIED_SECTION_INITRD];
|
||||
initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0;
|
||||
|
||||
ucode_size = szs[UNIFIED_SECTION_UCODE];
|
||||
ucode_base = ucode_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_UCODE] : 0;
|
||||
|
||||
_cleanup_pages_ Pages initrd_pages = {};
|
||||
if (credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) {
|
||||
/* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
|
||||
err = combine_initrd(
|
||||
initrd_base, initrd_size,
|
||||
if (ucode_base || credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) {
|
||||
/* If we have generated initrds dynamically or there is a microcode initrd, combine them with the built-in initrd. */
|
||||
err = combine_initrds(
|
||||
(const void*const[]) {
|
||||
/* Microcode must always be first as kernel only scans uncompressed cpios
|
||||
* and later initrds might be compressed. */
|
||||
PHYSICAL_ADDRESS_TO_POINTER(ucode_base),
|
||||
PHYSICAL_ADDRESS_TO_POINTER(initrd_base),
|
||||
credential_initrd,
|
||||
global_credential_initrd,
|
||||
sysext_initrd,
|
||||
|
@ -806,6 +805,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
|||
pcrpkey_initrd,
|
||||
},
|
||||
(const size_t[]) {
|
||||
ucode_size,
|
||||
initrd_size,
|
||||
credential_initrd_size,
|
||||
global_credential_initrd_size,
|
||||
sysext_initrd_size,
|
||||
|
@ -813,7 +814,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
|||
pcrsig_initrd_size,
|
||||
pcrpkey_initrd_size,
|
||||
},
|
||||
6,
|
||||
8,
|
||||
&initrd_pages, &initrd_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
|
|
@ -92,6 +92,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||
" --osrel=PATH Path to os-release file %7$s .osrel\n"
|
||||
" --cmdline=PATH Path to file with kernel command line %7$s .cmdline\n"
|
||||
" --initrd=PATH Path to initrd image file %7$s .initrd\n"
|
||||
" --ucode=PATH Path to microcode image file %7$s .ucode\n"
|
||||
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
|
||||
" --dtb=PATH Path to Devicetree file %7$s .dtb\n"
|
||||
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
|
||||
|
@ -133,6 +134,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
ARG_OSREL,
|
||||
ARG_CMDLINE,
|
||||
ARG_INITRD,
|
||||
ARG_UCODE,
|
||||
ARG_SPLASH,
|
||||
ARG_DTB,
|
||||
ARG_UNAME,
|
||||
|
@ -159,6 +161,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
{ "osrel", required_argument, NULL, ARG_OSREL },
|
||||
{ "cmdline", required_argument, NULL, ARG_CMDLINE },
|
||||
{ "initrd", required_argument, NULL, ARG_INITRD },
|
||||
{ "ucode", required_argument, NULL, ARG_UCODE },
|
||||
{ "splash", required_argument, NULL, ARG_SPLASH },
|
||||
{ "dtb", required_argument, NULL, ARG_DTB },
|
||||
{ "uname", required_argument, NULL, ARG_UNAME },
|
||||
|
|
|
@ -13,6 +13,7 @@ const char* const unified_sections[_UNIFIED_SECTION_MAX + 1] = {
|
|||
[UNIFIED_SECTION_OSREL] = ".osrel",
|
||||
[UNIFIED_SECTION_CMDLINE] = ".cmdline",
|
||||
[UNIFIED_SECTION_INITRD] = ".initrd",
|
||||
[UNIFIED_SECTION_UCODE] = ".ucode",
|
||||
[UNIFIED_SECTION_SPLASH] = ".splash",
|
||||
[UNIFIED_SECTION_DTB] = ".dtb",
|
||||
[UNIFIED_SECTION_UNAME] = ".uname",
|
||||
|
|
|
@ -10,6 +10,7 @@ typedef enum UnifiedSection {
|
|||
UNIFIED_SECTION_OSREL,
|
||||
UNIFIED_SECTION_CMDLINE,
|
||||
UNIFIED_SECTION_INITRD,
|
||||
UNIFIED_SECTION_UCODE,
|
||||
UNIFIED_SECTION_SPLASH,
|
||||
UNIFIED_SECTION_DTB,
|
||||
UNIFIED_SECTION_UNAME,
|
||||
|
|
|
@ -303,6 +303,7 @@ class Uname:
|
|||
DEFAULT_SECTIONS_TO_SHOW = {
|
||||
'.linux' : 'binary',
|
||||
'.initrd' : 'binary',
|
||||
'.ucode' : 'binary',
|
||||
'.splash' : 'binary',
|
||||
'.dtb' : 'binary',
|
||||
'.cmdline' : 'text',
|
||||
|
@ -855,6 +856,7 @@ def make_uki(opts):
|
|||
('.splash', opts.splash, True ),
|
||||
('.pcrpkey', pcrpkey, True ),
|
||||
('.initrd', initrd, True ),
|
||||
('.ucode', opts.microcode, True ),
|
||||
|
||||
# linux shall be last to leave breathing room for decompression.
|
||||
# We'll add it later.
|
||||
|
@ -1279,6 +1281,14 @@ CONFIG_ITEMS = [
|
|||
config_push = ConfigItem.config_list_prepend,
|
||||
),
|
||||
|
||||
ConfigItem(
|
||||
'--microcode',
|
||||
metavar = 'UCODE',
|
||||
type = pathlib.Path,
|
||||
help = 'microcode file [.ucode section]',
|
||||
config_key = 'UKI/Microcode',
|
||||
),
|
||||
|
||||
ConfigItem(
|
||||
('--config', '-c'),
|
||||
metavar = 'PATH',
|
||||
|
|
Loading…
Reference in a new issue