Compare commits

...

3 Commits

Author SHA1 Message Date
Ani Sinha 21a13a09a5
Merge dede6124e3 into 4b356c90dc 2024-11-23 16:35:06 +00:00
Ani Sinha dede6124e3 uki: introduce support for a .efifwauto section
UKIs can be used to bundle firmware blobs that can be measured and
used on a confidential computing environment. There can be more than one
firmware blob bundle, each one for a specific platform. Also firmware images
can themselves be containers like IGVM files that can in turn bundle the
actual firmware blob.

Add support to introduce a .efifwauto section in UKI that can be used for
firmware blobs/images. There can be multiple such sections and each section
can contain a single firmware image.

The matching .hwids entry for a specific platform can be used to select the
most appropriate firmware blob. Subsequent patches will add full support
for this selection mechanism.

ukify tool has been also changed to support addition of a firmware image
in UKI. For example:

ukify.py build \
        --stub ./build/src/boot/efi/linuxx64.efi.stub \
        --linux bzImage \
        --cmdline='blah blah debug' \
        --firmware ~/OVMF.fd \
        --output=root/efi/boot/bootx64.efi

Co-authored-by: harald.hoyer@gmail.com
2024-11-23 22:03:28 +05:30
Ani Sinha 4b356c90dc measure: add 'dtbauto' option in help message
'dtbauto' command line was missing from the help string. Add it.
2024-11-23 12:43:34 +00:00
5 changed files with 80 additions and 51 deletions

View File

@ -91,6 +91,15 @@
the same matching procedure. If a match is found, that <literal>.dtbauto</literal> section will be
loaded and will override <varname>.dtb</varname> if present.</para></listitem>
<listitem><para>Zero or more <literal>.efifwauto</literal> sections for the firmware image. It works
in many ways similar to <varname>.dtbauto</varname> sections. <filename>systemd-stub</filename>
will always use the first matching one. The match is performed by first selecting the most appropriate
entry in the <varname>.hwids</varname> section based on the hardware IDs supplied by SMBIOS (see below).
If a suitable entry is found, the <varname>compatible</varname> string from that entry will be used to
perform the matching procedure for firmware blobs in <varname>.efifwauto</varname> section. The first
matching firmware will be loaded.
</para></listitem>
<listitem><para>Zero or more <literal>.hwids</literal> sections with hardware IDs of the machines to
match DeviceTrees. <filename>systemd-stub</filename> will use the SMBIOS data to calculate hardware IDs
of the machine (as per <ulink

View File

@ -9,19 +9,20 @@ const char* const unified_sections[_UNIFIED_SECTION_MAX + 1] = {
* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
* (Note that PE *object* files may have longer section names (via indirection in the string table) but
* this is not allowed for PE *executables*, which UKIs are.) */
[UNIFIED_SECTION_LINUX] = ".linux",
[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",
[UNIFIED_SECTION_SBAT] = ".sbat",
[UNIFIED_SECTION_PCRSIG] = ".pcrsig",
[UNIFIED_SECTION_PCRPKEY] = ".pcrpkey",
[UNIFIED_SECTION_PROFILE] = ".profile",
[UNIFIED_SECTION_DTBAUTO] = ".dtbauto",
[UNIFIED_SECTION_HWIDS] = ".hwids",
[UNIFIED_SECTION_LINUX] = ".linux",
[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",
[UNIFIED_SECTION_SBAT] = ".sbat",
[UNIFIED_SECTION_PCRSIG] = ".pcrsig",
[UNIFIED_SECTION_PCRPKEY] = ".pcrpkey",
[UNIFIED_SECTION_PROFILE] = ".profile",
[UNIFIED_SECTION_DTBAUTO] = ".dtbauto",
[UNIFIED_SECTION_HWIDS] = ".hwids",
[UNIFIED_SECTION_FIRMWARE] = ".efifwauto",
NULL,
};

View File

@ -20,6 +20,7 @@ typedef enum UnifiedSection {
UNIFIED_SECTION_PROFILE,
UNIFIED_SECTION_DTBAUTO,
UNIFIED_SECTION_HWIDS,
UNIFIED_SECTION_FIRMWARE,
_UNIFIED_SECTION_MAX,
} UnifiedSection;

View File

@ -101,18 +101,20 @@ static int help(int argc, char *argv[], void *userdata) {
" -j Same as --json=pretty on tty, --json=short otherwise\n"
" --append=PATH Load specified JSON signature, and append new signature to it\n"
"\n%3$sUKI PE Section Options:%4$s %3$sUKI PE Section%4$s\n"
" --linux=PATH Path to Linux kernel image file %7$s .linux\n"
" --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"
" --sbat=PATH Path to SBAT file %7$s .sbat\n"
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
" --profile=PATH Path to profile file %7$s .profile\n"
" --hwids=PATH Path to HWIDs file %7$s .hwids\n"
" --linux=PATH Path to Linux kernel image file %7$s .linux\n"
" --osrel=PATH Path to os-release file %7$s .osrel\n"
" --cmdline=PATH Path to file with kernel command line %7$s .cmdline\n"
" --firmware=PATH Path to firmware image file %7$s .efifwauto\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"
" --dtbauto=PATH Path to DeviceTree file for auto selection %7$s .dtbauto\n"
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
" --sbat=PATH Path to SBAT file %7$s .sbat\n"
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
" --profile=PATH Path to profile file %7$s .profile\n"
" --hwids=PATH Path to HWIDs file %7$s .hwids\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,
@ -158,8 +160,9 @@ static int parse_argv(int argc, char *argv[]) {
ARG_PCRPKEY,
ARG_PROFILE,
ARG_HWIDS,
ARG_DTBAUTO,
_ARG_SECTION_LAST,
ARG_DTBAUTO = _ARG_SECTION_LAST,
ARG_FIRMWARE = _ARG_SECTION_LAST,
ARG_BANK,
ARG_PRIVATE_KEY,
ARG_PRIVATE_KEY_SOURCE,
@ -180,6 +183,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 },
{ "firmware", required_argument, NULL, ARG_FIRMWARE },
{ "ucode", required_argument, NULL, ARG_UCODE },
{ "splash", required_argument, NULL, ARG_SPLASH },
{ "dtb", required_argument, NULL, ARG_DTB },

View File

@ -242,6 +242,7 @@ class UkifyConfig:
efi_arch: str
hwids: Path
initrd: list[Path]
firmware: list[Path]
join_profiles: list[Path]
json: Union[Literal['pretty'], Literal['short'], Literal['off']]
linux: Optional[Path]
@ -362,21 +363,22 @@ class Uname:
DEFAULT_SECTIONS_TO_SHOW = {
'.linux': 'binary',
'.initrd': 'binary',
'.ucode': 'binary',
'.splash': 'binary',
'.dtb': 'binary',
'.dtbauto': 'binary',
'.hwids': 'binary',
'.cmdline': 'text',
'.osrel': 'text',
'.uname': 'text',
'.pcrpkey': 'text',
'.pcrsig': 'text',
'.sbat': 'text',
'.sbom': 'binary',
'.profile': 'text',
'.linux': 'binary',
'.initrd': 'binary',
'.ucode': 'binary',
'.splash': 'binary',
'.dtb': 'binary',
'.dtbauto': 'binary',
'.hwids': 'binary',
'.efifwauto': 'binary',
'.cmdline': 'text',
'.osrel': 'text',
'.uname': 'text',
'.pcrpkey': 'text',
'.pcrsig': 'text',
'.sbat': 'text',
'.sbom': 'binary',
'.profile': 'text',
} # fmt: skip
@ -1204,16 +1206,17 @@ def make_uki(opts: UkifyConfig) -> None:
sections = [
# name, content, measure?
('.osrel', opts.os_release, True),
('.cmdline', opts.cmdline, True),
('.dtb', opts.devicetree, True),
('.osrel', opts.os_release, True),
('.cmdline', opts.cmdline, True),
('.dtb', opts.devicetree, True),
*(('.dtbauto', dtb, True) for dtb in opts.devicetree_auto),
('.hwids', hwids, True),
('.uname', opts.uname, True),
('.splash', opts.splash, True),
('.pcrpkey', pcrpkey, True),
('.initrd', initrd, True),
('.ucode', opts.microcode, True),
('.hwids', hwids, True),
('.uname', opts.uname, True),
('.splash', opts.splash, True),
('.pcrpkey', pcrpkey, True),
('.initrd', initrd, True),
*(('.efifwauto', fw, True) for fw in opts.firmware),
('.ucode', opts.microcode, True),
] # fmt: skip
# If we're building a PE profile binary, the ".profile" section has to be the first one.
@ -1269,6 +1272,7 @@ def make_uki(opts: UkifyConfig) -> None:
'.osrel',
'.cmdline',
'.initrd',
'.efifwauto',
'.ucode',
'.splash',
'.dtb',
@ -1729,6 +1733,16 @@ CONFIG_ITEMS = [
config_key='UKI/Initrd',
config_push=ConfigItem.config_list_prepend,
),
ConfigItem(
'--firmware',
metavar='PATH',
type=Path,
action='append',
default=[],
help='firmware file [.efifwauto section]',
config_key='UKI/Firmware',
config_push=ConfigItem.config_list_prepend,
),
ConfigItem(
'--microcode',
metavar='UCODE',