Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only use local crt0 and lds files #57

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [fedora, debian-x86_64, arch, debian-i386]
steps:
Expand Down
82 changes: 82 additions & 0 deletions efi/crt0/crt0-efi-ia32.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* crt0-efi-ia32.S - x86 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <[email protected]>.

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/

.text
.align 4

.globl _start
.type _start,%function
_start:
pushl %ebp
movl %esp,%ebp

pushl 12(%ebp) # copy "image" argument
pushl 8(%ebp) # copy "systab" argument

call 0f
0: popl %eax
movl %eax,%ebx

addl $ImageBase-0b,%eax # %eax = ldbase
addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC

pushl %ebx # pass _DYNAMIC as second argument
pushl %eax # pass ldbase as first argument
call _relocate
popl %ebx
popl %ebx
testl %eax,%eax
jne .exit

call _entry # call app with "image" and "systab" argument

.exit: leave
ret

// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:

.data
dummy: .4byte 0

#define IMAGE_REL_ABSOLUTE 0
.section .reloc
.4byte dummy // Page RVA
.4byte 12 // Block Size (2*4+2*2), must be aligned by 32 Bits
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy

#if defined(__ELF__) && defined(__linux__)
.section .note.GNU-stack,"",%progbits
#endif
81 changes: 81 additions & 0 deletions efi/crt0/crt0-efi-x86_64.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* crt0-efi-x86_64.S - x86_64 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <[email protected]>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <[email protected]>.

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
.text
.align 4

.globl _start
.type _start,%function
_start:
subq $8, %rsp
pushq %rcx
pushq %rdx

0:
lea ImageBase(%rip), %rdi
lea _DYNAMIC(%rip), %rsi

popq %rcx
popq %rdx
pushq %rcx
pushq %rdx
call _relocate

popq %rdi
popq %rsi

call _entry
addq $8, %rsp

.exit:
ret

// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:

.data
dummy: .4byte 0

#define IMAGE_REL_ABSOLUTE 0
.section .reloc, "a"
label1:
.4byte dummy-label1 // Page RVA
.4byte 12 // Block Size (2*4+2*2), must be aligned by 32 Bits
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy

#if defined(__ELF__) && defined(__linux__)
.section .note.GNU-stack,"",%progbits
#endif
102 changes: 8 additions & 94 deletions efi/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ if uswid.found()
)
endif

efi_ldsdir = get_option('efi-ldsdir')
efi_incdir = get_option('efi-includedir')

gnu_efi_path_arch = ''
Expand All @@ -47,46 +46,14 @@ endif

have_gnu_efi = gnu_efi_path_arch != '' and efi_libdir != ''

if not have_gnu_efi
error('gnu-efi support requested, but headers were not found')
if not have_gnu_efi and not gnuefi.found()
error('gnu-efi headers were not found')
endif

# The name we need to look for on this arch and OS: elf_x86_64_fbsd_efi.lds
lds_os = ''
if host_cpu == 'x86_64' and host_machine.system() == 'freebsd'
lds_os = '_fbsd'
endif

arch_lds = 'efi.lds'
arch_crt = 'crt0.o'
if efi_ldsdir == ''
efi_ldsdir = join_paths(efi_libdir, 'gnuefi', gnu_efi_path_arch)
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds), check: false)
if cmd.returncode() != 0
arch_lds = 'elf_@0@@1@_efi.lds'.format(gnu_efi_path_arch, lds_os)
arch_crt = 'crt0-efi-@[email protected]'.format(gnu_efi_path_arch)
efi_ldsdir = join_paths(efi_libdir, 'gnuefi')
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds), check: false)
endif
if cmd.returncode() != 0
efi_ldsdir = efi_libdir
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds), check: false)
if cmd.returncode() != 0
error('Cannot find @0@'.format(arch_lds))
endif
endif
else
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds), check: false)
if cmd.returncode() != 0
arch_lds = 'elf_@0@@1@_efi.lds'.format(gnu_efi_path_arch, lds_os)
arch_crt = 'crt0-efi-@[email protected]'.format(gnu_efi_path_arch)
cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds), check: false)
endif
if cmd.returncode() != 0
error('Cannot find @0@'.format(arch_lds))
endif
endif
efi_crtdir = efi_ldsdir
efi_ldsdir = join_paths(meson.current_source_dir(), 'lds')
efi_crtdir = join_paths(meson.current_build_dir(), 'crt0')
arch_lds = 'elf_@0@_efi.lds'.format(gnu_efi_arch)
arch_crt = 'crt0-efi-@[email protected]'.format(gnu_efi_path_arch)

# If using objcopy, crt0 must not include the PE/COFF header
if run_command('grep', '-q', 'coff_header', join_paths(efi_crtdir, arch_crt), check: false).returncode() == 0
Expand All @@ -95,11 +62,6 @@ else
coff_header_in_crt0 = false
endif

# For NX compat, we must ensure we have .note.GNU-stack
if run_command('grep', '-q', '.note.GNU-stack', join_paths(efi_crtdir, arch_crt), check: false).returncode() != 0
warning('Cannot find NX section in @0@, update to gnu-efi 3.0.15+'.format(join_paths(efi_crtdir, arch_crt)))
endif

# older objcopy for Aarch64, ARM32 and RISC-V are not EFI capable.
# Use 'binary' instead, and add required symbols manually.
if host_cpu == 'arm' or host_cpu == 'riscv64' or (host_cpu == 'aarch64' and (objcopy_version.version_compare ('< 2.38') or coff_header_in_crt0 or uswid.found()))
Expand All @@ -113,50 +75,7 @@ else
generate_binary_extra = []
endif

# is the system linker script new enough to know about SBAT?
# i.e. gnu-efi with https://github.com/vathpela/gnu-efi/pull/14 has been installed
if get_option('efi_sbat_distro_id') != ''
cmd = run_command('grep', '-q', 'sbat', join_paths(efi_ldsdir, arch_lds), check: false)
if cmd.returncode() != 0
warning('Cannot find SBAT section in @0@, using local copy'.format(join_paths(efi_ldsdir, arch_lds)))
efi_ldsdir = join_paths(meson.current_source_dir(), 'lds')
arch_lds = 'elf_@0@@1@_efi.lds'.format(gnu_efi_arch, lds_os)
endif
endif

# SBOM is never in system lds
if uswid.found()
warning('Switching to local copy of linker script as using SBOM')
efi_ldsdir = join_paths(meson.current_source_dir(), 'lds')
arch_lds = 'elf_@0@@1@_efi.lds'.format(gnu_efi_arch, lds_os)
endif

# is the system crt0 for arm and aarch64 new enough to know about SBAT?
if objcopy_manualsymbols
if get_option('efi_sbat_distro_id') != ''
cmd = run_command('grep', '-q', 'sbat', join_paths(efi_crtdir, arch_crt), check: false)
if cmd.returncode() != 0
warning('Cannot find SBAT section in @0@, using local copy'.format(join_paths(efi_crtdir, arch_crt)))
# The gnuefi libraries are still needed
efi_libdir = efi_crtdir
efi_crtdir = join_paths(meson.current_build_dir(), 'crt0')
efi_ldsdir = join_paths(meson.current_source_dir(), 'lds')
endif
endif
endif

# SBOM not in system crt0
if objcopy_manualsymbols
if uswid.found()
warning('Switching to local copy of crt0 as using SBOM')
efi_crtdir = join_paths(meson.current_build_dir(), 'crt0')
efi_ldsdir = join_paths(meson.current_source_dir(), 'lds')
endif
endif

message('efi-libdir: "@0@"'.format(efi_libdir))
message('efi-ldsdir: "@0@"'.format(efi_ldsdir))
message('efi-crtdir: "@0@"'.format(efi_crtdir))
message('efi-includedir: "@0@"'.format(efi_incdir))

debugdir = join_paths (libdir, 'debug')
Expand Down Expand Up @@ -293,12 +212,7 @@ if uswid.found()
] + uswid_cflags)
endif

fwupd_so_deps = []
if efi_crtdir == join_paths(meson.current_build_dir(), 'crt0')
# A custom crt0 is needed
subdir('crt0')
fwupd_so_deps += [o_crt0]
endif
subdir('crt0')

efi_cc_ldflags = []
foreach flag : efi_ldflags
Expand All @@ -311,7 +225,7 @@ so = custom_target('fwup.so',
command : [cc.cmd_array(), '-nostdlib', '-o', '@OUTPUT@'] +
efi_cc_ldflags + ['@INPUT@'] +
['-lefi', '-lgnuefi', libgcc_file_name],
depends: fwupd_so_deps)
depends: o_crt0)

app = custom_target(efi_name,
input : so,
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ cc = meson.get_compiler('c')
objcopy = find_program('objcopy')
objcopy_version = run_command(objcopy, '--version', check: true).stdout().split('\n')[0].split(' ')[-1]

# pkgconfig introduced in 3.0.18, allows compiling against older
gnuefi = dependency('gnu-efi', required: false)
prefix = get_option('prefix')
libdir = join_paths(prefix, get_option('libdir'))
libexecdir = join_paths(prefix, get_option('libexecdir'))
Expand Down
1 change: 0 additions & 1 deletion meson_options.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
option('efi-libdir', type : 'string', description : 'path to the EFI lib directory')
option('efi-ldsdir', type : 'string', description : 'path to the EFI lds directory')
option('efi-includedir', type : 'string', value : '/usr/include/efi', description : 'path to the EFI header directory')
option('efi_sbat_fwupd_generation', type : 'integer', value : 1, description : 'SBAT fwupd generation')
option('efi_sbat_distro_id', type : 'string', value : '', description : 'SBAT distribution ID, e.g. fedora')
Expand Down
Loading