mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 18:23:32 +08:00
ukify: allow building PE addon
Make the kernel optional too, so that we can easily build and sign a PE addon, that can be used to carry extra command line options.
This commit is contained in:
parent
1db4acbe5d
commit
00e5933f57
@ -17,14 +17,14 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>ukify</refname>
|
||||
<refpurpose>Combine kernel and initrd into a signed Unified Kernel Image</refpurpose>
|
||||
<refpurpose>Combine components into a signed Unified Kernel Image for UEFI systems</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>/usr/lib/systemd/ukify</command>
|
||||
<arg choice="plain"><replaceable>LINUX</replaceable></arg>
|
||||
<arg choice="plain" rep="repeat"><replaceable>INITRD</replaceable></arg>
|
||||
<arg choice="opt"><replaceable>LINUX</replaceable></arg>
|
||||
<arg choice="opt" rep="repeat"><replaceable>INITRD</replaceable></arg>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@ -35,8 +35,8 @@
|
||||
<para>Note: this command is experimental for now. While it is intended to become a regular component of
|
||||
systemd, it might still change in behaviour and interface.</para>
|
||||
|
||||
<para><command>ukify</command> is a tool that combines a kernel and an initrd with
|
||||
a UEFI boot stub to create a
|
||||
<para><command>ukify</command> is a tool that combines components (e.g.: a kernel and an initrd with
|
||||
a UEFI boot stub) to create a
|
||||
<ulink url="https://uapi-group.org/specifications/specs/unified_kernel_image/">Unified Kernel Image (UKI)</ulink>
|
||||
— a PE binary that can be executed by the firmware to start the embedded linux kernel.
|
||||
See <citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
@ -53,6 +53,9 @@
|
||||
and <option>--section=</option>
|
||||
below.</para>
|
||||
|
||||
<para><command>ukify</command> can also be used to assemble a PE binary that is not executable but
|
||||
contains auxiliary data, for example additional kernel command line entries.</para>
|
||||
|
||||
<para>If PCR signing keys are provided via the <option>--pcr-public-key=</option> and
|
||||
<option>--pcr-private-key=</option> options, PCR values that will be seen after booting with the given
|
||||
kernel, initrd, and other sections, will be calculated, signed, and embedded in the UKI.
|
||||
@ -78,10 +81,9 @@
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<para>Note that the <replaceable>LINUX</replaceable> positional argument is mandatory. The
|
||||
<replaceable>INITRD</replaceable> positional arguments are optional. If more than one is specified, they
|
||||
will all be combined into a single PE section. This is useful to for example prepend microcode before the
|
||||
actual initrd.</para>
|
||||
<para>The <replaceable>LINUX</replaceable> and <replaceable>INITRD</replaceable> positional arguments are
|
||||
optional. If more than one <replaceable>INITRD</replaceable> are specified, they will all be combined into
|
||||
a single PE section. This is useful to for example prepend microcode before the actual initrd.</para>
|
||||
|
||||
<para>The following options are understood:</para>
|
||||
|
||||
@ -296,6 +298,19 @@
|
||||
key <filename index='false'>pcr-private-system-key.pem</filename>. The Linux binary and the resulting
|
||||
combined image will be signed with the SecureBoot key <filename index='false'>sb.key</filename>.</para>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Kernel command line auxiliary PE</title>
|
||||
|
||||
<programlisting>ukify \
|
||||
--secureboot-private-key=sb.key \
|
||||
--secureboot-certificate=sb.cert \
|
||||
--cmdline='debug' \
|
||||
--output=debug.cmdline.efi
|
||||
</programlisting>
|
||||
|
||||
<para>This creates a signed PE binary that contains an additional kernel command line parameter.</para>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -206,6 +206,27 @@ def test_sections(kernel_initrd, tmpdir):
|
||||
for sect in 'text osrel cmdline linux initrd uname test'.split():
|
||||
assert re.search(fr'^\s*\d+\s+.{sect}\s+0', dump, re.MULTILINE)
|
||||
|
||||
def test_addon(kernel_initrd, tmpdir):
|
||||
output = f'{tmpdir}/addon.efi'
|
||||
opts = ukify.parse_args([
|
||||
f'--output={output}',
|
||||
'--cmdline=ARG1 ARG2 ARG3',
|
||||
'--section=.test:CONTENTZ',
|
||||
])
|
||||
|
||||
try:
|
||||
ukify.check_inputs(opts)
|
||||
except OSError as e:
|
||||
pytest.skip(str(e))
|
||||
|
||||
ukify.make_uki(opts)
|
||||
|
||||
# let's check that objdump likes the resulting file
|
||||
dump = subprocess.check_output(['objdump', '-h', output], text=True)
|
||||
|
||||
for sect in 'text cmdline test'.split():
|
||||
assert re.search(fr'^\s*\d+\s+.{sect}\s+0', dump, re.MULTILINE)
|
||||
|
||||
|
||||
def unbase64(filename):
|
||||
tmp = tempfile.NamedTemporaryFile()
|
||||
|
@ -551,7 +551,7 @@ def make_uki(opts):
|
||||
sbsign_invocation += ['--engine', opts.signing_engine]
|
||||
|
||||
sign_kernel = opts.sign_kernel
|
||||
if sign_kernel is None and opts.sb_key:
|
||||
if sign_kernel is None and opts.linux is not None and opts.sb_key:
|
||||
# figure out if we should sign the kernel
|
||||
sbverify_tool = find_tool('sbverify', opts=opts)
|
||||
|
||||
@ -583,7 +583,7 @@ def make_uki(opts):
|
||||
else:
|
||||
linux = opts.linux
|
||||
|
||||
if opts.uname is None:
|
||||
if opts.uname is None and opts.linux is not None:
|
||||
print('Kernel version not specified, starting autodetection 😖.')
|
||||
opts.uname = Uname.scrape(opts.linux, opts=opts)
|
||||
|
||||
@ -624,7 +624,8 @@ def make_uki(opts):
|
||||
|
||||
# UKI creation
|
||||
|
||||
uki.add_section(Section.create('.linux', linux, measure=True))
|
||||
if linux is not None:
|
||||
uki.add_section(Section.create('.linux', linux, measure=True))
|
||||
|
||||
if opts.sb_key:
|
||||
unsigned = tempfile.NamedTemporaryFile(prefix='uki')
|
||||
@ -657,7 +658,7 @@ def parse_args(args=None):
|
||||
description='Build and sign Unified Kernel Images',
|
||||
allow_abbrev=False,
|
||||
usage='''\
|
||||
usage: ukify [options…] linux initrd…
|
||||
usage: ukify [options…] [linux [initrd…]]
|
||||
ukify -h | --help
|
||||
''')
|
||||
|
||||
@ -666,6 +667,7 @@ usage: ukify [options…] linux initrd…
|
||||
|
||||
p.add_argument('linux',
|
||||
type=pathlib.Path,
|
||||
nargs="?",
|
||||
help='vmlinuz file [.linux section]')
|
||||
p.add_argument('initrd',
|
||||
type=pathlib.Path,
|
||||
@ -769,7 +771,8 @@ usage: ukify [options…] linux initrd…
|
||||
|
||||
opts = p.parse_args(args)
|
||||
|
||||
path_is_readable(opts.linux)
|
||||
if opts.linux is not None:
|
||||
path_is_readable(opts.linux)
|
||||
for initrd in opts.initrd or ():
|
||||
path_is_readable(initrd)
|
||||
path_is_readable(opts.devicetree)
|
||||
@ -784,7 +787,7 @@ usage: ukify [options…] linux initrd…
|
||||
|
||||
if opts.os_release is not None and opts.os_release.startswith('@'):
|
||||
opts.os_release = path_is_readable(opts.os_release[1:])
|
||||
elif opts.os_release is None:
|
||||
elif opts.os_release is None and opts.linux is not None:
|
||||
p = pathlib.Path('/etc/os-release')
|
||||
if not p.exists():
|
||||
p = path_is_readable('/usr/lib/os-release')
|
||||
@ -815,6 +818,8 @@ usage: ukify [options…] linux initrd…
|
||||
raise ValueError('--phases= specifications must match --pcr-private-key=')
|
||||
|
||||
if opts.output is None:
|
||||
if opts.linux is None:
|
||||
raise ValueError('--output= must be specified when building a PE addon')
|
||||
suffix = '.efi' if opts.sb_key else '.unsigned.efi'
|
||||
opts.output = opts.linux.name + suffix
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user