systemd: fix systemd-boot keyboard handling lockup

In v248 compiler weirdness and refactoring lead to the bootloader
erroring out handling keyboard input on some systems.
See https://github.com/systemd/systemd/issues/19191

This should be redundant in v249.6 when it officially gets tagged in
systemd-stable.

Closes https://github.com/NixOS/nixpkgs/issues/143847
main
Anund 3 years ago
parent 9a96e0ec8c
commit d216b21513
  1. 4
      pkgs/os-specific/linux/systemd/0001-Start-device-units-for-uninitialised-encrypted-devic.patch
  2. 4
      pkgs/os-specific/linux/systemd/0002-Don-t-try-to-unmount-nix-or-nix-store.patch
  3. 4
      pkgs/os-specific/linux/systemd/0003-Fix-NixOS-containers.patch
  4. 4
      pkgs/os-specific/linux/systemd/0004-Look-for-fsck-in-the-right-place.patch
  5. 4
      pkgs/os-specific/linux/systemd/0005-Add-some-NixOS-specific-unit-directories.patch
  6. 4
      pkgs/os-specific/linux/systemd/0006-Get-rid-of-a-useless-message-in-user-sessions.patch
  7. 4
      pkgs/os-specific/linux/systemd/0007-hostnamed-localed-timedated-disable-methods-that-cha.patch
  8. 4
      pkgs/os-specific/linux/systemd/0008-Fix-hwdb-paths.patch
  9. 4
      pkgs/os-specific/linux/systemd/0009-Change-usr-share-zoneinfo-to-etc-zoneinfo.patch
  10. 4
      pkgs/os-specific/linux/systemd/0010-localectl-use-etc-X11-xkb-for-list-x11.patch
  11. 4
      pkgs/os-specific/linux/systemd/0011-build-don-t-create-statedir-and-don-t-touch-prefixdi.patch
  12. 4
      pkgs/os-specific/linux/systemd/0012-inherit-systemd-environment-when-calling-generators.patch
  13. 4
      pkgs/os-specific/linux/systemd/0013-add-rootprefix-to-lookup-dir-paths.patch
  14. 4
      pkgs/os-specific/linux/systemd/0014-systemd-shutdown-execute-scripts-in-etc-systemd-syst.patch
  15. 4
      pkgs/os-specific/linux/systemd/0015-systemd-sleep-execute-scripts-in-etc-systemd-system-.patch
  16. 4
      pkgs/os-specific/linux/systemd/0016-kmod-static-nodes.service-Update-ConditionFileNotEmp.patch
  17. 4
      pkgs/os-specific/linux/systemd/0017-path-util.h-add-placeholder-for-DEFAULT_PATH_NORMAL.patch
  18. 4
      pkgs/os-specific/linux/systemd/0018-pkg-config-derive-prefix-from-prefix.patch
  19. 4
      pkgs/os-specific/linux/systemd/0019-core-handle-lookup-paths-being-symlinks.patch
  20. 401
      pkgs/os-specific/linux/systemd/0020-sd-boot-Unify-error-handling.patch
  21. 320
      pkgs/os-specific/linux/systemd/0021-sd-boot-Rework-console-input-handling.patch
  22. 8
      pkgs/os-specific/linux/systemd/default.nix

@ -1,7 +1,7 @@
From 06a8dbb65584b6f705fee8a486f32dab12f72082 Mon Sep 17 00:00:00 2001
From d4ea219a35a09fe02bc9e47e8530644cb4fc4146 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Tue, 8 Jan 2013 15:46:30 +0100
Subject: [PATCH 01/19] Start device units for uninitialised encrypted devices
Subject: [PATCH 01/21] Start device units for uninitialised encrypted devices
This is necessary because the NixOS service that initialises the
filesystem depends on the appearance of the device unit. Also, this

@ -1,7 +1,7 @@
From 2c98ff115f7027bebde14cf3e74f2c51b343874c Mon Sep 17 00:00:00 2001
From 67abd8f22f70d9348bc9d8e0e93dde4d325627ba Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Fri, 12 Apr 2013 13:16:57 +0200
Subject: [PATCH 02/19] Don't try to unmount /nix or /nix/store
Subject: [PATCH 02/21] Don't try to unmount /nix or /nix/store
They'll still be remounted read-only.

@ -1,7 +1,7 @@
From 16f441b6495ff4c4d1d0b71a7f1650505147173d Mon Sep 17 00:00:00 2001
From 37c9471f59bd57223014a4a645b5f96a71d78787 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Wed, 16 Apr 2014 10:59:28 +0200
Subject: [PATCH 03/19] Fix NixOS containers
Subject: [PATCH 03/21] Fix NixOS containers
In NixOS containers, the init script is bind-mounted into the
container, so checking early whether it exists will fail.

@ -1,7 +1,7 @@
From 261423bc039378115ad9223c2b6ede9c395847b2 Mon Sep 17 00:00:00 2001
From 987d6f94dac8e1a75615fd9ddcfb0eb1c2c4c349 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Thu, 1 May 2014 14:10:10 +0200
Subject: [PATCH 04/19] Look for fsck in the right place
Subject: [PATCH 04/21] Look for fsck in the right place
---
src/fsck/fsck.c | 2 +-

@ -1,7 +1,7 @@
From 18b45c20499747bcc66714ee87edf34d4f6e3dca Mon Sep 17 00:00:00 2001
From da4f855044b2babe052ce303cca1de736cf952cd Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Fri, 19 Dec 2014 14:46:17 +0100
Subject: [PATCH 05/19] Add some NixOS-specific unit directories
Subject: [PATCH 05/21] Add some NixOS-specific unit directories
Look in `/nix/var/nix/profiles/default/lib/systemd/{system,user}` for
units provided by packages installed into the default profile via

@ -1,7 +1,7 @@
From 8b8f4168828a12cac17c3e8803cacebf31608c68 Mon Sep 17 00:00:00 2001
From c06abdb631527f56a626b739340d1b275349612c Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Mon, 11 May 2015 15:39:38 +0200
Subject: [PATCH 06/19] Get rid of a useless message in user sessions
Subject: [PATCH 06/21] Get rid of a useless message in user sessions
Namely lots of variants of

@ -1,7 +1,7 @@
From e147e9defaf2bb5e8040566537661d90b4008daf Mon Sep 17 00:00:00 2001
From 207c69466cdd164c42ed1901deb06f57b12f4363 Mon Sep 17 00:00:00 2001
From: Gabriel Ebner <gebner@gebner.org>
Date: Sun, 6 Dec 2015 14:26:36 +0100
Subject: [PATCH 07/19] hostnamed, localed, timedated: disable methods that
Subject: [PATCH 07/21] hostnamed, localed, timedated: disable methods that
change system settings.
---

@ -1,7 +1,7 @@
From 992d0e6abb09aacceee2f8646c4bcdacf7277dc7 Mon Sep 17 00:00:00 2001
From 3ca3855259c3015615983587063fa159cfa7e93c Mon Sep 17 00:00:00 2001
From: Nikolay Amiantov <ab@fmap.me>
Date: Thu, 7 Jul 2016 02:47:13 +0300
Subject: [PATCH 08/19] Fix hwdb paths
Subject: [PATCH 08/21] Fix hwdb paths
Patch by vcunat.
---

@ -1,7 +1,7 @@
From 462bc01b3a38468fd617066a3d7f27b1acca9e0a Mon Sep 17 00:00:00 2001
From 717226ad0dc37ceb6c667c1f56396848978b6e83 Mon Sep 17 00:00:00 2001
From: Nikolay Amiantov <ab@fmap.me>
Date: Tue, 11 Oct 2016 13:12:08 +0300
Subject: [PATCH 09/19] Change /usr/share/zoneinfo to /etc/zoneinfo
Subject: [PATCH 09/21] Change /usr/share/zoneinfo to /etc/zoneinfo
NixOS uses this path.
---

@ -1,7 +1,7 @@
From fbb302d00c63dc17a210f83648f24a1da983b2c0 Mon Sep 17 00:00:00 2001
From 75d12cf65073458f091899d673c613dfc43f60c0 Mon Sep 17 00:00:00 2001
From: Imuli <i@imu.li>
Date: Wed, 19 Oct 2016 08:46:47 -0400
Subject: [PATCH 10/19] localectl: use /etc/X11/xkb for list-x11-*
Subject: [PATCH 10/21] localectl: use /etc/X11/xkb for list-x11-*
NixOS has an option to link the xkb data files to /etc/X11, but not to
/usr/share/X11.

@ -1,7 +1,7 @@
From b850dae349de8ac6906d4f920a21ef275cecb2de Mon Sep 17 00:00:00 2001
From bce75eb4cdeb0b86df6b0a577e886c49a88303f6 Mon Sep 17 00:00:00 2001
From: Franz Pletz <fpletz@fnordicwalking.de>
Date: Sun, 11 Feb 2018 04:37:44 +0100
Subject: [PATCH 11/19] build: don't create statedir and don't touch prefixdir
Subject: [PATCH 11/21] build: don't create statedir and don't touch prefixdir
---
meson.build | 3 ---

@ -1,7 +1,7 @@
From beefb6d381286769cc47c71c82b831a37a405d90 Mon Sep 17 00:00:00 2001
From ecdf0c5d9f88f526521f093cc9ee85f43efab4b7 Mon Sep 17 00:00:00 2001
From: Andreas Rammhold <andreas@rammhold.de>
Date: Fri, 2 Nov 2018 21:15:42 +0100
Subject: [PATCH 12/19] inherit systemd environment when calling generators.
Subject: [PATCH 12/21] inherit systemd environment when calling generators.
Systemd generators need access to the environment configured in
stage-2-init.sh since it schedules fsck and mkfs executions based on

@ -1,7 +1,7 @@
From 146b79d55cc4fdfdb5fd4978e68b21f5c1df1679 Mon Sep 17 00:00:00 2001
From 39969a1b01d6c223a21c770093209b7f4047aaa4 Mon Sep 17 00:00:00 2001
From: Andreas Rammhold <andreas@rammhold.de>
Date: Thu, 9 May 2019 11:15:22 +0200
Subject: [PATCH 13/19] add rootprefix to lookup dir paths
Subject: [PATCH 13/21] add rootprefix to lookup dir paths
systemd does not longer use the UDEVLIBEXEC directory as root for
discovery default udev rules. By adding `$out/lib` to the lookup paths

@ -1,7 +1,7 @@
From 8edd810e74e2308f34eba6e8072e559e69307830 Mon Sep 17 00:00:00 2001
From e7c960789b0ca97b24a66e9eeaa56ea645d9c66b Mon Sep 17 00:00:00 2001
From: Nikolay Amiantov <ab@fmap.me>
Date: Thu, 25 Jul 2019 20:45:55 +0300
Subject: [PATCH 14/19] systemd-shutdown: execute scripts in
Subject: [PATCH 14/21] systemd-shutdown: execute scripts in
/etc/systemd/system-shutdown
This is needed for NixOS to use such scripts as systemd directory is immutable.

@ -1,7 +1,7 @@
From 9ed24199dd3ce91d3f7fbfbdf823312c124aba56 Mon Sep 17 00:00:00 2001
From 6124720aa2b9dbc07f2fb898f0db150a44a86041 Mon Sep 17 00:00:00 2001
From: Nikolay Amiantov <ab@fmap.me>
Date: Thu, 25 Jul 2019 20:46:58 +0300
Subject: [PATCH 15/19] systemd-sleep: execute scripts in
Subject: [PATCH 15/21] systemd-sleep: execute scripts in
/etc/systemd/system-sleep
This is needed for NixOS to use such scripts as systemd directory is immutable.

@ -1,7 +1,7 @@
From 6db7ad4d5526a82e4ed9b135daf1054a8b71e1c7 Mon Sep 17 00:00:00 2001
From bee1d855d4fb7f2d6f6b9beb1dfd14b1dea31887 Mon Sep 17 00:00:00 2001
From: Florian Klink <flokli@flokli.de>
Date: Sat, 7 Mar 2020 22:40:27 +0100
Subject: [PATCH 16/19] kmod-static-nodes.service: Update ConditionFileNotEmpty
Subject: [PATCH 16/21] kmod-static-nodes.service: Update ConditionFileNotEmpty
On NixOS, kernel modules of the currently booted systems are located at
/run/booted-system/kernel-modules/lib/modules/%v/, not /lib/modules/%v/.

@ -1,7 +1,7 @@
From 160d32c336c96744bbfb618eae4c12cb90138644 Mon Sep 17 00:00:00 2001
From 62198599bbc559eeb8e2a3caebce7b9135085270 Mon Sep 17 00:00:00 2001
From: Florian Klink <flokli@flokli.de>
Date: Sun, 8 Mar 2020 01:05:54 +0100
Subject: [PATCH 17/19] path-util.h: add placeholder for DEFAULT_PATH_NORMAL
Subject: [PATCH 17/21] path-util.h: add placeholder for DEFAULT_PATH_NORMAL
This will be the $PATH used to lookup ExecStart= etc. options, which
systemd itself uses extensively.

@ -1,7 +1,7 @@
From 777d61550f95b1dcf253e1d2132f9db7010a18f3 Mon Sep 17 00:00:00 2001
From 7654964344ba083529cb232ab229db7c0888f782 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
Date: Sun, 6 Dec 2020 08:34:19 +0100
Subject: [PATCH 18/19] pkg-config: derive prefix from --prefix
Subject: [PATCH 18/21] pkg-config: derive prefix from --prefix
Point prefix to the one configured, instead of `/usr` `systemd` has limited
support for making the pkgconfig prefix overridable, and interpolates those

@ -1,7 +1,7 @@
From 273e706ff561f2164b84c714148346ac92dd8846 Mon Sep 17 00:00:00 2001
From 4e9b4aa87d299be08cffc77a86d6f473a7a4109a Mon Sep 17 00:00:00 2001
From: Andreas Rammhold <andreas@rammhold.de>
Date: Wed, 18 Aug 2021 19:10:08 +0200
Subject: [PATCH 19/19] core: handle lookup paths being symlinks
Subject: [PATCH 19/21] core: handle lookup paths being symlinks
With a recent change paths leaving the statically known lookup paths
would be treated differently then those that remained within those. That

@ -0,0 +1,401 @@
From 3cf1b5fb6d1dc342e836cf0990df3170d2e9db49 Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Wed, 11 Aug 2021 14:59:46 +0200
Subject: [PATCH 20/21] sd-boot: Unify error handling
log_error_stall() and log_error_status_stall() will ensure the user has
a chance to catch an error message by stalling and also forcing a
lightred/black color on it. Also, convert several Print() calls to it
since they are actually error messages.
(cherry picked from commit 8aba0eec499b762657f528988c2f093ac490620d)
---
src/boot/efi/boot.c | 62 ++++++++++----------------------
src/boot/efi/random-seed.c | 73 +++++++++++++-------------------------
src/boot/efi/stub.c | 24 ++++---------
src/boot/efi/util.c | 17 +++++++--
src/boot/efi/util.h | 9 +++++
5 files changed, 75 insertions(+), 110 deletions(-)
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 13940a6df7..54d704f0d1 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -527,7 +527,7 @@ static BOOLEAN menu_run(
err = console_set_mode(&config->console_mode, config->console_mode_change);
if (EFI_ERROR(err)) {
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
- Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
+ log_error_stall(L"Error switching console mode to %lu: %r", (UINT64)config->console_mode, err);
}
} else
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@@ -1221,8 +1221,7 @@ static VOID config_entry_bump_counters(
break;
if (r != EFI_BUFFER_TOO_SMALL || file_info_size * 2 < file_info_size) {
- Print(L"\nFailed to get file info for '%s': %r\n", old_path, r);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ log_error_stall(L"Failed to get file info for '%s': %r", old_path, r);
return;
}
@@ -1234,8 +1233,7 @@ static VOID config_entry_bump_counters(
StrCpy(file_info->FileName, entry->next_name);
r = uefi_call_wrapper(handle->SetInfo, 4, handle, &EfiFileInfoGuid, file_info_size, file_info);
if (EFI_ERROR(r)) {
- Print(L"\nFailed to rename '%s' to '%s', ignoring: %r\n", old_path, entry->next_name, r);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ log_error_stall(L"Failed to rename '%s' to '%s', ignoring: %r", old_path, entry->next_name, r);
return;
}
@@ -2165,18 +2163,12 @@ static EFI_STATUS image_start(
EFI_STATUS err;
path = FileDevicePath(entry->device, entry->loader);
- if (!path) {
- Print(L"Error getting device path.");
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return EFI_INVALID_PARAMETER;
- }
+ if (!path)
+ return log_error_status_stall(EFI_INVALID_PARAMETER, L"Error getting device path.");
err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image);
- if (EFI_ERROR(err)) {
- Print(L"Error loading %s: %r", entry->loader, err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error loading %s: %r", entry->loader, err);
if (config->options_edit)
options = config->options_edit;
@@ -2190,8 +2182,7 @@ static EFI_STATUS image_start(
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) {
- Print(L"Error getting LoadedImageProtocol handle: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ log_error_stall(L"Error getting LoadedImageProtocol handle: %r", err);
goto out_unload;
}
loaded_image->LoadOptions = options;
@@ -2202,10 +2193,8 @@ static EFI_STATUS image_start(
err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
- if (EFI_ERROR(err)) {
- Print(L"Unable to add image options measurement: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
- }
+ if (EFI_ERROR(err))
+ log_error_stall(L"Unable to add image options measurement: %r", err);
#endif
}
@@ -2231,9 +2220,7 @@ static EFI_STATUS reboot_into_firmware(VOID) {
return err;
err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL);
- Print(L"Error calling ResetSystem: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
+ return log_error_status_stall(err, L"Error calling ResetSystem: %r", err);
}
static VOID config_free(Config *config) {
@@ -2305,30 +2292,21 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR(err)) {
- Print(L"Error getting a LoadedImageProtocol handle: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
/* export the device path this image is started from */
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
root_dir = LibOpenRoot(loaded_image->DeviceHandle);
- if (!root_dir) {
- Print(L"Unable to open root directory.");
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return EFI_LOAD_ERROR;
- }
+ if (!root_dir)
+ return log_error_status_stall(EFI_LOAD_ERROR, L"Unable to open root directory.", EFI_LOAD_ERROR);
if (secure_boot_enabled() && shim_loaded()) {
err = security_policy_install();
- if (EFI_ERROR(err)) {
- Print(L"Error installing security policy: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error installing security policy: %r", err);
}
/* the filesystem path to this image, to prevent adding ourselves to the menu */
@@ -2367,8 +2345,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
}
if (config.entry_count == 0) {
- Print(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ log_error_stall(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
goto out;
}
@@ -2440,8 +2417,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = image_start(image, &config, entry);
if (EFI_ERROR(err)) {
graphics_mode(FALSE);
- Print(L"\nFailed to execute %s (%s): %r\n", entry->title, entry->loader, err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ log_error_stall(L"Failed to execute %s (%s): %r", entry->title, entry->loader, err);
goto out;
}
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
index 3e179851b0..939daf3e41 100644
--- a/src/boot/efi/random-seed.c
+++ b/src/boot/efi/random-seed.c
@@ -35,10 +35,8 @@ static EFI_STATUS acquire_rng(UINTN size, VOID **ret) {
return log_oom();
err = uefi_call_wrapper(rng->GetRNG, 3, rng, NULL, size, data);
- if (EFI_ERROR(err)) {
- Print(L"Failed to acquire RNG data: %r\n", err);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Failed to acquire RNG data: %r", err);
*ret = TAKE_PTR(data);
return EFI_SUCCESS;
@@ -149,14 +147,12 @@ static EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND)
- Print(L"Failed to read LoaderSystemToken EFI variable: %r", err);
+ log_error_stall(L"Failed to read LoaderSystemToken EFI variable: %r", err);
return err;
}
- if (size <= 0) {
- Print(L"System token too short, ignoring.");
- return EFI_NOT_FOUND;
- }
+ if (size <= 0)
+ return log_error_status_stall(EFI_NOT_FOUND, L"System token too short, ignoring.");
*ret = TAKE_PTR(data);
*ret_size = size;
@@ -209,8 +205,7 @@ static VOID validate_sha256(void) {
sha256_finish_ctx(&hash, result);
if (CompareMem(result, array[i].hash, HASH_VALUE_SIZE) != 0) {
- Print(L"SHA256 failed validation.\n");
- uefi_call_wrapper(BS->Stall, 1, 120 * 1000 * 1000);
+ log_error_stall(L"SHA256 failed validation.");
return;
}
}
@@ -246,7 +241,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, (CHAR16*) L"\\loader\\random-seed", EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL);
if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED)
- Print(L"Failed to open random seed file: %r\n", err);
+ log_error_stall(L"Failed to open random seed file: %r", err);
return err;
}
@@ -255,15 +250,11 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
return log_oom();
size = info->FileSize;
- if (size < RANDOM_MAX_SIZE_MIN) {
- Print(L"Random seed file is too short?\n");
- return EFI_INVALID_PARAMETER;
- }
+ if (size < RANDOM_MAX_SIZE_MIN)
+ return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too short.");
- if (size > RANDOM_MAX_SIZE_MAX) {
- Print(L"Random seed file is too large?\n");
- return EFI_INVALID_PARAMETER;
- }
+ if (size > RANDOM_MAX_SIZE_MAX)
+ return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large.");
seed = AllocatePool(size);
if (!seed)
@@ -271,20 +262,14 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
rsize = size;
err = uefi_call_wrapper(handle->Read, 3, handle, &rsize, seed);
- if (EFI_ERROR(err)) {
- Print(L"Failed to read random seed file: %r\n", err);
- return err;
- }
- if (rsize != size) {
- Print(L"Short read on random seed file\n");
- return EFI_PROTOCOL_ERROR;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Failed to read random seed file: %r", err);
+ if (rsize != size)
+ return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short read on random seed file.");
err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0);
- if (EFI_ERROR(err)) {
- Print(L"Failed to seek to beginning of random seed file: %r\n", err);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
/* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good
* idea to use it because it helps us for cases where users mistakenly include a random seed in
@@ -299,27 +284,19 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
/* Update the random seed on disk before we use it */
wsize = size;
err = uefi_call_wrapper(handle->Write, 3, handle, &wsize, new_seed);
- if (EFI_ERROR(err)) {
- Print(L"Failed to write random seed file: %r\n", err);
- return err;
- }
- if (wsize != size) {
- Print(L"Short write on random seed file\n");
- return EFI_PROTOCOL_ERROR;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Failed to write random seed file: %r", err);
+ if (wsize != size)
+ return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file.");
err = uefi_call_wrapper(handle->Flush, 1, handle);
- if (EFI_ERROR(err)) {
- Print(L"Failed to flush random seed file: %r\n");
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
/* We are good to go */
err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0);
- if (EFI_ERROR(err)) {
- Print(L"Failed to write random seed to EFI variable: %r\n", err);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Failed to write random seed to EFI variable: %r", err);
return EFI_SUCCESS;
}
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index 082fe91c9e..82da1d3ec4 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -36,18 +36,12 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR(err)) {
- Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
- if (EFI_ERROR(err)) {
- Print(L"Unable to locate embedded .linux section: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err);
if (szs[0] > 0)
cmdline = (CHAR8 *)(loaded_image->ImageBase) + addrs[0];
@@ -72,10 +66,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
- if (EFI_ERROR(err)) {
- Print(L"Unable to add image options measurement: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
- }
+ if (EFI_ERROR(err))
+ log_error_stall(L"Unable to add image options measurement: %r", err);
#endif
}
@@ -126,7 +118,5 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
(UINTN)loaded_image->ImageBase + addrs[2], szs[2]);
graphics_mode(FALSE);
- Print(L"Execution of embedded linux image failed: %r\n", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
+ return log_error_status_stall(err, L"Execution of embedded linux image failed: %r", err);
}
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
index 6f4e5933d3..aee076060b 100644
--- a/src/boot/efi/util.c
+++ b/src/boot/efi/util.c
@@ -411,8 +411,21 @@ EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN s
return err;
}
+VOID log_error_stall(const CHAR16 *fmt, ...) {
+ va_list args;
+
+ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK);
+
+ Print(L"\n");
+ va_start(args, fmt);
+ VPrint(fmt, args);
+ va_end(args);
+ Print(L"\n");
+
+ uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+}
+
EFI_STATUS log_oom(void) {
- Print(L"Out of memory.");
- (void) uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ log_error_stall(L"Out of memory.");
return EFI_OUT_OF_RESOURCES;
}
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
index 1a42b01033..d3bf848a95 100644
--- a/src/boot/efi/util.h
+++ b/src/boot/efi/util.h
@@ -74,4 +74,13 @@ static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
#define UINT64_MAX ((UINT64) -1)
#endif
+VOID log_error_stall(const CHAR16 *fmt, ...);
EFI_STATUS log_oom(void);
+
+/* This works just like log_error_errno() from userspace, but requires you
+ * to provide err a second time if you want to use %r in the message! */
+#define log_error_status_stall(err, fmt, ...) \
+ ({ \
+ log_error_stall(fmt, ##__VA_ARGS__); \
+ err; \
+ })
--
2.33.0

@ -0,0 +1,320 @@
From 2d9fcfcfa38667ada306e095599944f941576e53 Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Wed, 11 Aug 2021 14:59:46 +0200
Subject: [PATCH 21/21] sd-boot: Rework console input handling
Fixes: #15847
Probably fixes: #19191
(cherry picked from commit e98d271e57f3d0356e444b6ea2d48836ee2769b0)
---
src/boot/efi/boot.c | 55 +++++++---------------
src/boot/efi/console.c | 102 +++++++++++++++++++++++++++++------------
src/boot/efi/console.h | 2 +-
3 files changed, 91 insertions(+), 68 deletions(-)
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 54d704f0d1..b4f3b9605a 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -134,7 +134,7 @@ static BOOLEAN line_edit(
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print);
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
- err = console_key_read(&key, TRUE);
+ err = console_key_read(&key, 0);
if (EFI_ERROR(err))
continue;
@@ -387,7 +387,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"OsIndicationsSupported: %d\n", indvar);
Print(L"\n--- press key ---\n\n");
- console_key_read(&key, TRUE);
+ console_key_read(&key, 0);
Print(L"timeout: %u\n", config->timeout_sec);
if (config->timeout_sec_efivar >= 0)
@@ -432,7 +432,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"LoaderEntryDefault: %s\n", defaultstr);
Print(L"\n--- press key ---\n\n");
- console_key_read(&key, TRUE);
+ console_key_read(&key, 0);
for (UINTN i = 0; i < config->entry_count; i++) {
ConfigEntry *entry;
@@ -482,7 +482,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
entry->path, entry->next_name);
Print(L"\n--- press key ---\n\n");
- console_key_read(&key, TRUE);
+ console_key_read(&key, 0);
}
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@@ -509,11 +509,10 @@ static BOOLEAN menu_run(
UINTN y_max;
CHAR16 *status;
CHAR16 *clearline;
- INTN timeout_remain;
+ UINTN timeout_remain = config->timeout_sec;
INT16 idx;
BOOLEAN exit = FALSE;
BOOLEAN run = TRUE;
- BOOLEAN wait = FALSE;
graphics_mode(FALSE);
uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
@@ -538,12 +537,6 @@ static BOOLEAN menu_run(
y_max = 25;
}
- /* we check 10 times per second for a keystroke */
- if (config->timeout_sec > 0)
- timeout_remain = config->timeout_sec * 10;
- else
- timeout_remain = -1;
-
idx_highlight = config->idx_default;
idx_highlight_prev = 0;
@@ -643,7 +636,7 @@ static BOOLEAN menu_run(
if (timeout_remain > 0) {
FreePool(status);
- status = PoolPrint(L"Boot in %d sec.", (timeout_remain + 5) / 10);
+ status = PoolPrint(L"Boot in %d s.", timeout_remain);
}
/* print status at last line of screen */
@@ -664,27 +657,18 @@ static BOOLEAN menu_run(
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len);
}
- err = console_key_read(&key, wait);
- if (EFI_ERROR(err)) {
- /* timeout reached */
+ err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : 0);
+ if (err == EFI_TIMEOUT) {
+ timeout_remain--;
if (timeout_remain == 0) {
exit = TRUE;
break;
}
- /* sleep and update status */
- if (timeout_remain > 0) {
- uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
- timeout_remain--;
- continue;
- }
-
- /* timeout disabled, wait for next key */
- wait = TRUE;
+ /* update status */
continue;
- }
-
- timeout_remain = -1;
+ } else
+ timeout_remain = 0;
/* clear status after keystroke */
if (status) {
@@ -787,7 +771,7 @@ static BOOLEAN menu_run(
config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0)
- status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
+ status = PoolPrint(L"Menu timeout set to %d s.", config->timeout_sec_efivar);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
} else if (config->timeout_sec_efivar <= 0){
@@ -795,7 +779,7 @@ static BOOLEAN menu_run(
efivar_set(
LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_config > 0)
- status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
+ status = PoolPrint(L"Menu timeout of %d s is defined by configuration file.",
config->timeout_sec_config);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
@@ -813,7 +797,7 @@ static BOOLEAN menu_run(
config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0)
- status = PoolPrint(L"Menu timeout set to %d sec.",
+ status = PoolPrint(L"Menu timeout set to %d s.",
config->timeout_sec_efivar);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
@@ -2369,13 +2353,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
else {
UINT64 key;
- err = console_key_read(&key, FALSE);
-
- if (err == EFI_NOT_READY) {
- uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
- err = console_key_read(&key, FALSE);
- }
-
+ /* Block up to 100ms to give firmware time to get input working. */
+ err = console_key_read(&key, 100 * 1000);
if (!EFI_ERROR(err)) {
INT16 idx;
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
index 83619d2147..369c549daf 100644
--- a/src/boot/efi/console.c
+++ b/src/boot/efi/console.c
@@ -11,61 +11,105 @@
#define EFI_SIMPLE_TEXT_INPUT_EX_GUID &(EFI_GUID) EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
-EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
+static inline void EventClosep(EFI_EVENT *event) {
+ if (!*event)
+ return;
+
+ uefi_call_wrapper(BS->CloseEvent, 1, *event);
+}
+
+/*
+ * Reading input from the console sounds like an easy task to do, but thanks to broken
+ * firmware it is actually a nightmare.
+ *
+ * There is a ConIn and TextInputEx API for this. Ideally we want to use TextInputEx,
+ * because that gives us Ctrl/Alt/Shift key state information. Unfortunately, it is not
+ * always available and sometimes just non-functional.
+ *
+ * On the other hand we have ConIn, where some firmware likes to just freeze on us
+ * if we call ReadKeyStroke on it.
+ *
+ * Therefore, we use WaitForEvent on both ConIn and TextInputEx (if available) along
+ * with a timer event. The timer ensures there is no need to call into functions
+ * that might freeze on us, while still allowing us to show a timeout counter.
+ */
+EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked;
UINTN index;
EFI_INPUT_KEY k;
EFI_STATUS err;
+ _cleanup_(EventClosep) EFI_EVENT timer = NULL;
+ EFI_EVENT events[3] = { ST->ConIn->WaitForKey };
+ UINTN n_events = 1;
if (!checked) {
err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx);
- if (EFI_ERROR(err))
+ if (EFI_ERROR(err) ||
+ uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx) == EFI_INVALID_PARAMETER)
+ /* If WaitForKeyEx fails here, the firmware pretends it talks this
+ * protocol, but it really doesn't. */
TextInputEx = NULL;
+ else
+ events[n_events++] = TextInputEx->WaitForKeyEx;
checked = TRUE;
}
- /* wait until key is pressed */
- if (wait)
- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
+ if (timeout_usec > 0) {
+ err = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &timer);
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error creating timer event: %r", err);
+
+ /* SetTimer expects 100ns units for some reason. */
+ err = uefi_call_wrapper(BS->SetTimer, 3, timer, TimerRelative, timeout_usec * 10);
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error arming timer event: %r", err);
- if (TextInputEx) {
+ events[n_events++] = timer;
+ }
+
+ err = uefi_call_wrapper(BS->WaitForEvent, 3, n_events, events, &index);
+ if (EFI_ERROR(err))
+ return log_error_status_stall(err, L"Error waiting for events: %r", err);
+
+ if (timeout_usec > 0 && timer == events[index])
+ return EFI_TIMEOUT;
+
+ /* TextInputEx might be ready too even if ConIn got to signal first. */
+ if (TextInputEx && !EFI_ERROR(uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx))) {
EFI_KEY_DATA keydata;
UINT64 keypress;
+ UINT32 shift = 0;
err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
- if (!EFI_ERROR(err)) {
- UINT32 shift = 0;
-
- /* do not distinguish between left and right keys */
- if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
- if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
- shift |= EFI_CONTROL_PRESSED;
- if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
- shift |= EFI_ALT_PRESSED;
- };
-
- /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
- keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
- if (keypress > 0) {
- *key = keypress;
- return 0;
- }
+ if (EFI_ERROR(err))
+ return err;
+
+ /* do not distinguish between left and right keys */
+ if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
+ if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
+ shift |= EFI_CONTROL_PRESSED;
+ if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
+ shift |= EFI_ALT_PRESSED;
+ };
+
+ /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
+ keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
+ if (keypress > 0) {
+ *key = keypress;
+ return EFI_SUCCESS;
}
+
+ return EFI_NOT_READY;
}
- /* fallback for firmware which does not support SimpleTextInputExProtocol
- *
- * This is also called in case ReadKeyStrokeEx did not return a key, because
- * some broken firmwares offer SimpleTextInputExProtocol, but never actually
- * handle any key. */
err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
if (EFI_ERROR(err))
return err;
*key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
- return 0;
+ return EFI_SUCCESS;
}
static EFI_STATUS change_mode(UINTN mode) {
diff --git a/src/boot/efi/console.h b/src/boot/efi/console.h
index 2c69af552a..23848a9c58 100644
--- a/src/boot/efi/console.h
+++ b/src/boot/efi/console.h
@@ -16,5 +16,5 @@ enum console_mode_change_type {
CONSOLE_MODE_MAX,
};
-EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait);
+EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec);
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how);
--
2.33.0

@ -164,6 +164,14 @@ stdenv.mkDerivation {
# all our root unit dirs if they are symlinks. This does exactly what we
# need (AFAICT).
./0019-core-handle-lookup-paths-being-symlinks.patch
# In v248 compiler weirdness and refactoring lead to the bootloader
# erroring out handling keyboard input on some systems. See
# https://github.com/systemd/systemd/issues/19191
# This should be redundant in v249.6 when it offically gets tagged in
# systemd-stable
./0020-sd-boot-Unify-error-handling.patch
./0021-sd-boot-Rework-console-input-handling.patch
] ++ lib.optional stdenv.hostPlatform.isMusl (let
oe-core = fetchzip {
url = "https://git.openembedded.org/openembedded-core/snapshot/openembedded-core-14c6e5a4b72d0e4665279158a0740dd1dc21f72f.tar.bz2";

Loading…
Cancel
Save