mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
boot: Bring back bootloader builds
This adds back sd-boot builds by using meson compile targets directly. We can do this now, because userspace binaries use the special dependency that allows us to easily separate flags, so that we don't pass anything to EFI builds that shouldn't be passed. Additionally, we pass a bunch of flags to hopefully disable/override any distro provided flags that should not be used for EFI binaries. Fixes: #12275
This commit is contained in:
1
README
1
README
@@ -216,6 +216,7 @@ REQUIREMENTS:
|
||||
awk, sed, grep, and similar tools
|
||||
clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs
|
||||
from source code in C)
|
||||
pyelftools (optional, required for systemd-boot)
|
||||
|
||||
During runtime, you need the following additional
|
||||
dependencies:
|
||||
|
||||
27
meson.build
27
meson.build
@@ -1972,11 +1972,28 @@ if get_option('bootloader') != 'false' and efi_arch != ''
|
||||
elif get_option('bootloader') == 'true' and efi_arch == ''
|
||||
error('EFI not supported for this arch.')
|
||||
endif
|
||||
|
||||
efi_arch_alt = ''
|
||||
if efi_arch == 'x64' and cc.links('''
|
||||
#include <limits.h>
|
||||
int main(int argc, char *argv[]) {
|
||||
return __builtin_popcount(argc - CHAR_MAX);
|
||||
}''', args : ['-m32', '-march=i686'], name : '32bit build possible')
|
||||
efi_arch_alt = 'ia32'
|
||||
endif
|
||||
|
||||
have_pyelftools = pymod.find_installation('python3', required : false, modules : ['elftools']).found()
|
||||
if get_option('bootloader') == 'true' and (not python_39 or not have_pyelftools)
|
||||
error('EFI bootloader support requires Python >= 3.9 and pyelftools.')
|
||||
endif
|
||||
|
||||
conf.set10(
|
||||
'ENABLE_BOOTLOADER',
|
||||
get_option('efi') and
|
||||
get_option('bootloader') in ['auto', 'true'] and
|
||||
efi_arch != '',
|
||||
efi_arch != '' and
|
||||
python_39 and
|
||||
have_pyelftools,
|
||||
)
|
||||
|
||||
if get_option('ukify') == 'auto'
|
||||
@@ -1990,18 +2007,20 @@ conf.set10('ENABLE_UKIFY', want_ukify)
|
||||
|
||||
############################################################
|
||||
#
|
||||
elf2efi_lds = project_source_root / 'tools/elf2efi.lds'
|
||||
elf2efi_py = find_program('tools/elf2efi.py')
|
||||
export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
|
||||
generate_gperfs = find_program('tools/generate-gperfs.py')
|
||||
make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
|
||||
make_directive_index_py = find_program('tools/make-directive-index.py')
|
||||
make_man_index_py = find_program('tools/make-man-index.py')
|
||||
meson_render_jinja2 = find_program('tools/meson-render-jinja2.py')
|
||||
update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
|
||||
update_man_rules_py = find_program('tools/update-man-rules.py')
|
||||
update_hwdb_sh = find_program('tools/update-hwdb.sh')
|
||||
update_hwdb_autosuspend_sh = find_program('tools/update-hwdb-autosuspend.sh')
|
||||
update_hwdb_sh = find_program('tools/update-hwdb.sh')
|
||||
update_man_rules_py = find_program('tools/update-man-rules.py')
|
||||
update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh')
|
||||
xml_helper_py = find_program('tools/xml_helper.py')
|
||||
export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
|
||||
|
||||
############################################################
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "shim.h"
|
||||
#include "ticks.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
#include "vmm.h"
|
||||
|
||||
/* Magic string for recognizing our own binaries */
|
||||
|
||||
@@ -126,7 +126,7 @@ _gnu_printf_(2, 0) _warn_unused_result_ char16_t *xvasprintf_status(EFI_STATUS s
|
||||
/* inttypes.h is provided by libc instead of the compiler and is not supposed to be used in freestanding
|
||||
* environments. We could use clang __*_FMT*__ constants for this, bug gcc does not have them. :( */
|
||||
|
||||
# if defined(__ILP32__) || defined(__arm__)
|
||||
# if defined(__ILP32__) || defined(__arm__) || defined(__i386__)
|
||||
# define PRI64_PREFIX "ll"
|
||||
# elif defined(__LP64__)
|
||||
# define PRI64_PREFIX "l"
|
||||
|
||||
@@ -57,7 +57,7 @@ elif get_option('sbat-distro') != ''
|
||||
endif
|
||||
endif
|
||||
|
||||
summary({'UEFI architecture' : efi_arch},
|
||||
summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)},
|
||||
section : 'UEFI')
|
||||
|
||||
if efi_conf.get('SBAT_DISTRO', '') != ''
|
||||
@@ -76,6 +76,97 @@ configure_file(
|
||||
|
||||
############################################################
|
||||
|
||||
efi_includes = [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',
|
||||
)
|
||||
|
||||
efi_c_ld_args = [
|
||||
# We only support bfd. gold is going away, lld has issues with LTO on x86
|
||||
# and mold does not support linker scripts.
|
||||
'-fuse-ld=bfd',
|
||||
|
||||
'-lgcc',
|
||||
'-nostdlib',
|
||||
'-static-pie',
|
||||
'-Wl,--entry=efi_main',
|
||||
'-Wl,--fatal-warnings',
|
||||
|
||||
# These flags should be passed by -static-pie, but seem to be missing sometimes.
|
||||
'-Wl,--no-dynamic-linker',
|
||||
'-z', 'text',
|
||||
|
||||
# EFI has 4KiB pages.
|
||||
'-z', 'common-page-size=4096',
|
||||
'-z', 'max-page-size=4096',
|
||||
|
||||
'-z', 'noexecstack',
|
||||
'-z', 'norelro',
|
||||
'-T' + elf2efi_lds,
|
||||
]
|
||||
|
||||
# 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-trapv',
|
||||
'-fno-sanitize=all',
|
||||
'-fno-stack-clash-protection',
|
||||
'-fno-stack-protector',
|
||||
'-fno-unwind-tables',
|
||||
)
|
||||
efi_c_args += efi_disabled_c_args
|
||||
efi_c_ld_args += efi_disabled_c_args
|
||||
efi_override_options = [
|
||||
'b_coverage=false',
|
||||
'b_pgo=off',
|
||||
'b_sanitize=none',
|
||||
]
|
||||
|
||||
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
|
||||
|
||||
if host_machine.cpu_family() == 'arm'
|
||||
# libgcc is not compiled with -fshort-wchar, but it does not use it anyways,
|
||||
# so it's fine to link against it.
|
||||
efi_c_ld_args += '-Wl,--no-wchar-size-warning'
|
||||
endif
|
||||
|
||||
efi_c_args_primary = [efi_c_args, '-DEFI_MACHINE_TYPE_NAME="' + efi_arch + '"']
|
||||
efi_c_args_alt = [efi_c_args, '-DEFI_MACHINE_TYPE_NAME="' + efi_arch_alt + '"']
|
||||
efi_c_ld_args_primary = efi_c_ld_args
|
||||
efi_c_ld_args_alt = efi_c_ld_args
|
||||
|
||||
efi_c_args_primary += {
|
||||
'aarch64' : ['-mgeneral-regs-only'],
|
||||
'arm' : ['-mgeneral-regs-only'],
|
||||
'x86_64' : ['-march=x86-64', '-mno-red-zone', '-mgeneral-regs-only'],
|
||||
'x86' : ['-march=i686', '-mgeneral-regs-only'],
|
||||
}.get(host_machine.cpu_family(), [])
|
||||
|
||||
if efi_arch_alt == 'ia32'
|
||||
efi_c_args_alt += ['-m32', '-march=i686', '-mgeneral-regs-only']
|
||||
efi_c_ld_args_alt += '-m32'
|
||||
endif
|
||||
|
||||
############################################################
|
||||
|
||||
libefi_sources = files(
|
||||
'console.c',
|
||||
'device-path-util.c',
|
||||
@@ -155,3 +246,86 @@ if host_machine.cpu_family() in ['aarch64', 'arm', 'x86_64', 'x86']
|
||||
},
|
||||
]
|
||||
endif
|
||||
|
||||
boot_targets = []
|
||||
efi_elf_binaries = []
|
||||
efi_archspecs = [
|
||||
{
|
||||
'arch' : efi_arch,
|
||||
'c_args' : efi_c_args_primary,
|
||||
'link_args' : efi_c_ld_args_primary,
|
||||
},
|
||||
]
|
||||
if efi_arch_alt != ''
|
||||
efi_archspecs += {
|
||||
'arch' : efi_arch_alt,
|
||||
'c_args' : efi_c_args_alt,
|
||||
'link_args' : efi_c_ld_args_alt,
|
||||
}
|
||||
endif
|
||||
|
||||
foreach archspec : efi_archspecs
|
||||
libefi = static_library(
|
||||
'efi' + archspec['arch'],
|
||||
fundamental_sources,
|
||||
libefi_sources,
|
||||
include_directories : efi_includes,
|
||||
c_args : archspec['c_args'],
|
||||
dependencies : versiondep,
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
override_options : efi_override_options,
|
||||
pic : true)
|
||||
|
||||
efi_elf_binaries += executable(
|
||||
'systemd-boot' + archspec['arch'],
|
||||
systemd_boot_sources,
|
||||
include_directories : efi_includes,
|
||||
c_args : archspec['c_args'],
|
||||
link_args : archspec['link_args'],
|
||||
link_with : libefi,
|
||||
link_depends : elf2efi_lds,
|
||||
dependencies : versiondep,
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
override_options : efi_override_options,
|
||||
name_suffix : 'elf',
|
||||
pie : true)
|
||||
|
||||
efi_elf_binaries += executable(
|
||||
'linux' + archspec['arch'],
|
||||
stub_sources,
|
||||
include_directories : efi_includes,
|
||||
c_args : archspec['c_args'],
|
||||
link_args : archspec['link_args'],
|
||||
link_with : libefi,
|
||||
link_depends : elf2efi_lds,
|
||||
dependencies : versiondep,
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
override_options : efi_override_options,
|
||||
name_suffix : 'elf.stub',
|
||||
pie : true)
|
||||
endforeach
|
||||
|
||||
foreach efi_elf_binary : efi_elf_binaries
|
||||
# FIXME: Use build_tgt.name() with meson >= 0.54.0
|
||||
name = fs.name(efi_elf_binary.full_path()).split('.')[0]
|
||||
name += name.startswith('linux') ? '.efi.stub' : '.efi'
|
||||
boot_targets += custom_target(
|
||||
name,
|
||||
output : name,
|
||||
input : efi_elf_binary,
|
||||
install : true,
|
||||
install_dir : bootlibdir,
|
||||
install_tag : 'systemd-boot',
|
||||
command : [
|
||||
elf2efi_py,
|
||||
'--version-major=' + meson.project_version(),
|
||||
'--version-minor=0',
|
||||
'--efi-major=1',
|
||||
'--efi-minor=1',
|
||||
'--subsystem=10',
|
||||
'@INPUT@',
|
||||
'@OUTPUT@',
|
||||
])
|
||||
endforeach
|
||||
|
||||
alias_target('systemd-boot', boot_targets)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "splash.h"
|
||||
#include "tpm-pcr.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
#include "vmm.h"
|
||||
|
||||
/* magic string to find in the binary image */
|
||||
|
||||
@@ -168,18 +168,18 @@ void hexdump(const char16_t *prefix, const void *data, size_t size);
|
||||
# define notify_debugger(i, w)
|
||||
#endif
|
||||
|
||||
#define DEFINE_EFI_MAIN_FUNCTION(func, identity, wait_for_debugger) \
|
||||
EFI_SYSTEM_TABLE *ST; \
|
||||
EFI_BOOT_SERVICES *BS; \
|
||||
EFI_RUNTIME_SERVICES *RT; \
|
||||
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) { \
|
||||
ST = system_table; \
|
||||
BS = system_table->BootServices; \
|
||||
RT = system_table->RuntimeServices; \
|
||||
notify_debugger((identity), (wait_for_debugger)); \
|
||||
EFI_STATUS err = func(image); \
|
||||
log_wait(); \
|
||||
return err; \
|
||||
#define DEFINE_EFI_MAIN_FUNCTION(func, identity, wait_for_debugger) \
|
||||
EFI_SYSTEM_TABLE *ST; \
|
||||
EFI_BOOT_SERVICES *BS; \
|
||||
EFI_RUNTIME_SERVICES *RT; \
|
||||
EFIAPI EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) { \
|
||||
ST = system_table; \
|
||||
BS = system_table->BootServices; \
|
||||
RT = system_table->RuntimeServices; \
|
||||
notify_debugger((identity), (wait_for_debugger)); \
|
||||
EFI_STATUS err = func(image); \
|
||||
log_wait(); \
|
||||
return err; \
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#ifdef SBAT_DISTRO
|
||||
# define SBAT_SECTION_TEXT \
|
||||
"sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md\n" \
|
||||
|
||||
49
tools/elf2efi.lds
Normal file
49
tools/elf2efi.lds
Normal file
@@ -0,0 +1,49 @@
|
||||
SECTIONS {
|
||||
/* We skip the first page because the space will be occupied by the PE headers after conversion. */
|
||||
. = CONSTANT(MAXPAGESIZE);
|
||||
.text ALIGN(CONSTANT(MAXPAGESIZE)) : {
|
||||
*(.text .text.*)
|
||||
}
|
||||
.rodata ALIGN(CONSTANT(MAXPAGESIZE)) : {
|
||||
*(.rodata .rodata.*)
|
||||
*(.srodata .srodata.*)
|
||||
}
|
||||
.data ALIGN(CONSTANT(MAXPAGESIZE)) : {
|
||||
*(.data .data.*)
|
||||
*(.sdata .sdata.*)
|
||||
*(.got .got.*)
|
||||
*(.got.plt .got.plt.*)
|
||||
|
||||
/* EDK2 says some firmware cannot handle BSS sections properly. */
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
.sdmagic ALIGN(CONSTANT(MAXPAGESIZE)) : { *(.sdmagic) }
|
||||
.osrel ALIGN(CONSTANT(MAXPAGESIZE)) : { *(.osrel) }
|
||||
.sbat ALIGN(CONSTANT(MAXPAGESIZE)) : { *(.sbat) }
|
||||
|
||||
/* These are used for PE conversion and then discarded. */
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.rel.dyn : { *(.rel.dyn) }
|
||||
.rela.dyn : { *(.rela.dyn) }
|
||||
|
||||
/* These aren't needed and could be discarded. Just in case that they're useful to the debugger
|
||||
* we keep them, but move them out of the way to keep the PE binary more compact. */
|
||||
.ARM.exidx : { *(.ARM.exidx) }
|
||||
.eh_frame : { *(.eh_frame) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.hash : { *(.hash) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id ) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.ARM.attributes)
|
||||
*(.comment)
|
||||
*(.note.*)
|
||||
*(.riscv.attributes)
|
||||
}
|
||||
}
|
||||
578
tools/elf2efi.py
Executable file
578
tools/elf2efi.py
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user