1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-22 13:33:56 +03:00

Merge pull request #21225 from medhefgo/boot-cleanup

Boot cleanup
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-11-05 14:53:47 +01:00 committed by GitHub
commit 7f9521d5e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 96 additions and 89 deletions

View File

@ -328,13 +328,6 @@ static inline int __coverity_check_and_return__(int condition) {
ans; \
})
#define UPDATE_FLAG(orig, flag, b) \
((b) ? ((orig) | (flag)) : ((orig) & ~(flag)))
#define SET_FLAG(v, flag, b) \
(v) = UPDATE_FLAG(v, flag, b)
#define FLAGS_SET(v, flags) \
((~(v) & (flags)) == 0)
#define SWAP_TWO(x, y) do { \
typeof(x) _t = (x); \
(x) = (y); \

View File

@ -551,7 +551,7 @@ static EFI_STATUS reboot_into_firmware(void) {
UINT64 osind = 0;
EFI_STATUS err;
if (!(get_os_indications_supported() & EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
if (!FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
return log_error_status_stall(EFI_UNSUPPORTED, L"Reboot to firmware interface not supported.");
(void) efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &osind);
@ -924,7 +924,7 @@ static BOOLEAN menu_run(
case KEYPRESS(0, SCAN_F10, 0): /* HP and Lenovo. */
case KEYPRESS(0, SCAN_DELETE, 0): /* Same as F2. */
case KEYPRESS(0, SCAN_ESC, 0): /* HP. */
if (get_os_indications_supported() & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) {
if (FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) {
firmware_setup = TRUE;
/* Let's make sure the user really wants to do this. */
status = PoolPrint(L"Press Enter to reboot into firmware interface.");
@ -1590,7 +1590,7 @@ static void config_load_entries(
if (f->FileName[0] == '.')
continue;
if (f->Attribute & EFI_FILE_DIRECTORY)
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
continue;
if (!endswith_no_case(f->FileName, L".conf"))
@ -2026,16 +2026,23 @@ static void config_entry_add_linux(
return;
for (;;) {
enum {
SECTION_CMDLINE,
SECTION_OSREL,
_SECTION_MAX,
};
static const CHAR8* const sections[_SECTION_MAX + 1] = {
[SECTION_CMDLINE] = (const CHAR8 *) ".cmdline",
[SECTION_OSREL] = (const CHAR8 *) ".osrel",
NULL,
};
_cleanup_freepool_ CHAR16 *os_name_pretty = NULL, *os_name = NULL, *os_id = NULL,
*os_version = NULL, *os_version_id = NULL, *os_build_id = NULL, *os_image_version = NULL;
_cleanup_freepool_ CHAR8 *content = NULL;
const CHAR8 *sections[] = {
(CHAR8 *)".osrel",
(CHAR8 *)".cmdline",
NULL
};
UINTN offs[ELEMENTSOF(sections)-1] = {};
UINTN szs[ELEMENTSOF(sections)-1] = {};
UINTN offs[_SECTION_MAX] = {};
UINTN szs[_SECTION_MAX] = {};
CHAR8 *line;
UINTN pos = 0;
CHAR8 *key, *value;
@ -2046,7 +2053,7 @@ static void config_entry_add_linux(
if (f->FileName[0] == '.')
continue;
if (f->Attribute & EFI_FILE_DIRECTORY)
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
continue;
if (!endswith_no_case(f->FileName, L".efi"))
continue;
@ -2054,11 +2061,11 @@ static void config_entry_add_linux(
continue;
/* look for .osrel and .cmdline sections in the .efi binary */
err = pe_file_locate_sections(linux_dir, f->FileName, sections, offs, szs);
if (EFI_ERROR(err))
err = pe_file_locate_sections(linux_dir, f->FileName, (const CHAR8**) sections, offs, szs);
if (EFI_ERROR(err) || szs[SECTION_OSREL] == 0)
continue;
err = file_read(linux_dir, f->FileName, offs[0], szs[0], &content, NULL);
err = file_read(linux_dir, f->FileName, offs[SECTION_OSREL], szs[SECTION_OSREL], &content, NULL);
if (EFI_ERROR(err))
continue;
@ -2122,21 +2129,24 @@ static void config_entry_add_linux(
path,
os_image_version ?: (os_version ?: (os_version_id ? : os_build_id)));
config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi");
if (szs[SECTION_CMDLINE] == 0)
continue;
FreePool(content);
content = NULL;
/* read the embedded cmdline file */
err = file_read(linux_dir, f->FileName, offs[1], szs[1], &content, NULL);
err = file_read(linux_dir, f->FileName, offs[SECTION_CMDLINE], szs[SECTION_CMDLINE], &content, NULL);
if (!EFI_ERROR(err)) {
/* chomp the newline */
if (content[szs[1]-1] == '\n')
content[szs[1]-1] = '\0';
if (content[szs[SECTION_CMDLINE] - 1] == '\n')
content[szs[SECTION_CMDLINE] - 1] = '\0';
entry->options = stra_to_str(content);
}
config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi");
}
}
}
@ -2352,7 +2362,7 @@ static void config_load_all_entries(
config_entry_add_loader_auto(config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
L"auto-efi-default", '\0', L"EFI Default Loader", NULL);
if (config->auto_firmware && (get_os_indications_supported() & EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
if (config->auto_firmware && FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
config_entry_add_call(config,
L"auto-reboot-to-firmware-setup",
L"Reboot Into Firmware Interface",

View File

@ -375,7 +375,7 @@ EFI_STATUS pack_cpio(
if (dirent->FileName[0] == '.')
continue;
if (dirent->Attribute & EFI_FILE_DIRECTORY)
if (FLAGS_SET(dirent->Attribute, EFI_FILE_DIRECTORY))
continue;
if (match_suffix && !endswith_no_case(dirent->FileName, match_suffix))
continue;

View File

@ -103,7 +103,7 @@ EFI_STATUS load_drivers(
if (dirent->FileName[0] == '.')
continue;
if (dirent->Attribute & EFI_FILE_DIRECTORY)
if (FLAGS_SET(dirent->Attribute, EFI_FILE_DIRECTORY))
continue;
if (!endswith_no_case(dirent->FileName, EFI_MACHINE_TYPE_NAME L".efi"))
continue;

View File

@ -45,6 +45,12 @@ stub_sources = '''
cpio.c
'''.split()
if efi_arch in ['x86', 'x86_64']
stub_sources += 'linux_x86.c'
else
stub_sources += 'linux.c'
endif
if conf.get('ENABLE_EFI') == 1 and get_option('gnu-efi') != 'false'
efi_cc = get_option('efi-cc')
if efi_cc.length() == 0
@ -197,11 +203,10 @@ if have_gnu_efi
compile_args = cc.get_supported_arguments(
basic_disabled_warnings +
possible_common_cc_flags + [
'-ffreestanding',
'-fno-stack-protector',
'-fno-strict-aliasing',
'-fpic',
'-fshort-wchar',
'-fwide-exec-charset=UCS2',
'-Wall',
'-Wextra',
'-Wsign-compare',
@ -209,6 +214,8 @@ if have_gnu_efi
) + [
'-nostdlib',
'-std=gnu99',
'-ffreestanding',
'-fshort-wchar',
'-isystem', efi_incdir,
'-isystem', efi_incdir / gnu_efi_path_arch,
'-I', fundamental_path,
@ -217,46 +224,52 @@ if have_gnu_efi
'-include', efi_config_h,
'-include', version_h,
]
if ['ia32', 'x86_64'].contains(efi_arch)
stub_sources += 'linux_x86.c'
else
stub_sources += 'linux.c'
endif
if efi_arch == 'x86_64'
compile_args += ['-mno-red-zone',
'-mno-sse',
'-mno-mmx']
elif efi_arch == 'ia32'
elif efi_arch == 'x86'
compile_args += ['-mno-sse',
'-mno-mmx']
elif efi_arch == 'arm'
if cc.has_argument('-mgeneral-regs-only')
compile_args += ['-mgeneral-regs-only']
endif
if cc.has_argument('-mfpu=none')
compile_args += ['-mfpu=none']
endif
compile_args += cc.get_supported_arguments([
'-mgeneral-regs-only',
'-mfpu=none'
])
endif
if get_option('werror') == true
# We are putting the efi_cc command line together ourselves, so make sure to pull any
# relevant compiler flags from meson/CFLAGS as povided by the user or distro.
if get_option('werror')
compile_args += ['-Werror']
endif
if get_option('buildtype') == 'debug'
compile_args += ['-ggdb', '-O0', '-DEFI_DEBUG']
elif get_option('buildtype') == 'debugoptimized'
compile_args += ['-ggdb', '-Og', '-DEFI_DEBUG']
else
compile_args += ['-O2']
if get_option('debug')
compile_args += ['-ggdb', '-DEFI_DEBUG']
endif
if get_option('optimization') != '0'
compile_args += ['-O' + get_option('optimization')]
endif
if get_option('b_ndebug') == 'true' or (
get_option('b_ndebug') == 'if-release' and ['plain', 'release'].contains(get_option('buildtype')))
compile_args += ['-DNDEBUG']
endif
foreach arg : get_option('c_args')
if arg in ['-Werror', '-g', '-ggdb', '-O1', '-O2', '-O3', '-Og', '-Os', '-DNDEBUG']
message('Using "@0@" from c_args for EFI compiler'.format(arg))
compile_args += arg
endif
endforeach
efi_ldflags = ['-T', efi_lds,
'-shared',
'-Bsymbolic',
'-nostdlib',
'--no-undefined',
'--warn-common',
'--fatal-warnings',
'-znocombreloc',
'--build-id=sha1',
'-L', efi_libdir,
@ -291,7 +304,6 @@ if have_gnu_efi
systemd_boot_efi_name = 'systemd-boot@0@.efi'.format(EFI_MACHINE_TYPE_NAME)
stub_elf_name = 'linux@0@.elf.stub'.format(EFI_MACHINE_TYPE_NAME)
stub_efi_name = 'linux@0@.efi.stub'.format(EFI_MACHINE_TYPE_NAME)
no_undefined_symbols = find_program('no-undefined-symbols.sh')
efi_stubs = []
foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects, false],
@ -325,12 +337,6 @@ if have_gnu_efi
install_dir : bootlibdir)
efi_stubs += [[so, stub]]
if want_tests != 'false'
test('no-undefined-symbols-' + tuple[0],
no_undefined_symbols,
args : so)
endif
endforeach
############################################################

View File

@ -1,9 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
set -o pipefail
if nm -D -u "${1:?}" | grep ' U '; then
echo "Undefined symbols detected!"
exit 1
fi

View File

@ -122,7 +122,8 @@ static inline BOOLEAN verify_pe(const struct PeFileHeader *pe) {
return CompareMem(pe->Magic, PE_FILE_MAGIC, STRLEN(PE_FILE_MAGIC)) == 0 &&
pe->FileHeader.Machine == TARGET_MACHINE_TYPE &&
pe->FileHeader.NumberOfSections > 0 &&
pe->FileHeader.NumberOfSections <= MAX_SECTIONS;
pe->FileHeader.NumberOfSections <= MAX_SECTIONS &&
IN_SET(pe->OptionalHeader.Magic, OPTHDR32_MAGIC, OPTHDR64_MAGIC);
}
static inline UINTN section_table_offset(const struct DosFileHeader *dos, const struct PeFileHeader *pe) {
@ -182,15 +183,8 @@ EFI_STATUS pe_alignment_info(
return EFI_LOAD_ERROR;
*ret_entry_point_address = pe->OptionalHeader.AddressOfEntryPoint;
if (pe->OptionalHeader.Magic == OPTHDR32_MAGIC) {
*ret_size_of_image = pe->OptionalHeader.SizeOfImage;
*ret_section_alignment = pe->OptionalHeader.SectionAlignment;
} else if (pe->OptionalHeader.Magic == OPTHDR64_MAGIC) {
*ret_size_of_image = pe->OptionalHeader.SizeOfImage;
*ret_section_alignment = pe->OptionalHeader.SectionAlignment;
} else
return EFI_UNSUPPORTED;
*ret_size_of_image = pe->OptionalHeader.SizeOfImage;
*ret_section_alignment = pe->OptionalHeader.SectionAlignment;
return EFI_SUCCESS;
}

View File

@ -154,7 +154,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
_SECTION_MAX,
};
const CHAR8* const sections[] = {
static const CHAR8* const sections[_SECTION_MAX + 1] = {
[SECTION_CMDLINE] = (const CHAR8*) ".cmdline",
[SECTION_LINUX] = (const CHAR8*) ".linux",
[SECTION_INITRD] = (const CHAR8*) ".initrd",
@ -172,6 +172,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
UINTN addrs[_SECTION_MAX] = {};
UINTN szs[_SECTION_MAX] = {};
CHAR8 *cmdline = NULL;
_cleanup_freepool_ CHAR8 *cmdline_owned = NULL;
EFI_STATUS err;
InitializeLib(image, sys_table);
@ -187,8 +188,11 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
err = pe_memory_locate_sections(loaded_image->ImageBase, (const CHAR8**) sections, addrs, szs);
if (EFI_ERROR(err))
if (EFI_ERROR(err) || szs[SECTION_LINUX] == 0) {
if (!EFI_ERROR(err))
err = EFI_NOT_FOUND;
return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err);
}
/* Show splash screen as early as possible */
graphics_splash((const UINT8*) loaded_image->ImageBase + addrs[SECTION_SPLASH], szs[SECTION_SPLASH], NULL);
@ -201,18 +205,13 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */
if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 &&
*(CHAR16 *) loaded_image->LoadOptions > 0x1F) {
CHAR16 *options;
CHAR8 *line;
options = (CHAR16 *)loaded_image->LoadOptions;
cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
line = AllocatePool(cmdline_len);
if (!line)
cmdline = cmdline_owned = AllocatePool(cmdline_len);
if (!cmdline)
return log_oom();
for (UINTN i = 0; i < cmdline_len; i++)
line[i] = options[i];
cmdline = line;
cmdline[i] = ((CHAR16 *) loaded_image->LoadOptions)[i];
/* Let's measure the passed kernel command line into the TPM. Note that this possibly
* duplicates what we already did in the boot menu, if that was already used. However, since

View File

@ -493,14 +493,21 @@ void log_error_stall(const CHAR16 *fmt, ...) {
assert(fmt);
INT32 attr = ST->ConOut->Mode->Attribute;
ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK);
Print(L"\n");
if (ST->ConOut->Mode->CursorColumn > 0)
Print(L"\n");
va_start(args, fmt);
VPrint(fmt, args);
va_end(args);
Print(L"\n");
ST->ConOut->SetAttribute(ST->ConOut, attr);
/* Give the user a chance to see the message. */
BS->Stall(3 * 1000 * 1000);
}
@ -734,7 +741,7 @@ EFI_STATUS open_directory(
err = get_file_info_harder(dir, &file_info, NULL);
if (EFI_ERROR(err))
return err;
if (!(file_info->Attribute & EFI_FILE_DIRECTORY))
if (!FLAGS_SET(file_info->Attribute, EFI_FILE_DIRECTORY))
return EFI_LOAD_ERROR;
*ret = TAKE_PTR(dir);

View File

@ -306,3 +306,10 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
(l <= SIZE_MAX - (ali - 1)), /* overflow? */ \
((l) + (ali) - 1) & ~((ali) - 1), \
VOID_0)
#define UPDATE_FLAG(orig, flag, b) \
((b) ? ((orig) | (flag)) : ((orig) & ~(flag)))
#define SET_FLAG(v, flag, b) \
(v) = UPDATE_FLAG(v, flag, b)
#define FLAGS_SET(v, flags) \
((~(v) & (flags)) == 0)