]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | # SPDX-License-Identifier: LGPL-2.1-or-later |
3a726fcd | 2 | |
776fabbc | 3 | efi_config_h_dir = meson.current_build_dir() |
320266b9 | 4 | efi_addon = '' |
776fabbc | 5 | |
2d7c857d JJ |
6 | libefitest = static_library( |
7 | 'efitest', | |
8 | files( | |
9 | 'bcd.c', | |
10 | 'efi-string.c', | |
11 | ), | |
12 | build_by_default : false, | |
13 | include_directories : [ | |
14 | basic_includes, | |
15 | include_directories('.'), | |
16 | ], | |
17 | dependencies : userspace) | |
2c7c68e4 | 18 | |
2d7c857d JJ |
19 | efitest_base = { |
20 | 'link_with' : [ | |
21 | libefitest, | |
22 | libshared, | |
23 | ], | |
24 | } | |
25 | efi_test_template = test_template + efitest_base | |
26 | efi_fuzz_template = fuzz_template + efitest_base | |
2c7c68e4 | 27 | |
2d7c857d JJ |
28 | executables += [ |
29 | efi_test_template + { | |
30 | 'sources' : files('test-bcd.c'), | |
3fc72d54 | 31 | 'dependencies' : libzstd_cflags, |
2d7c857d JJ |
32 | 'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_ZSTD'], |
33 | }, | |
34 | efi_test_template + { | |
35 | 'sources' : files('test-efi-string.c'), | |
36 | 'conditions' : ['ENABLE_BOOTLOADER'], | |
37 | }, | |
38 | efi_fuzz_template + { | |
39 | 'sources' : files('fuzz-bcd.c'), | |
40 | }, | |
41 | efi_fuzz_template + { | |
42 | 'sources' : files('fuzz-efi-string.c'), | |
43 | }, | |
e9e40862 JJ |
44 | efi_fuzz_template + { |
45 | 'sources' : files('fuzz-efi-osrel.c'), | |
46 | }, | |
2d7c857d JJ |
47 | efi_fuzz_template + { |
48 | 'sources' : files('fuzz-efi-printf.c'), | |
49 | }, | |
50 | ] | |
2c7c68e4 | 51 | |
dfca5587 | 52 | if conf.get('ENABLE_BOOTLOADER') != 1 |
9cf75222 JJ |
53 | subdir_done() |
54 | endif | |
55 | ||
9cf75222 | 56 | efi_conf = configuration_data() |
9cf75222 JJ |
57 | efi_conf.set10('ENABLE_TPM', get_option('tpm')) |
58 | ||
59 | foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit'] | |
60 | c = get_option('efi-' + ctype).split(',') | |
61 | efi_conf.set(ctype.underscorify().to_upper(), 'EFI_TEXT_ATTR(@0@, @1@)'.format( | |
62 | 'EFI_' + c[0].strip().underscorify().to_upper(), | |
63 | 'EFI_' + c[1].strip().underscorify().to_upper())) | |
64 | endforeach | |
65 | ||
252b6b1b JJ |
66 | if meson.is_cross_build() and get_option('sbat-distro') == 'auto' |
67 | warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.') | |
68 | elif get_option('sbat-distro') != '' | |
9cf75222 | 69 | efi_conf.set_quoted('SBAT_PROJECT', meson.project_name()) |
ea2a57be | 70 | efi_conf.set_quoted('PROJECT_VERSION', meson.project_version().split('~')[0]) |
3f6ce3d4 | 71 | efi_conf.set_quoted('VERSION_TAG', version_tag) |
9cf75222 JJ |
72 | efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL')) |
73 | if get_option('sbat-distro-generation') < 1 | |
74 | error('SBAT Distro Generation must be a positive integer') | |
df7cacae | 75 | endif |
9cf75222 JJ |
76 | efi_conf.set('SBAT_DISTRO_GENERATION', get_option('sbat-distro-generation')) |
77 | foreach sbatvar : [['sbat-distro', 'ID'], | |
78 | ['sbat-distro-summary', 'NAME'], | |
79 | ['sbat-distro-url', 'BUG_REPORT_URL']] | |
80 | value = get_option(sbatvar[0]) | |
252b6b1b | 81 | if (value == '' or value == 'auto') and not meson.is_cross_build() |
9cf75222 | 82 | cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1]) |
68a06b3c | 83 | value = run_command(sh, '-c', cmd, check: true).stdout().strip() |
4b4ee0f7 | 84 | endif |
9cf75222 JJ |
85 | if value == '' |
86 | error('Required @0@ option not set and autodetection failed'.format(sbatvar[0])) | |
53f69d67 | 87 | endif |
9cf75222 | 88 | efi_conf.set_quoted(sbatvar[0].underscorify().to_upper(), value) |
e313e934 JJ |
89 | endforeach |
90 | ||
9cf75222 JJ |
91 | pkgname = get_option('sbat-distro-pkgname') |
92 | if pkgname == '' | |
93 | pkgname = meson.project_name() | |
9137c03c | 94 | endif |
9cf75222 | 95 | efi_conf.set_quoted('SBAT_DISTRO_PKGNAME', pkgname) |
9137c03c | 96 | |
9cf75222 JJ |
97 | pkgver = get_option('sbat-distro-version') |
98 | if pkgver == '' | |
c78b611e JJ |
99 | # This is determined during build, not configuration, so we can't display it yet. |
100 | efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION') | |
101 | else | |
102 | efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver) | |
37efbbd8 | 103 | endif |
ce4121c6 | 104 | endif |
37efbbd8 | 105 | |
2afeaf16 | 106 | summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)}, |
dfca5587 | 107 | section : 'UEFI') |
3f871f12 | 108 | |
e4e44a01 ZJS |
109 | if efi_conf.get('SBAT_DISTRO', '') != '' |
110 | summary({ | |
111 | 'SBAT distro': efi_conf.get('SBAT_DISTRO'), | |
112 | 'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'), | |
4122d686 | 113 | 'SBAT distro version': efi_conf.get('SBAT_DISTRO_VERSION'), |
e4e44a01 ZJS |
114 | 'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'), |
115 | 'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')}, | |
dfca5587 | 116 | section : 'UEFI') |
e4e44a01 ZJS |
117 | endif |
118 | ||
dfca5587 JJ |
119 | configure_file( |
120 | output : 'efi_config.h', | |
121 | configuration : efi_conf) | |
65dcf9f9 | 122 | |
dfca5587 | 123 | ############################################################ |
65dcf9f9 | 124 | |
3c1eee5b ZJS |
125 | efi_includes = [ |
126 | build_dir_include, | |
127 | fundamental_include, | |
128 | include_directories('.'), | |
129 | ] | |
2afeaf16 JJ |
130 | |
131 | efi_c_args = [ | |
132 | '-DSD_BOOT=1', | |
133 | '-ffreestanding', | |
134 | '-fno-strict-aliasing', | |
135 | '-fshort-wchar', | |
136 | '-include', 'efi_config.h', | |
137 | ] | |
138 | ||
139 | efi_c_args += cc.get_supported_arguments( | |
140 | '-fwide-exec-charset=UCS2', | |
141 | # gcc docs says this is required for ms_abi to work correctly. | |
142 | '-maccumulate-outgoing-args', | |
48e1b2c2 | 143 | '-mstack-protector-guard=global', |
2afeaf16 JJ |
144 | ) |
145 | ||
c4ad9b23 JJ |
146 | # Debug information has little value in release builds as no normal human being knows |
147 | # how to attach a debugger to EFI binaries running on real hardware. Anyone who does | |
148 | # certainly has the means to do their own dev build. | |
149 | if get_option('mode') == 'developer' and get_option('debug') | |
150 | efi_c_args += '-DEFI_DEBUG' | |
151 | endif | |
152 | ||
2afeaf16 | 153 | efi_c_ld_args = [ |
2afeaf16 JJ |
154 | '-lgcc', |
155 | '-nostdlib', | |
156 | '-static-pie', | |
157 | '-Wl,--entry=efi_main', | |
158 | '-Wl,--fatal-warnings', | |
159 | ||
a8b53f4f JJ |
160 | # These flags should be passed by -static-pie, but for whatever reason the flag translation |
161 | # is not enabled on all architectures. Not passing `-static` would just allow the linker to | |
162 | # use dynamic libraries, (which we can't/don't use anyway). But if `-pie` is missing and the | |
163 | # gcc build does not default to `-pie` we get a regular (no-pie) binary that will be | |
164 | # rightfully rejected by elf2efi. Note that meson also passes `-pie` to the linker driver, | |
165 | # but it is overridden by our `-static-pie`. We also need to pass these directly to the | |
166 | # linker as `-static`+`-pie` seem to get translated differently. | |
167 | '-Wl,-static,-pie,--no-dynamic-linker,-z,text', | |
2afeaf16 JJ |
168 | |
169 | # EFI has 4KiB pages. | |
170 | '-z', 'common-page-size=4096', | |
171 | '-z', 'max-page-size=4096', | |
172 | ||
173 | '-z', 'noexecstack', | |
823bf39a | 174 | '-z', 'relro', |
142f0c61 | 175 | '-z', 'separate-code', |
2afeaf16 JJ |
176 | ] |
177 | ||
0b042d3d JJ |
178 | efi_c_ld_args += cc.get_supported_link_arguments( |
179 | # binutils >= 2.38 | |
180 | '-Wl,-z,nopack-relative-relocs', | |
181 | ) | |
eff91e2f | 182 | |
2afeaf16 JJ |
183 | # efi_c_args is explicitly passed to targets so that they can override distro-provided flags |
184 | # that should not be used for EFI binaries. | |
185 | efi_disabled_c_args = cc.get_supported_arguments( | |
186 | '-fcf-protection=none', | |
187 | '-fno-asynchronous-unwind-tables', | |
188 | '-fno-exceptions', | |
2afeaf16 JJ |
189 | '-fno-unwind-tables', |
190 | ) | |
2afeaf16 JJ |
191 | efi_override_options = [ |
192 | 'b_coverage=false', | |
193 | 'b_pgo=off', | |
2afeaf16 JJ |
194 | ] |
195 | ||
1e7ff4ba JJ |
196 | if get_option('b_sanitize') == 'undefined' |
197 | efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize-link-runtime') | |
198 | else | |
199 | efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize=all') | |
200 | efi_override_options += 'b_sanitize=none' | |
201 | endif | |
202 | ||
203 | efi_c_args += efi_disabled_c_args | |
204 | efi_c_ld_args += efi_disabled_c_args | |
205 | ||
2afeaf16 JJ |
206 | if cc.get_id() == 'clang' |
207 | # clang is too picky sometimes. | |
208 | efi_c_args += '-Wno-unused-command-line-argument' | |
209 | efi_c_ld_args += '-Wno-unused-command-line-argument' | |
210 | endif | |
211 | ||
b87d6da4 | 212 | efi_arch_c_args = { |
2afeaf16 JJ |
213 | 'aarch64' : ['-mgeneral-regs-only'], |
214 | 'arm' : ['-mgeneral-regs-only'], | |
7ea44f17 JJ |
215 | # Pass -m64/32 explicitly to make building on x32 work. |
216 | 'x86_64' : ['-m64', '-march=x86-64', '-mno-red-zone', '-mgeneral-regs-only'], | |
217 | 'x86' : ['-m32', '-march=i686', '-mgeneral-regs-only', '-malign-double'], | |
218 | } | |
219 | efi_arch_c_ld_args = { | |
220 | # libgcc is not compiled with -fshort-wchar, but it does not use it anyways, | |
221 | # so it's fine to link against it. | |
0b042d3d | 222 | 'arm' : cc.get_supported_link_arguments('-Wl,--no-wchar-size-warning'), |
7ea44f17 JJ |
223 | 'x86_64' : ['-m64'], |
224 | 'x86' : ['-m32'], | |
b87d6da4 | 225 | } |
2afeaf16 | 226 | |
0b042d3d JJ |
227 | linker_sanity_code = 'void a(void) {}; void _start(void) { a(); }' |
228 | linker_sanity_args = ['-nostdlib', '-Wl,--fatal-warnings'] | |
229 | if not cc.links(linker_sanity_code, | |
230 | name : 'linker supports -static-pie', | |
231 | args : [linker_sanity_args, '-static-pie']) | |
232 | error('Linker does not support -static-pie.') | |
233 | endif | |
234 | ||
235 | # https://github.com/llvm/llvm-project/issues/67152 | |
236 | if not cc.links(linker_sanity_code, | |
237 | name : 'linker supports LTO with -nostdlib', | |
238 | args : [linker_sanity_args, '-flto']) | |
239 | efi_c_args += '-fno-lto' | |
240 | efi_c_ld_args += '-fno-lto' | |
241 | endif | |
242 | ||
243 | # https://github.com/llvm/llvm-project/issues/61101 | |
244 | if efi_cpu_family_alt == 'x86' and not cc.links(linker_sanity_code, | |
245 | name : 'linker supports LTO with -nostdlib (x86)', | |
246 | args : [linker_sanity_args, '-flto', '-m32']) | |
247 | efi_arch_c_args += { 'x86' : efi_arch_c_args['x86'] + '-fno-lto' } | |
248 | efi_arch_c_ld_args += { 'x86' : efi_arch_c_ld_args['x86'] + '-fno-lto' } | |
249 | endif | |
250 | ||
2afeaf16 JJ |
251 | ############################################################ |
252 | ||
dfca5587 | 253 | libefi_sources = files( |
e6b0cfad | 254 | 'console.c', |
e6d7dc9a | 255 | 'device-path-util.c', |
65dcf9f9 | 256 | 'devicetree.c', |
ba279392 | 257 | 'drivers.c', |
9080ffd4 | 258 | 'efi-string.c', |
65dcf9f9 | 259 | 'graphics.c', |
46ce6cf7 | 260 | 'initrd.c', |
c2c62035 | 261 | 'log.c', |
65dcf9f9 | 262 | 'measure.c', |
0a1d8ac7 | 263 | 'part-discovery.c', |
65dcf9f9 | 264 | 'pe.c', |
0a1d8ac7 | 265 | 'random-seed.c', |
65dcf9f9 | 266 | 'secure-boot.c', |
05c9f9c2 | 267 | 'shim.c', |
1e66a233 | 268 | 'ticks.c', |
b3c5a707 | 269 | 'util.c', |
ba279392 | 270 | 'vmm.c', |
b3c5a707 | 271 | ) |
65dcf9f9 | 272 | |
b3c5a707 | 273 | systemd_boot_sources = files( |
65dcf9f9 | 274 | 'boot.c', |
b3c5a707 | 275 | ) |
65dcf9f9 | 276 | |
b3c5a707 | 277 | stub_sources = files( |
65dcf9f9 | 278 | 'cpio.c', |
ba2a105c | 279 | 'linux.c', |
65dcf9f9 | 280 | 'splash.c', |
b3c5a707 JJ |
281 | 'stub.c', |
282 | ) | |
65dcf9f9 | 283 | |
f644ea3e LB |
284 | addon_sources = files( |
285 | 'addon.c', | |
286 | ) | |
287 | ||
1e7ff4ba JJ |
288 | if get_option('b_sanitize') == 'undefined' |
289 | libefi_sources += files('ubsan.c') | |
290 | endif | |
291 | ||
dfca5587 | 292 | if host_machine.cpu_family() in ['x86', 'x86_64'] |
b3c5a707 | 293 | stub_sources += files('linux_x86.c') |
65dcf9f9 ZJS |
294 | endif |
295 | ||
77fcf28c | 296 | # BCD parser only makes sense on arches that Windows supports. |
dfca5587 | 297 | if host_machine.cpu_family() in ['aarch64', 'arm', 'x86_64', 'x86'] |
b3c5a707 | 298 | systemd_boot_sources += files('bcd.c') |
77fcf28c | 299 | endif |
2afeaf16 JJ |
300 | |
301 | boot_targets = [] | |
302 | efi_elf_binaries = [] | |
303 | efi_archspecs = [ | |
304 | { | |
305 | 'arch' : efi_arch, | |
7ea44f17 JJ |
306 | 'c_args' : [ |
307 | efi_c_args, | |
308 | '-DEFI_MACHINE_TYPE_NAME="' + efi_arch + '"', | |
309 | efi_arch_c_args.get(host_machine.cpu_family(), []), | |
310 | ], | |
311 | 'link_args' : [ | |
312 | efi_c_ld_args, | |
313 | efi_arch_c_ld_args.get(host_machine.cpu_family(), []), | |
314 | ], | |
2afeaf16 JJ |
315 | }, |
316 | ] | |
317 | if efi_arch_alt != '' | |
318 | efi_archspecs += { | |
319 | 'arch' : efi_arch_alt, | |
7ea44f17 JJ |
320 | 'c_args' : [ |
321 | efi_c_args, | |
322 | '-DEFI_MACHINE_TYPE_NAME="' + efi_arch_alt + '"', | |
323 | efi_arch_c_args.get(efi_cpu_family_alt, []), | |
324 | ], | |
325 | 'link_args' : [ | |
326 | efi_c_ld_args, | |
327 | efi_arch_c_ld_args.get(efi_cpu_family_alt, []), | |
328 | ], | |
2afeaf16 JJ |
329 | } |
330 | endif | |
331 | ||
332 | foreach archspec : efi_archspecs | |
333 | libefi = static_library( | |
334 | 'efi' + archspec['arch'], | |
335 | fundamental_sources, | |
336 | libefi_sources, | |
56a0b906 | 337 | version_h, |
2afeaf16 JJ |
338 | include_directories : efi_includes, |
339 | c_args : archspec['c_args'], | |
2afeaf16 JJ |
340 | gnu_symbol_visibility : 'hidden', |
341 | override_options : efi_override_options, | |
342 | pic : true) | |
343 | ||
0c491d0f YW |
344 | kwargs = { |
345 | 'include_directories' : efi_includes, | |
346 | 'c_args' : archspec['c_args'], | |
347 | 'link_args' : archspec['link_args'], | |
0c491d0f YW |
348 | 'gnu_symbol_visibility' : 'hidden', |
349 | 'override_options' : efi_override_options, | |
350 | 'pie' : true, | |
351 | } | |
352 | ||
2afeaf16 JJ |
353 | efi_elf_binaries += executable( |
354 | 'systemd-boot' + archspec['arch'], | |
56a0b906 | 355 | sources : [systemd_boot_sources, version_h], |
0b042d3d | 356 | link_with : libefi, |
2afeaf16 | 357 | name_suffix : 'elf', |
0c491d0f | 358 | kwargs : kwargs) |
2afeaf16 JJ |
359 | |
360 | efi_elf_binaries += executable( | |
361 | 'linux' + archspec['arch'], | |
56a0b906 | 362 | sources : [stub_sources, version_h], |
0b042d3d | 363 | link_with : libefi, |
2afeaf16 | 364 | name_suffix : 'elf.stub', |
0c491d0f | 365 | kwargs : kwargs) |
f644ea3e LB |
366 | |
367 | efi_elf_binaries += executable( | |
368 | 'addon' + archspec['arch'], | |
56a0b906 | 369 | sources : [addon_sources, version_h], |
f644ea3e | 370 | name_suffix : 'elf.stub', |
0c491d0f | 371 | kwargs : kwargs) |
2afeaf16 JJ |
372 | endforeach |
373 | ||
374 | foreach efi_elf_binary : efi_elf_binaries | |
816df466 | 375 | name = efi_elf_binary.name() |
f644ea3e LB |
376 | name += name.startswith('systemd-boot') ? '.efi' : '.efi.stub' |
377 | # For the addon, given it's empty, we need to explicitly reserve space in the header to account for | |
378 | # the sections that ukify will add. | |
d0bbe324 | 379 | minimum_sections = name.endswith('.stub') ? '15' : '0' |
3f80c139 | 380 | exe = custom_target( |
2afeaf16 JJ |
381 | name, |
382 | output : name, | |
383 | input : efi_elf_binary, | |
384 | install : true, | |
385 | install_dir : bootlibdir, | |
386 | install_tag : 'systemd-boot', | |
387 | command : [ | |
388 | elf2efi_py, | |
ea2a57be | 389 | '--version-major=' + meson.project_version().split('~')[0], |
2afeaf16 JJ |
390 | '--version-minor=0', |
391 | '--efi-major=1', | |
392 | '--efi-minor=1', | |
393 | '--subsystem=10', | |
f644ea3e | 394 | '--minimum-sections=' + minimum_sections, |
898e9edc | 395 | '--copy-sections=.sbat,.sdmagic,.osrel', |
2afeaf16 JJ |
396 | '@INPUT@', |
397 | '@OUTPUT@', | |
398 | ]) | |
3f80c139 ZJS |
399 | boot_targets += exe |
400 | if name.startswith('linux') | |
401 | boot_stubs += exe | |
402 | endif | |
320266b9 ZJS |
403 | |
404 | # This is supposed to match exactly one time | |
405 | if name == 'addon@0@.efi.stub'.format(efi_arch) | |
406 | efi_addon = exe.full_path() | |
407 | endif | |
2afeaf16 JJ |
408 | endforeach |
409 | ||
410 | alias_target('systemd-boot', boot_targets) |