1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-03 17:47:28 +03:00

Split and rename src/boot (#35068)

This commit is contained in:
Yu Watanabe 2024-11-08 04:13:45 +09:00 committed by GitHub
commit dd2bf3141b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
109 changed files with 1933 additions and 1918 deletions

View File

@ -2344,8 +2344,9 @@ subdir('src/ask-password')
subdir('src/backlight')
subdir('src/battery-check')
subdir('src/binfmt')
subdir('src/bless-boot')
subdir('src/boot')
subdir('src/boot/efi')
subdir('src/bootctl')
subdir('src/busctl')
subdir('src/cgls')
subdir('src/cgroups-agent')
@ -2380,6 +2381,7 @@ subdir('src/locale')
subdir('src/login')
subdir('src/machine')
subdir('src/machine-id-setup')
subdir('src/measure')
subdir('src/mountfsd')
subdir('src/modules-load')
subdir('src/mount')
@ -2408,6 +2410,7 @@ subdir('src/rfkill')
subdir('src/rpm')
subdir('src/run')
subdir('src/run-generator')
subdir('src/sbsign')
subdir('src/shutdown')
subdir('src/sleep')
subdir('src/socket-activate')

View File

@ -0,0 +1,37 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if get_option('link-boot-shared')
boot_link_with = [libshared]
else
boot_link_with = [
libshared_static,
libsystemd_static,
]
endif
executables += [
libexec_template + {
'name' : 'systemd-bless-boot',
'public' : true,
'conditions' : [
'HAVE_BLKID',
'ENABLE_BOOTLOADER',
],
'sources' : files('bless-boot.c'),
'link_with' : boot_link_with,
'dependencies' : libblkid,
},
generator_template + {
'name' : 'systemd-bless-boot-generator',
'conditions' : [
'HAVE_BLKID',
'ENABLE_BOOTLOADER',
],
'sources' : files('bless-boot-generator.c'),
'link_with' : boot_link_with,
},
libexec_template + {
'name' : 'systemd-boot-check-no-failures',
'sources' : files('boot-check-no-failures.c'),
},
]

View File

@ -1,324 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#if ENABLE_TPM
#include "macro-fundamental.h"
#include "measure.h"
#include "memory-util-fundamental.h"
#include "proto/cc-measurement.h"
#include "proto/tcg.h"
#include "tpm2-pcr.h"
#include "util.h"
static EFI_STATUS tpm2_measure_to_pcr_and_tagged_event_log(
EFI_TCG2_PROTOCOL *tcg,
uint32_t pcrindex,
EFI_PHYSICAL_ADDRESS buffer,
uint64_t buffer_size,
uint32_t event_id,
const char16_t *description) {
_cleanup_free_ struct event {
EFI_TCG2_EVENT tcg_event;
EFI_TCG2_TAGGED_EVENT tcg_tagged_event;
} _packed_ *event = NULL;
size_t desc_len, event_size;
assert(tcg);
assert(description);
/* New style stuff we log as EV_EVENT_TAG with a recognizable event tag. */
desc_len = strsize16(description);
event_size = offsetof(EFI_TCG2_EVENT, Event) + offsetof(EFI_TCG2_TAGGED_EVENT, Event) + desc_len;
event = xmalloc(event_size);
*event = (struct event) {
.tcg_event = (EFI_TCG2_EVENT) {
.Size = event_size,
.Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER),
.Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION,
.Header.PCRIndex = pcrindex,
.Header.EventType = EV_EVENT_TAG,
},
.tcg_tagged_event = {
.EventId = event_id,
.EventSize = desc_len,
},
};
memcpy(event->tcg_tagged_event.Event, description, desc_len);
return tcg->HashLogExtendEvent(
tcg,
0,
buffer, buffer_size,
&event->tcg_event);
}
static EFI_STATUS tpm2_measure_to_pcr_and_ipl_event_log(
EFI_TCG2_PROTOCOL *tcg,
uint32_t pcrindex,
EFI_PHYSICAL_ADDRESS buffer,
uint64_t buffer_size,
const char16_t *description) {
_cleanup_free_ EFI_TCG2_EVENT *tcg_event = NULL;
size_t desc_len;
assert(tcg);
assert(description);
/* We record older stuff as EV_IPL. Which sucks, because it makes it hard to recognize from the event
* log which of the events are ours. Measurement logs are kinda API hence this is hard to change for
* existing, established events. But for future additions, let's use EV_EVENT_TAG instead, with a tag
* of our choosing that makes clear what precisely we are measuring here. See above. */
desc_len = strsize16(description);
tcg_event = xmalloc(offsetof(EFI_TCG2_EVENT, Event) + desc_len);
*tcg_event = (EFI_TCG2_EVENT) {
.Size = offsetof(EFI_TCG2_EVENT, Event) + desc_len,
.Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER),
.Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION,
.Header.PCRIndex = pcrindex,
.Header.EventType = EV_IPL,
};
memcpy(tcg_event->Event, description, desc_len);
return tcg->HashLogExtendEvent(
tcg,
0,
buffer, buffer_size,
tcg_event);
}
static EFI_STATUS cc_measure_to_mr_and_ipl_event_log(
EFI_CC_MEASUREMENT_PROTOCOL *cc,
uint32_t pcrindex,
EFI_PHYSICAL_ADDRESS buffer,
uint64_t buffer_size,
const char16_t *description) {
_cleanup_free_ EFI_CC_EVENT *event = NULL;
uint32_t mr;
EFI_STATUS err;
size_t desc_len;
assert(cc);
assert(description);
/* MapPcrToMrIndex service provides callers information on
* how the TPM PCR registers are mapped to the CC measurement
* registers (MR) in the vendor implementation. */
err = cc->MapPcrToMrIndex(cc, pcrindex, &mr);
if (err != EFI_SUCCESS)
return EFI_NOT_FOUND;
desc_len = strsize16(description);
event = xmalloc(offsetof(EFI_CC_EVENT, Event) + desc_len);
*event = (EFI_CC_EVENT) {
.Size = offsetof(EFI_CC_EVENT, Event) + desc_len,
.Header.HeaderSize = sizeof(EFI_CC_EVENT_HEADER),
.Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION,
.Header.MrIndex = mr,
.Header.EventType = EV_IPL,
};
memcpy(event->Event, description, desc_len);
return cc->HashLogExtendEvent(
cc,
0,
buffer,
buffer_size,
event);
}
static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) {
EFI_CC_BOOT_SERVICE_CAPABILITY capability = {
.Size = sizeof(capability),
};
EFI_STATUS err;
EFI_CC_MEASUREMENT_PROTOCOL *cc;
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_CC_MEASUREMENT_PROTOCOL), NULL, (void **) &cc);
if (err != EFI_SUCCESS)
return NULL;
err = cc->GetCapability(cc, &capability);
if (err != EFI_SUCCESS)
return NULL;
if (!(capability.SupportedEventLogs & EFI_CC_EVENT_LOG_FORMAT_TCG_2))
return NULL;
return cc;
}
static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
.Size = sizeof(capability),
};
EFI_STATUS err;
EFI_TCG2_PROTOCOL *tcg;
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg);
if (err != EFI_SUCCESS)
return NULL;
err = tcg->GetCapability(tcg, &capability);
if (err != EFI_SUCCESS)
return NULL;
if (capability.StructureVersion.Major == 1 &&
capability.StructureVersion.Minor == 0) {
EFI_TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
(EFI_TCG_BOOT_SERVICE_CAPABILITY*) &capability;
if (caps_1_0->TPMPresentFlag)
return tcg;
}
if (!capability.TPMPresentFlag)
return NULL;
return tcg;
}
bool tpm_present(void) {
return tcg2_interface_check();
}
static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err = EFI_SUCCESS;
assert(ret_measured);
tpm2 = tcg2_interface_check();
if (!tpm2) {
*ret_measured = false;
return EFI_SUCCESS;
}
err = tpm2_measure_to_pcr_and_ipl_event_log(tpm2, pcrindex, buffer, buffer_size, description);
if (err != EFI_SUCCESS)
return err;
*ret_measured = true;
return EFI_SUCCESS;
}
static EFI_STATUS cc_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
EFI_CC_MEASUREMENT_PROTOCOL *cc;
EFI_STATUS err = EFI_SUCCESS;
assert(ret_measured);
cc = cc_interface_check();
if (!cc) {
*ret_measured = false;
return EFI_SUCCESS;
}
err = cc_measure_to_mr_and_ipl_event_log(cc, pcrindex, buffer, buffer_size, description);
if (err != EFI_SUCCESS)
return err;
*ret_measured = true;
return EFI_SUCCESS;
}
EFI_STATUS tpm_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
EFI_STATUS err;
bool tpm_ret_measured, cc_ret_measured;
assert(description || pcrindex == UINT32_MAX);
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
* something, or false if measurement was turned off. */
if (pcrindex == UINT32_MAX) { /* PCR disabled? */
if (ret_measured)
*ret_measured = false;
return EFI_SUCCESS;
}
/* Measure into both CC and TPM if both are available to avoid a problem like CVE-2021-42299 */
err = cc_log_event(pcrindex, buffer, buffer_size, description, &cc_ret_measured);
if (err != EFI_SUCCESS)
return err;
err = tcg2_log_ipl_event(pcrindex, buffer, buffer_size, description, &tpm_ret_measured);
if (err != EFI_SUCCESS)
return err;
if (ret_measured)
*ret_measured = tpm_ret_measured || cc_ret_measured;
return EFI_SUCCESS;
}
EFI_STATUS tpm_log_tagged_event(
uint32_t pcrindex,
EFI_PHYSICAL_ADDRESS buffer,
size_t buffer_size,
uint32_t event_id,
const char16_t *description,
bool *ret_measured) {
EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err;
assert(description || pcrindex == UINT32_MAX);
assert(event_id > 0);
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
* something, or false if measurement was turned off. */
tpm2 = tcg2_interface_check();
if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */
if (ret_measured)
*ret_measured = false;
return EFI_SUCCESS;
}
err = tpm2_measure_to_pcr_and_tagged_event_log(tpm2, pcrindex, buffer, buffer_size, event_id, description);
if (!err)
return err;
*ret_measured = true;
return EFI_SUCCESS;
}
EFI_STATUS tpm_log_ipl_event_ascii(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char *description, bool *ret_measured) {
_cleanup_free_ char16_t *c = NULL;
if (description)
c = xstr8_to_16(description);
return tpm_log_ipl_event(pcrindex, buffer, buffer_size, c, ret_measured);
}
EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured) {
EFI_STATUS err;
/* Measures a load options string into the TPM2, i.e. the kernel command line */
err = tpm_log_ipl_event(
TPM2_PCR_KERNEL_CONFIG,
POINTER_TO_PHYSICAL_ADDRESS(load_options),
strsize16(load_options),
load_options,
ret_measured);
if (err != EFI_SUCCESS)
return log_error_status(
err,
"Unable to add load options (i.e. kernel command) line measurement to PCR %i: %m",
TPM2_PCR_KERNEL_CONFIG);
return EFI_SUCCESS;
}
#endif

View File

@ -1,430 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
efi_config_h_dir = meson.current_build_dir()
efi_addon = ''
libefitest = static_library(
'efitest',
files(
'bcd.c',
'efi-string.c',
),
build_by_default : false,
include_directories : [
basic_includes,
include_directories('.'),
],
dependencies : userspace)
efitest_base = {
'link_with' : [
libefitest,
libshared,
],
}
efi_test_template = test_template + efitest_base
efi_fuzz_template = fuzz_template + efitest_base
executables += [
efi_test_template + {
'sources' : files('test-bcd.c'),
'dependencies' : libzstd_cflags,
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_ZSTD'],
},
efi_test_template + {
'sources' : files('test-efi-string.c'),
'conditions' : ['ENABLE_BOOTLOADER'],
},
efi_fuzz_template + {
'sources' : files('fuzz-bcd.c'),
},
efi_fuzz_template + {
'sources' : files('fuzz-efi-string.c'),
},
efi_fuzz_template + {
'sources' : files('fuzz-efi-osrel.c'),
},
efi_fuzz_template + {
'sources' : files('fuzz-efi-printf.c'),
},
]
if conf.get('ENABLE_BOOTLOADER') != 1
subdir_done()
endif
efi_conf = configuration_data()
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
c = get_option('efi-' + ctype).split(',')
efi_conf.set(ctype.underscorify().to_upper(), 'EFI_TEXT_ATTR(@0@, @1@)'.format(
'EFI_' + c[0].strip().underscorify().to_upper(),
'EFI_' + c[1].strip().underscorify().to_upper()))
endforeach
efi_conf.set_quoted('PROJECT_VERSION', project_major_version)
efi_conf.set_quoted('VERSION_TAG', version_tag)
efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
if meson.is_cross_build() and get_option('sbat-distro') == 'auto'
warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.')
elif get_option('sbat-distro') != ''
efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
if get_option('sbat-distro-generation') < 1
error('SBAT Distro Generation must be a positive integer')
endif
efi_conf.set('SBAT_DISTRO_GENERATION', get_option('sbat-distro-generation'))
foreach sbatvar : [['sbat-distro', 'ID'],
['sbat-distro-summary', 'NAME'],
['sbat-distro-url', 'BUG_REPORT_URL']]
value = get_option(sbatvar[0])
if (value == '' or value == 'auto') and not meson.is_cross_build()
cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1])
value = run_command(sh, '-c', cmd, check: true).stdout().strip()
endif
if value == ''
error('Required @0@ option not set and autodetection failed'.format(sbatvar[0]))
endif
efi_conf.set_quoted(sbatvar[0].underscorify().to_upper(), value)
endforeach
pkgname = get_option('sbat-distro-pkgname')
if pkgname == ''
pkgname = meson.project_name()
endif
efi_conf.set_quoted('SBAT_DISTRO_PKGNAME', pkgname)
pkgver = get_option('sbat-distro-version')
if pkgver == ''
# This is determined during build, not configuration, so we can't display it yet.
efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION')
else
efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver)
endif
endif
summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)},
section : 'UEFI')
if efi_conf.get('SBAT_DISTRO', '') != ''
summary({
'SBAT distro': efi_conf.get('SBAT_DISTRO'),
'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'),
'SBAT distro version': efi_conf.get('SBAT_DISTRO_VERSION'),
'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'),
'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')},
section : 'UEFI')
endif
configure_file(
output : 'efi_config.h',
configuration : efi_conf)
############################################################
efi_includes = [
build_dir_include,
fundamental_include,
include_directories('.'),
]
efi_c_args = [
'-DSD_BOOT=1',
'-ffreestanding',
'-fno-strict-aliasing',
'-fshort-wchar',
'-include', 'efi_config.h',
]
efi_c_args += cc.get_supported_arguments(
'-fwide-exec-charset=UCS2',
# gcc docs says this is required for ms_abi to work correctly.
'-maccumulate-outgoing-args',
'-mstack-protector-guard=global',
)
# Debug information has little value in release builds as no normal human being knows
# how to attach a debugger to EFI binaries running on real hardware. Anyone who does
# certainly has the means to do their own dev build.
if get_option('mode') == 'developer' and get_option('debug')
efi_c_args += '-DEFI_DEBUG'
endif
efi_c_ld_args = [
'-lgcc',
'-nostdlib',
'-static-pie',
'-Wl,--entry=efi_main',
'-Wl,--fatal-warnings',
# These flags should be passed by -static-pie, but for whatever reason the flag translation
# is not enabled on all architectures. Not passing `-static` would just allow the linker to
# use dynamic libraries, (which we can't/don't use anyway). But if `-pie` is missing and the
# gcc build does not default to `-pie` we get a regular (no-pie) binary that will be
# rightfully rejected by elf2efi. Note that meson also passes `-pie` to the linker driver,
# but it is overridden by our `-static-pie`. We also need to pass these directly to the
# linker as `-static`+`-pie` seem to get translated differently.
'-Wl,-static,-pie,--no-dynamic-linker,-z,text',
# EFI has 4KiB pages.
'-z', 'common-page-size=4096',
'-z', 'max-page-size=4096',
'-z', 'noexecstack',
'-z', 'relro',
'-z', 'separate-code',
]
efi_c_ld_args += cc.get_supported_link_arguments(
# binutils >= 2.38
'-Wl,-z,nopack-relative-relocs',
)
# efi_c_args is explicitly passed to targets so that they can override distro-provided flags
# that should not be used for EFI binaries.
efi_disabled_c_args = cc.get_supported_arguments(
'-fcf-protection=none',
'-fno-asynchronous-unwind-tables',
'-fno-exceptions',
'-fno-unwind-tables',
)
efi_override_options = [
'b_coverage=false',
'b_pgo=off',
]
if get_option('b_sanitize') == 'undefined'
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize-link-runtime')
else
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize=all')
efi_override_options += 'b_sanitize=none'
endif
efi_c_args += efi_disabled_c_args
efi_c_ld_args += efi_disabled_c_args
if cc.get_id() == 'clang'
# clang is too picky sometimes.
efi_c_args += '-Wno-unused-command-line-argument'
efi_c_ld_args += '-Wno-unused-command-line-argument'
endif
efi_arch_c_args = {
'aarch64' : ['-mgeneral-regs-only'],
'arm' : ['-mgeneral-regs-only'],
# Until -mgeneral-regs-only is supported in LoongArch, use the following option instead:
'loongarch64' : ['-mno-lsx', '-mno-lasx'],
# Pass -m64/32 explicitly to make building on x32 work.
'x86_64' : ['-m64', '-march=x86-64', '-mno-red-zone', '-mgeneral-regs-only'],
'x86' : ['-m32', '-march=i686', '-mgeneral-regs-only', '-malign-double'],
}
efi_arch_c_ld_args = {
# libgcc is not compiled with -fshort-wchar, but it does not use it anyways,
# so it's fine to link against it.
'arm' : cc.get_supported_link_arguments('-Wl,--no-wchar-size-warning'),
'x86_64' : ['-m64'],
'x86' : ['-m32'],
}
linker_sanity_code = 'void a(void) {}; void _start(void) { a(); }'
linker_sanity_args = ['-nostdlib', '-Wl,--fatal-warnings']
if not cc.links(linker_sanity_code,
name : 'linker supports -static-pie',
args : [linker_sanity_args, '-static-pie'])
error('Linker does not support -static-pie.')
endif
# https://github.com/llvm/llvm-project/issues/67152
if not cc.links(linker_sanity_code,
name : 'linker supports LTO with -nostdlib',
args : [linker_sanity_args, '-flto'])
efi_c_args += '-fno-lto'
efi_c_ld_args += '-fno-lto'
endif
# https://github.com/llvm/llvm-project/issues/61101
if efi_cpu_family_alt == 'x86' and not cc.links(linker_sanity_code,
name : 'linker supports LTO with -nostdlib (x86)',
args : [linker_sanity_args, '-flto', '-m32'])
efi_arch_c_args += { 'x86' : efi_arch_c_args['x86'] + '-fno-lto' }
efi_arch_c_ld_args += { 'x86' : efi_arch_c_ld_args['x86'] + '-fno-lto' }
endif
############################################################
libefi_sources = files(
'chid.c',
'console.c',
'device-path-util.c',
'devicetree.c',
'drivers.c',
'efi-string.c',
'efivars.c',
'export-vars.c',
'graphics.c',
'initrd.c',
'log.c',
'measure.c',
'part-discovery.c',
'pe.c',
'random-seed.c',
'secure-boot.c',
'shim.c',
'smbios.c',
'ticks.c',
'util.c',
'vmm.c',
)
systemd_boot_sources = files(
'boot.c',
)
stub_sources = files(
'cpio.c',
'linux.c',
'splash.c',
'stub.c',
)
addon_sources = files(
'addon.c',
)
if get_option('b_sanitize') == 'undefined'
libefi_sources += files('ubsan.c')
endif
if host_machine.cpu_family() in ['x86', 'x86_64']
stub_sources += files('linux_x86.c')
endif
# BCD parser only makes sense on arches that Windows supports.
if host_machine.cpu_family() in ['aarch64', 'arm', 'x86_64', 'x86']
systemd_boot_sources += files('bcd.c')
endif
boot_targets = []
efi_elf_binaries = []
efi_archspecs = [
{
'arch' : efi_arch,
'c_args' : [
efi_c_args,
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch + '"',
efi_arch_c_args.get(host_machine.cpu_family(), []),
],
'link_args' : [
efi_c_ld_args,
efi_arch_c_ld_args.get(host_machine.cpu_family(), []),
],
},
]
if efi_arch_alt != ''
efi_archspecs += {
'arch' : efi_arch_alt,
'c_args' : [
efi_c_args,
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch_alt + '"',
efi_arch_c_args.get(efi_cpu_family_alt, []),
],
'link_args' : [
efi_c_ld_args,
efi_arch_c_ld_args.get(efi_cpu_family_alt, []),
],
}
endif
foreach archspec : efi_archspecs
libefi = static_library(
'efi' + archspec['arch'],
fundamental_sources,
libefi_sources,
version_h,
include_directories : efi_includes,
c_args : archspec['c_args'],
gnu_symbol_visibility : 'hidden',
override_options : efi_override_options,
pic : true)
kwargs = {
'include_directories' : efi_includes,
'c_args' : archspec['c_args'],
'link_args' : archspec['link_args'],
'gnu_symbol_visibility' : 'hidden',
'override_options' : efi_override_options,
'pie' : true,
}
efi_elf_binaries += executable(
'systemd-boot' + archspec['arch'],
sources : [systemd_boot_sources, version_h],
link_with : libefi,
name_suffix : 'elf',
kwargs : kwargs)
efi_elf_binaries += executable(
'linux' + archspec['arch'],
sources : [stub_sources, version_h],
link_with : libefi,
name_suffix : 'elf.stub',
kwargs : kwargs)
efi_elf_binaries += executable(
'addon' + archspec['arch'],
sources : [addon_sources, version_h],
name_suffix : 'elf.stub',
kwargs : kwargs)
endforeach
foreach efi_elf_binary : efi_elf_binaries
name = efi_elf_binary.name()
name += name.startswith('systemd-boot') ? '.efi' : '.efi.stub'
# For the addon, given it's empty, we need to explicitly reserve space in the header to account for
# the sections that ukify will add.
if name.startswith('linux')
minimum_sections = get_option('efi-stub-extra-sections')
elif name.startswith('addon')
minimum_sections = get_option('efi-addon-extra-sections')
else
minimum_sections = 0
endif
exe = custom_target(
name,
output : name,
input : efi_elf_binary,
install : true,
install_dir : bootlibdir,
install_tag : 'systemd-boot',
command : [
elf2efi_py,
'--version-major=' + project_major_version,
'--version-minor=' + project_minor_version,
'--efi-major=1',
'--efi-minor=1',
'--subsystem=10',
'--minimum-sections=@0@'.format(minimum_sections),
'--copy-sections=.sbat,.sdmagic,.osrel',
'@INPUT@',
'@OUTPUT@',
])
boot_targets += exe
if name.startswith('linux')
boot_stubs += exe
endif
# This is supposed to match exactly one time
if name == 'addon@0@.efi.stub'.format(efi_arch)
efi_addon = exe.full_path()
endif
test('check-alignment-@0@'.format(name),
check_efi_alignment_py,
args : exe.full_path(),
suite : 'efi')
endforeach
alias_target('systemd-boot', boot_targets)

File diff suppressed because it is too large Load Diff

View File

@ -1,77 +1,430 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
bootctl_sources = files(
'bootctl-install.c',
'bootctl-random-seed.c',
'bootctl-reboot-to-firmware.c',
'bootctl-set-efivar.c',
'bootctl-status.c',
'bootctl-systemd-efi-options.c',
'bootctl-uki.c',
'bootctl-util.c',
'bootctl.c',
)
efi_config_h_dir = meson.current_build_dir()
efi_addon = ''
if get_option('link-boot-shared')
boot_link_with = [libshared]
else
boot_link_with = [
libshared_static,
libsystemd_static,
]
endif
libefitest = static_library(
'efitest',
files(
'bcd.c',
'efi-string.c',
),
build_by_default : false,
include_directories : [
basic_includes,
include_directories('.'),
],
dependencies : userspace)
efitest_base = {
'link_with' : [
libefitest,
libshared,
],
}
efi_test_template = test_template + efitest_base
efi_fuzz_template = fuzz_template + efitest_base
executables += [
executable_template + {
'name' : 'bootctl',
'public' : true,
'conditions' : [
'HAVE_BLKID',
],
'sources' : bootctl_sources,
'link_with' : boot_link_with,
'dependencies' : [libblkid, libopenssl],
efi_test_template + {
'sources' : files('test-bcd.c'),
'dependencies' : libzstd_cflags,
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_ZSTD'],
},
libexec_template + {
'name' : 'systemd-bless-boot',
'public' : true,
'conditions' : [
'HAVE_BLKID',
'ENABLE_BOOTLOADER',
],
'sources' : files('bless-boot.c'),
'link_with' : boot_link_with,
'dependencies' : libblkid,
efi_test_template + {
'sources' : files('test-efi-string.c'),
'conditions' : ['ENABLE_BOOTLOADER'],
},
generator_template + {
'name' : 'systemd-bless-boot-generator',
'conditions' : [
'HAVE_BLKID',
'ENABLE_BOOTLOADER',
],
'sources' : files('bless-boot-generator.c'),
'link_with' : boot_link_with,
efi_fuzz_template + {
'sources' : files('fuzz-bcd.c'),
},
libexec_template + {
'name' : 'systemd-measure',
'conditions' : [
'HAVE_BLKID',
'HAVE_OPENSSL',
'HAVE_TPM2',
],
'sources' : files('measure.c'),
'dependencies' : libopenssl,
efi_fuzz_template + {
'sources' : files('fuzz-efi-string.c'),
},
libexec_template + {
'name' : 'systemd-sbsign',
'conditions' : [
'HAVE_OPENSSL',
],
'sources' : files('sbsign.c'),
'dependencies' : libopenssl,
efi_fuzz_template + {
'sources' : files('fuzz-efi-osrel.c'),
},
libexec_template + {
'name' : 'systemd-boot-check-no-failures',
'sources' : files('boot-check-no-failures.c'),
efi_fuzz_template + {
'sources' : files('fuzz-efi-printf.c'),
},
]
if conf.get('ENABLE_BOOTLOADER') != 1
subdir_done()
endif
efi_conf = configuration_data()
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
c = get_option('efi-' + ctype).split(',')
efi_conf.set(ctype.underscorify().to_upper(), 'EFI_TEXT_ATTR(@0@, @1@)'.format(
'EFI_' + c[0].strip().underscorify().to_upper(),
'EFI_' + c[1].strip().underscorify().to_upper()))
endforeach
efi_conf.set_quoted('PROJECT_VERSION', project_major_version)
efi_conf.set_quoted('VERSION_TAG', version_tag)
efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
if meson.is_cross_build() and get_option('sbat-distro') == 'auto'
warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.')
elif get_option('sbat-distro') != ''
efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
if get_option('sbat-distro-generation') < 1
error('SBAT Distro Generation must be a positive integer')
endif
efi_conf.set('SBAT_DISTRO_GENERATION', get_option('sbat-distro-generation'))
foreach sbatvar : [['sbat-distro', 'ID'],
['sbat-distro-summary', 'NAME'],
['sbat-distro-url', 'BUG_REPORT_URL']]
value = get_option(sbatvar[0])
if (value == '' or value == 'auto') and not meson.is_cross_build()
cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1])
value = run_command(sh, '-c', cmd, check: true).stdout().strip()
endif
if value == ''
error('Required @0@ option not set and autodetection failed'.format(sbatvar[0]))
endif
efi_conf.set_quoted(sbatvar[0].underscorify().to_upper(), value)
endforeach
pkgname = get_option('sbat-distro-pkgname')
if pkgname == ''
pkgname = meson.project_name()
endif
efi_conf.set_quoted('SBAT_DISTRO_PKGNAME', pkgname)
pkgver = get_option('sbat-distro-version')
if pkgver == ''
# This is determined during build, not configuration, so we can't display it yet.
efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION')
else
efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver)
endif
endif
summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)},
section : 'UEFI')
if efi_conf.get('SBAT_DISTRO', '') != ''
summary({
'SBAT distro': efi_conf.get('SBAT_DISTRO'),
'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'),
'SBAT distro version': efi_conf.get('SBAT_DISTRO_VERSION'),
'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'),
'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')},
section : 'UEFI')
endif
configure_file(
output : 'efi_config.h',
configuration : efi_conf)
############################################################
efi_includes = [
build_dir_include,
fundamental_include,
include_directories('.'),
]
efi_c_args = [
'-DSD_BOOT=1',
'-ffreestanding',
'-fno-strict-aliasing',
'-fshort-wchar',
'-include', 'efi_config.h',
]
efi_c_args += cc.get_supported_arguments(
'-fwide-exec-charset=UCS2',
# gcc docs says this is required for ms_abi to work correctly.
'-maccumulate-outgoing-args',
'-mstack-protector-guard=global',
)
# Debug information has little value in release builds as no normal human being knows
# how to attach a debugger to EFI binaries running on real hardware. Anyone who does
# certainly has the means to do their own dev build.
if get_option('mode') == 'developer' and get_option('debug')
efi_c_args += '-DEFI_DEBUG'
endif
efi_c_ld_args = [
'-lgcc',
'-nostdlib',
'-static-pie',
'-Wl,--entry=efi_main',
'-Wl,--fatal-warnings',
# These flags should be passed by -static-pie, but for whatever reason the flag translation
# is not enabled on all architectures. Not passing `-static` would just allow the linker to
# use dynamic libraries, (which we can't/don't use anyway). But if `-pie` is missing and the
# gcc build does not default to `-pie` we get a regular (no-pie) binary that will be
# rightfully rejected by elf2efi. Note that meson also passes `-pie` to the linker driver,
# but it is overridden by our `-static-pie`. We also need to pass these directly to the
# linker as `-static`+`-pie` seem to get translated differently.
'-Wl,-static,-pie,--no-dynamic-linker,-z,text',
# EFI has 4KiB pages.
'-z', 'common-page-size=4096',
'-z', 'max-page-size=4096',
'-z', 'noexecstack',
'-z', 'relro',
'-z', 'separate-code',
]
efi_c_ld_args += cc.get_supported_link_arguments(
# binutils >= 2.38
'-Wl,-z,nopack-relative-relocs',
)
# efi_c_args is explicitly passed to targets so that they can override distro-provided flags
# that should not be used for EFI binaries.
efi_disabled_c_args = cc.get_supported_arguments(
'-fcf-protection=none',
'-fno-asynchronous-unwind-tables',
'-fno-exceptions',
'-fno-unwind-tables',
)
efi_override_options = [
'b_coverage=false',
'b_pgo=off',
]
if get_option('b_sanitize') == 'undefined'
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize-link-runtime')
else
efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize=all')
efi_override_options += 'b_sanitize=none'
endif
efi_c_args += efi_disabled_c_args
efi_c_ld_args += efi_disabled_c_args
if cc.get_id() == 'clang'
# clang is too picky sometimes.
efi_c_args += '-Wno-unused-command-line-argument'
efi_c_ld_args += '-Wno-unused-command-line-argument'
endif
efi_arch_c_args = {
'aarch64' : ['-mgeneral-regs-only'],
'arm' : ['-mgeneral-regs-only'],
# Until -mgeneral-regs-only is supported in LoongArch, use the following option instead:
'loongarch64' : ['-mno-lsx', '-mno-lasx'],
# Pass -m64/32 explicitly to make building on x32 work.
'x86_64' : ['-m64', '-march=x86-64', '-mno-red-zone', '-mgeneral-regs-only'],
'x86' : ['-m32', '-march=i686', '-mgeneral-regs-only', '-malign-double'],
}
efi_arch_c_ld_args = {
# libgcc is not compiled with -fshort-wchar, but it does not use it anyways,
# so it's fine to link against it.
'arm' : cc.get_supported_link_arguments('-Wl,--no-wchar-size-warning'),
'x86_64' : ['-m64'],
'x86' : ['-m32'],
}
linker_sanity_code = 'void a(void) {}; void _start(void) { a(); }'
linker_sanity_args = ['-nostdlib', '-Wl,--fatal-warnings']
if not cc.links(linker_sanity_code,
name : 'linker supports -static-pie',
args : [linker_sanity_args, '-static-pie'])
error('Linker does not support -static-pie.')
endif
# https://github.com/llvm/llvm-project/issues/67152
if not cc.links(linker_sanity_code,
name : 'linker supports LTO with -nostdlib',
args : [linker_sanity_args, '-flto'])
efi_c_args += '-fno-lto'
efi_c_ld_args += '-fno-lto'
endif
# https://github.com/llvm/llvm-project/issues/61101
if efi_cpu_family_alt == 'x86' and not cc.links(linker_sanity_code,
name : 'linker supports LTO with -nostdlib (x86)',
args : [linker_sanity_args, '-flto', '-m32'])
efi_arch_c_args += { 'x86' : efi_arch_c_args['x86'] + '-fno-lto' }
efi_arch_c_ld_args += { 'x86' : efi_arch_c_ld_args['x86'] + '-fno-lto' }
endif
############################################################
libefi_sources = files(
'chid.c',
'console.c',
'device-path-util.c',
'devicetree.c',
'drivers.c',
'efi-string.c',
'efivars.c',
'export-vars.c',
'graphics.c',
'initrd.c',
'log.c',
'measure.c',
'part-discovery.c',
'pe.c',
'random-seed.c',
'secure-boot.c',
'shim.c',
'smbios.c',
'ticks.c',
'util.c',
'vmm.c',
)
systemd_boot_sources = files(
'boot.c',
)
stub_sources = files(
'cpio.c',
'linux.c',
'splash.c',
'stub.c',
)
addon_sources = files(
'addon.c',
)
if get_option('b_sanitize') == 'undefined'
libefi_sources += files('ubsan.c')
endif
if host_machine.cpu_family() in ['x86', 'x86_64']
stub_sources += files('linux_x86.c')
endif
# BCD parser only makes sense on arches that Windows supports.
if host_machine.cpu_family() in ['aarch64', 'arm', 'x86_64', 'x86']
systemd_boot_sources += files('bcd.c')
endif
boot_targets = []
efi_elf_binaries = []
efi_archspecs = [
{
'arch' : efi_arch,
'c_args' : [
efi_c_args,
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch + '"',
efi_arch_c_args.get(host_machine.cpu_family(), []),
],
'link_args' : [
efi_c_ld_args,
efi_arch_c_ld_args.get(host_machine.cpu_family(), []),
],
},
]
if efi_arch_alt != ''
efi_archspecs += {
'arch' : efi_arch_alt,
'c_args' : [
efi_c_args,
'-DEFI_MACHINE_TYPE_NAME="' + efi_arch_alt + '"',
efi_arch_c_args.get(efi_cpu_family_alt, []),
],
'link_args' : [
efi_c_ld_args,
efi_arch_c_ld_args.get(efi_cpu_family_alt, []),
],
}
endif
foreach archspec : efi_archspecs
libefi = static_library(
'efi' + archspec['arch'],
fundamental_sources,
libefi_sources,
version_h,
include_directories : efi_includes,
c_args : archspec['c_args'],
gnu_symbol_visibility : 'hidden',
override_options : efi_override_options,
pic : true)
kwargs = {
'include_directories' : efi_includes,
'c_args' : archspec['c_args'],
'link_args' : archspec['link_args'],
'gnu_symbol_visibility' : 'hidden',
'override_options' : efi_override_options,
'pie' : true,
}
efi_elf_binaries += executable(
'systemd-boot' + archspec['arch'],
sources : [systemd_boot_sources, version_h],
link_with : libefi,
name_suffix : 'elf',
kwargs : kwargs)
efi_elf_binaries += executable(
'linux' + archspec['arch'],
sources : [stub_sources, version_h],
link_with : libefi,
name_suffix : 'elf.stub',
kwargs : kwargs)
efi_elf_binaries += executable(
'addon' + archspec['arch'],
sources : [addon_sources, version_h],
name_suffix : 'elf.stub',
kwargs : kwargs)
endforeach
foreach efi_elf_binary : efi_elf_binaries
name = efi_elf_binary.name()
name += name.startswith('systemd-boot') ? '.efi' : '.efi.stub'
# For the addon, given it's empty, we need to explicitly reserve space in the header to account for
# the sections that ukify will add.
if name.startswith('linux')
minimum_sections = get_option('efi-stub-extra-sections')
elif name.startswith('addon')
minimum_sections = get_option('efi-addon-extra-sections')
else
minimum_sections = 0
endif
exe = custom_target(
name,
output : name,
input : efi_elf_binary,
install : true,
install_dir : bootlibdir,
install_tag : 'systemd-boot',
command : [
elf2efi_py,
'--version-major=' + project_major_version,
'--version-minor=' + project_minor_version,
'--efi-major=1',
'--efi-minor=1',
'--subsystem=10',
'--minimum-sections=@0@'.format(minimum_sections),
'--copy-sections=.sbat,.sdmagic,.osrel',
'@INPUT@',
'@OUTPUT@',
])
boot_targets += exe
if name.startswith('linux')
boot_stubs += exe
endif
# This is supposed to match exactly one time
if name == 'addon@0@.efi.stub'.format(efi_arch)
efi_addon = exe.full_path()
endif
test('check-alignment-@0@'.format(name),
check_efi_alignment_py,
args : exe.full_path(),
suite : 'efi')
endforeach
alias_target('systemd-boot', boot_targets)

Some files were not shown because too many files have changed in this diff Show More