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

Enable booting of Slaunch-enabled EFI binaries via chainloader command #28

Open
wants to merge 81 commits into
base: tb-dev
Choose a base branch
from

Conversation

SergiiDmytruk
Copy link
Member

Relevant changes are in the top 2 commits, the rest are more fixes noticed in the process (to be squashed later).

…I boot

GRUB can either the linux legacy boot command but the default is to use the EFI
linux boot command on EFI capable systems. This debug parameter allows forcing
the use of legacy linux boot.

NOTE: This is not part of the final patch set, just for debugging.

Signed-off-by: Ross Philipson <[email protected]>
grub-core/loader/slaunch/x86_efi_linux.c Outdated Show resolved Hide resolved
Comment on lines +260 to +328
slparams->boot_params = &boot_params;
slparams->boot_params_base = (grub_addr_t)&boot_params;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why we have two fields which seemingly hold the same data. Is there any difference between them?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boot_params holds virtual and boot_params_base physical address. From i386/linux.c:

    real_mode_mem = get_virtual_current_address (ch);

    if (grub_slaunch_platform_type () != SLP_NONE)
      {
        slparams.boot_params = real_mode_mem;
        slparams.boot_params_base = get_physical_target_address (ch);
      }

Why the suffix is _base and not _pa or something like that is not known to me :) Secure Launch Spec also uses "base" at least once in the same sense.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Well It would be good to have boot_params_va and boot_params_pa, because right know I cannot distinguish which one is which. I will start some discussion on Matrix. RIght now closing the thread, as it should not be blocking.

Copy link

@miczyg1 miczyg1 Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh wait... These fields look like something GRUB-specific:

struct grub_slaunch_params
{
  grub_uint32_t boot_type;
  grub_uint32_t platform_type;
  struct linux_kernel_params *boot_params;
  grub_uint64_t boot_params_base;

I thought it is defined in the spec... I guess it would be better to have:

struct grub_slaunch_params
{
  grub_uint32_t boot_type;
  grub_uint32_t platform_type;
  grub_uint64_t boot_params_va;
  grub_uint64_t boot_params_pa;

For less confusion. As the slaunch is not Linux-specific (will need casts everywhere to linux_kernel_params *). @rossphilipson WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I mentioned the spec only because the reasoning for the suffix should be the same in both cases.

If changing a couple of the fields, then the rest should be changed too:

  • efi_memmap_mem -> efi_memmap_va?
  • slr_table_base -> slr_table_base
  • slr_table_mem -> slr_table_va?
  • mle_start -> mle_pa
  • mle_ptab_target -> mle_ptab_pa
  • mle_ptab_mem -> mle_ptab_va?
  • ap_wake_block -> ap_wake_block_pa
  • dce_base -> dce_pa
  • tpm_evt_log_base -> tpm_evt_log_pa

Types are also inconsistent. Addresses should probably all be grub_addr_t.

Which is why I didn't do it. Lots of renames across lots of commits and review might result in yet other names. _target, _base, _mem are also used as parameters and local variables.

Copy link
Member

@krystian-hebel krystian-hebel Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addresses should probably all be grub_addr_t.

Not really. First of all, GRUB uses this for physical addresses only (not sure if that is what you meant by "all"), virtual addresses are either void * or pointer to proper type. This type is also defined differently between 64b and 32b GRUB. While it may be enough to be used internally by GRUB (it won't allocate above 4G in 32b anyway), fields in SLRT are defined to always be 64 bits.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant physical addresses. Consistently using grub_uint64_t for them is a good option too. Currently, mle_start and ap_wake_block are of type grub_uint32_t.

@SergiiDmytruk SergiiDmytruk force-pushed the xen-uefi branch 2 times, most recently from 8b8a8b8 to 35c725e Compare January 3, 2025 18:26
@@ -98,7 +98,7 @@ grub_skl_set_module (const void *skl_base, grub_uint32_t size)
if (module->skl_info_offset > module->length - sizeof (info->uuid))
{
grub_dprintf ("slaunch",
"Possible SKL module doesn't measure info: %u > %u\n",
"Possible SKL module doesn't measure info: %u > %lu\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually breaks the build for i386-pc:

In file included from ../../include/grub/disk.h:31,
                 from ../../include/grub/file.h:26,
                 from ../../include/grub/loader.h:23,
                 from ../../grub-core/loader/slaunch/skl.c:35:
../../grub-core/loader/slaunch/skl.c: In function ‘grub_skl_set_module’:
../../grub-core/loader/slaunch/skl.c:101:21: error: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 6 has type ‘unsigned int’ [-Werror=format=]
  101 |                     "Possible SKL module doesn't measure info: %u > %lu\n",
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  102 |                     module->skl_info_offset,
  103 |                     module->length - sizeof (info->uuid));
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                    |
      |                                    unsigned int
../../include/grub/misc.h:38:88: note: in definition of macro ‘grub_dprintf’
   38 | #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__)
      |                                                                                        ^~~~~~~~~~~
../../grub-core/loader/slaunch/skl.c:101:71: note: format string is defined here
  101 |                     "Possible SKL module doesn't measure info: %u > %lu\n",
      |                                                                     ~~^
      |                                                                       |
      |                                                                       long unsigned int
      |                                                                     %u

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miczyg1
Copy link

miczyg1 commented Jan 14, 2025

@SergiiDmytruk can we get packages built by CI here too?

@SergiiDmytruk
Copy link
Member Author

@SergiiDmytruk can we get packages built by CI here too?

I'm trying to make CI work at https://github.com/TrenchBoot/grub/commits/xen-efi-ci/.

@SergiiDmytruk SergiiDmytruk force-pushed the xen-uefi branch 2 times, most recently from 54debcb to 6965858 Compare January 15, 2025 14:29
This avoids the need to keep memory pointed to by mle_mem around.

Signed-off-by: Sergii Dmytruk <[email protected]>
@SergiiDmytruk SergiiDmytruk force-pushed the xen-uefi branch 3 times, most recently from 58fc5d3 to 1426946 Compare January 22, 2025 23:03
…alls

Size wasn't converted to pages.

Signed-off-by: Sergii Dmytruk <[email protected]>
It's a special value for slr_table_base of struct grub_slaunch_params
that indicates that the table should be stored near OS2MLE data (right after it).

Signed-off-by: Sergii Dmytruk <[email protected]>
@SergiiDmytruk SergiiDmytruk force-pushed the xen-uefi branch 3 times, most recently from 8cff0a3 to d2bcffb Compare January 30, 2025 22:53
Signed-off-by: Michał Żygowski <[email protected]>
Signed-off-by: Krystian Hebel <[email protected]>
Signed-off-by: Sergii Dmytruk <[email protected]>
vathpela and others added 29 commits February 4, 2025 21:07
This makes the stack executable on most of the grub utilities, which is
bad, and rpmdiff complains about it.

Signed-off-by: Peter Jones <[email protected]>
This adds "increment" and "decrement" commands, and uses them to maintain our
variables in 01_fallback_counter.  It also simplifies the counter logic, so
that there are no nested tests that conflict with each other.

Apparently, this *really* wasn't tested well enough.

Resolves: rhbz#1614637
Signed-off-by: Peter Jones <[email protected]>
[lorbus: add comments and revert logic changes in 01_fallback_counting]
Signed-off-by: Christian Glombek <[email protected]>
Currently if grub_strtoul(saved_entry_value, NULL, 0) does not return an
error, we assume the value it has produced is a correct index into our
menu entry list, and do not try to interpret the value as the "id" or
"title" .  In cases where "id" or "title" start with a numeral, this
makes them impossible to use as selection criteria.

This patch splits the search into three phases - matching id, matching
title, and only once those have been exhausted, trying to interpret the
ID as a numeral.  In that case, we also require that the entire string
is numeric, not merely a string with leading numeric characters.

Resolves: rhbz#1640979

Signed-off-by: Peter Jones <[email protected]>
[javierm: fix menu entry selection based on title]
Signed-off-by: Javier Martinez Canillas <[email protected]>
The --users option is used to restrict the access to specific menu entries
only to a set of users. But the option requires an argument to either be a
constant or a variable that has been set. So for example the following:

  menuentry "May be run by superusers or users in $users" --users $users {
  	    linux /vmlinuz
  }

Would fail if $users is not defined and grub would discard the menu entry.
Instead, allow the --users option to have an optional argument and ignore
the option if the argument was not set.

Related: rhbz#1652434

Signed-off-by: Javier Martinez Canillas <[email protected]>
This adds "efi-export-env VARIABLE" and "efi-load-env", which manipulate the
environment block stored in the EFI variable
GRUB_ENV-91376aff-cba6-42be-949d-06fde81128e8.

Signed-off-by: Peter Jones <[email protected]>
When a submenu is created, only the exported variables are copied to the
new menu context. But we want the variables to be global, so export lets
export all variables to the new created submenu.

Also, don't unset the default variable when a new submenu is created.

Signed-off-by: Javier Martinez Canillas <[email protected]>
Also rename fallback and menu auto hide script to be executed
before and after boot success reset script.
In menu auto hide script, rename last_boot_ok var to menu_hide_ok
We have stopped using pkexec for grub-set-bootflag, instead it is now
installed suid root, update the comment accordingly.

Signed-off-by: Hans de Goede <[email protected]>
Make the grubenv writing code in grub-set-bootflag more robust by
writing the modified grubenv to a tmpfile first and then renaming the
tmpfile over the old grubenv (following symlinks).

Signed-off-by: Hans de Goede <[email protected]>
The "grub.d: Split out boot success reset from menu auto hide script"
not only moved the code to clear boot_success and boot_indeterminate
but for some reason also mixed in some broken changes to the
boot_indeterminate handling.

The boot_indeterminate var is meant to suppress the boot menu after
a reboot from either a selinux-relabel or offline-updates. These
2 special boot scenarios do not set boot_success since there is no
successfull interaction with the user. Instead they increment
boot_indeterminate, and if it is 1 and only when it is 1, so the
first reboot after a "special" boot we suppress the menu.

To ensure that we do show the menu if we somehow get stuck in a
"special" boot loop where we do special-boots without them
incrementing boot_indeterminate, the code before the
"grub.d: Split out boot success reset from menu auto hide script"
commit would increment boot_indeterminate once when it is 1, so that
even if the "special" boot reboot-loop immediately we would show the
menu on the next boot.

That commit broke this however, because it not only moves the code,
it also changes it from only "incrementing" boot_indeterminate once to
always incrementing it, except when boot_success == 1 (and we reset it).

This broken behavior causes the following problem:

1. Boot a broken kernel, system hangs, power-cycle
2. boot_success now != 1, so we increment boot_indeterminate from 0
   (unset!) to 1. User either simply tries again, or makes some changes
   but the end-result still is a system hang, power-cycle
3. Now boot_indeterminate==1 so we do not show the menu even though the
   previous boot failed -> BAD

This commit fixes this by restoring the behavior of setting
boot_indeterminate to 2 when it was 1 before.

Fixes: "grub.d: Split out boot success reset from menu auto hide script"
Signed-off-by: Hans de Goede <[email protected]>
The python-unversioned-command package is not installed in the buildroot,
but the bootstrap script expects the python command to be present if one
is not defined. So building the package leads to the following error:

./autogen.sh: line 20: python: command not found

This is harmless since gnulib is included as a source anyways, because the
builders can't download. But still the issue should be fixed by forcing to
use python3 that's the default in Fedora now.

Signed-off-by: Javier Martinez Canillas <[email protected]>
Somewhere along the way this got mis-merged to include a return without
a value.  Fix it up.

Signed-off-by: Peter Jones <[email protected]>
…er-menu=xxx" work with grub

This commit adds a number of scripts / config files to make
"systemctl reboot --boot-loader-menu=xxx" work with grub:

1. /lib/systemd/system/systemd-logind.service.d/10-grub.conf
This sets SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU in the env. for logind,
indicating that the boot-loader which is used supports this feature, see:
https://github.com/systemd/systemd/blob/master/docs/ENVIRONMENT.md

2. /lib/systemd/system/grub-systemd-integration.service
   /lib/systemd/system/reboot.target.wants/grub-systemd-integration.service ->
     ../grub-systemd-integration.service
   /usr/libexec/grub/grub-systemd-integration.sh

The symlink in the .wants dir causes the added service file to be started
by systemd just before rebooting the system.
If /run/systemd/reboot-to-boot-loader-menu exist then the service will run
the grub-systemd-integration.sh script.
This script sets the new menu_show_once_timeout grubenv variable to the
requested timeout in seconds.

3. /etc/grub.d/14_menu_show_once

This new grub-mkconfig snippet adds the necessary code to the generated
grub.conf to honor the new menu_show_once_timeout variable, and to
automatically clear it after consuming it.

Note the service and libexec script use grub-systemd-integration as name
because in the future they may be used to add further integration with
systemctl reboot --foo options, e.g. support for --boot-loader-entry=NAME.

A few notes about upstreaming this patch from the rhboot grub2 fork:
1. I have deliberately put the grub.conf bits for this in a new / separate
   grub-mkconfig snippet generator for easy upstreaming
2. Even though the commit message mentions the .wants symlink for the .service
   I have been unable to come up with a clean way to do this at "make install"
   time, this should be fixed before upstreaming.

Downstream notes:
1. Since make install does not add the .wants symlink, this needs to be done
   in grub2.spec %install
2. This is keeping support for the "old" Fedora specific menu_show_once env
   variable, which has a hardcoded timeout of 60 sec in 12_menu_auto_hide in
   place for now. This can be dropped (eventually) in a follow-up patch once
   GNOME has been converted to use the systemd dbus API equivalent of
   "systemctl reboot --boot-loader-menu=xxx".

Signed-off-by: Hans de Goede <[email protected]>
Downstream RH / Fedora patch for compatibility with old, not (yet)
regenerated grub.cfg files which miss the menu_show_once_timeout check.
This older grubenv variable leads to a fixed timeout of 60 seconds.

Note that the new menu_show_once_timeout will overrule these 60 seconds
if both are set and the grub.cfg does have the menu_show_once_timeout
check.

Signed-off-by: Hans de Goede <[email protected]>
When keyboard controller acts in Translate mode (0x40 mask), then use
set 1 since translation is done.
Otherwise use the mode queried from the controller (usually set 2).

Added "atkeyb" debugging messages in at_keyboard module as well.

Resolves: rhbz#1897587

Tested on:
- Asus N53SN (set 1 used)
- Dell Precision (set 1 used)
- HP Elitebook (set 2 used)
- HP G5430 (set 1 used, keyboard in XT mode!)
- Lenovo P71 & Lenovo T460s (set 2 used)
- QEMU/KVM (set 1 used)

Signed-off-by: Renaud Métrich <[email protected]>
For each platform, GRUB is shipped as a kernel image and a set of
modules. These files are then used by the grub-install utility to
install GRUB on a specific device. However, in order to support UEFI
Secure Boot, the resulting EFI binary must be signed by a recognized
private key. For this reason, for EFI platforms, most distributions also
ship prebuilt EFI binaries signed by a distribution-specific private
key. In this case, however, the grub-install utility should not be used
because it would overwrite the signed EFI binary.

The current fix is suboptimal because it preserves all EFI-related code.
A better solution could be to modularize the code and provide a
build-time option.

Resolves: rhbz#1737444

Signed-off-by: Jan Hlavac <[email protected]>
[rharwood: drop man page]
… is in the environment and not empty

Signed-off-by: Renaud Métrich <[email protected]>
Signed-off-by: Renaud Métrich <[email protected]>
[[email protected]: rebase fuzz]
Signed-off-by: Robbie Harwood <[email protected]>
This seems required with HP DL380p Gen 8 systems.
Indeed, with this system, we can see the following sequence:

1. controller is queried to get current configuration (returns 0x30 which is quite standard)
2. controller is queried to get the current keyboard set in used, using code 0xf0 (first part)
3. controller answers with 0xfa which means "ACK" (== ok)
4. then we send "0" to tell "we want to know which set your are supporting"
5. controller answers with 0xfa ("ACK")
6. controller should then give us 1, 2, 3 or 0x43, 0x41, 0x3f, but here it gives us 0xfe which means "NACK"

Since there seems no way to determine the current set, and in fact the
controller expects set2 to be used, we need to rely on an environment
variable.
Everything has been tested on this system: using 0xFE (resend command),
making sure we wait for ACK in the 2 steps "write_mode", etc.

Below is litterature I used to come up with "there is no other
solution":
- https://wiki.osdev.org/%228042%22_PS/2_Controller
- http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm
- http://www.s100computers.com/My%20System%20Pages/MSDOS%20Board/PC%20Keyboard.pdf
Colin Watson's patch from comment #11 on the upstream bug:
https://savannah.gnu.org/bugs/?35880#comment11

Resolves: rhbz#1592124

Signed-off-by: Paulo Flabiano Smorigo <[email protected]>
The 30_uefi-firmware template checks if an OsIndicationsSupported UEFI var
exists and EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, to decide whether
a "fwsetup" menu entry would be added or not to the GRUB menu.

But this has the problem that it will only work if the configuration file
was created on an UEFI machine that supports booting to a firmware UI.

This for example doesn't support creating GRUB config files when executing
on systems that support both UEFI and legacy BIOS booting. Since creating
the config file from legacy BIOS wouldn't allow to access the firmware UI.

To prevent this, make the template to unconditionally create the grub.cfg
snippet but check at runtime if was booted through UEFI to decide if this
entry should be added. That way it won't be added when booting with BIOS.

There's no need to check if EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set,
since that's already done by the "fwsetup" command when is executed.

Resolves: rhbz#1823864

Signed-off-by: Javier Martinez Canillas <[email protected]>
When filesystem detection fails, all that's currently debug-logged is a
series of messages like:

    grub-core/kern/fs.c:56:fs: Detecting ntfs...
    grub-core/kern/fs.c:76:fs: ntfs detection failed.

repeated for each filesystem.  Any messages provided to grub_error() by
the filesystem are lost, and one has to break out gdb to figure out what
went wrong.

With this change, one instead sees:

    grub-core/kern/fs.c:56:fs: Detecting fat...
    grub-core/osdep/hostdisk.c:357:hostdisk: reusing open device
    `/path/to/device'
    grub-core/kern/fs.c:77:fs: error: invalid modification timestamp for /.
    grub-core/kern/fs.c:79:fs: fat detection failed.

in the debug prints.

Signed-off-by: Robbie Harwood <[email protected]>
(cherry picked from commit 838c79d658797d0662ee7f9e033e38ee88059e02)
These #include lines ensure that grub2 continues to build with C99
where implicit function declarations are removed.

Related to:

  <https://fedoraproject.org/wiki/Changes/PortingToModernC>
  <https://fedoraproject.org/wiki/Toolchain/PortingToModernC>
Recently we started building with -Werror=implicit-function-declaration,
and discovered that ofdisk.c is missing an include to declare
grub_env_get().

This patch adds that #include.

Signed-off-by: Peter Jones <[email protected]>
fixes bz#2223437

Signed-off-by: Marta Lewandowska <[email protected]>
The initial fix implemented a new flag that forces the grub cfg
stub to be located on the same disk as grub. This created several
issues such as RAID machines not being able to boot as their
partition names under grub were different from the partition where
grub is located. It also simply means that any machines with the
/boot partition located on a disk other than the one containing grub
won't boot.
This commit denies booting if the grub cfg stub is located on a USB
drive with a duplicated UUID (UUID being the same as the partition
containing the actual grub cfg stub)

Signed-off-by: Nicolas Frayer <[email protected]>
It is disabled very much intentional, to not parse arbitrary partition
on the disk. Do not suggest enabling it.

Signed-off-by: Marek Marczykowski-Górecki <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.