Am 1. Oktober 2020 22:27:43 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Mon, 28 Sep 2020 at 12:20, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 28.09.20 18:51, Simon Glass wrote:
Hi,
I thought perhaps it might be worth starting a thread on this, as despite Grant and Heinrich kinding spending a bit of time talking about this, I am still very much in the dark about how 'embedded'
and
distro/other boot flows are going to come together with EBBR. Of course this would be easier f2f.
Case 1: Firmware loads the kernel to a particular address, selects DT and boots it. The kernel may require EFI boot services, or may not, but
in
the general case the firmware provides them.
The Linux kernel has an EFI stub. This EFI stub consumes UEFI
services
and starts the main part of the kernel.
What about the case where we don't want to use EFI?
Nobody forbids you to forego UEFI. But the topic of EBBR is UEFI.
With UEFI you have a standardized way of booting which allows to boot alternative operating systems with alternative firmwares. This allows to replace OS and firmware independently.
There are use cases where you are tight on resources and will decide to skip this standard.
Case 2: Firmware loads EFI app and provides EFI boot services to it. How
the
system actually boots is under control of the app.
Which app can be the Linux, Windows, BSD or if you do not want to
start
an operating system directly it can be a boot manager like GRUB,
iPXE,
rEFInd.
The strength of the UEFI spec is that it just provides an API and
does
not prescribe what you use it for. This gives much more choice than a firmware tied down to boot one specific OS only.
Exactly, but it is overly complex for many use cases.
It is like with nuts and bolts. An M6 nut will fit onto any M6 bolt anywhere in the world. - But beware of 1/4" UNC parts. They only fit
to
their kin.
How about playing a game written for the EFI API: https://github.com/Openwide-Ingenierie/Pong-UEFI
I think you've just proved my point.
I feel that a lot of the confusion about verified boot, DT
selections,
boot menus, etc. is coming from the introduction of an EFI app
which
has no specification (it can be grub, shim or something else, as I understand it). Certainly this is very flexible and future-proof,
but
it is also arbitrarily complex, unpredictable and hard to secure.
I am wondering if we can come up with a way to deterministically specify how a system will boot and how to make it boot a different
way
(i.e. with a different kernel, initrd, DT).
Heinrich mentioned EFI variables as a way of selecting kernel/initrd/DT. Then the problem becomes just a case of being
able
to change those variables from Linux userspace. Is that right?
In Linux you can use the command efibootmgr to set up the boot
variables
if the UEFI firmware offers the SetVariable() runtime service.
(U-Boot
does not offer it at runtime) With the variables you can only specify
a
binary that is started and "load options". Linux uses these load
options
as command line. A Linux command line parameter (initrd=<path>) can
be
used to specify the initial ramdisk.
The UEFI boot manager (in U-Boot command 'bootefi bootmgr') uses the BootNext and BootOrder variables to identify which BootXXXX variable contains the specification of the binary to start.
The entry point of an UEFI binary (e.g. the Linux EFI stub) receives
two
parameters: the system table pointer, and the handle of the loaded image. The UEFI system table points to a list of configuration
tables.
These may include ACPI, SMBIOS, device-tree, and more. The Linux
command
line can be retrieved via the LoadOptions field of the loaded image protocol installed on the handle passed to the entry point.
It is the task of the firmware to set up a configuration table with
the
device tree or the ACPI table.
Yes most of that matches what I understood, but I knew very little about the boot variables.
So I think we can have still have a reasonably simple boot if the boot variables and all required boot functionality are implemented in U-Boot (as apparently they are) and can be changed using efibootmgr under Linux.
efibootmgr can only be used if the firmware provides UEFI runtime services.
Currently you cannot use efibootmgr to set variables with U-Boot as U-Boot does not offer SetVariable() at runtime yet.
We are talking about having a 'secure' part of EBBR, which allows
for
secure boot. Should we have a 'defined boot' part of EBBR, that defines how the kernel/DT/initrd are selected, based on EFI
variables?
Secure Boot in UEFI terms involves setting up the PK, KEK, db, and
dbx
variables. Then every UEFI binary loaded can only be started via
service
StartImage() if it was signed with a certificate with a public key in
db
and not in dbx.
Verification of intrd and fdt is out of scope for the UEFI
specification.
If these are in a FIT then the verification can be done in U-Boot.
If you ensure the integrity of your binaries without relying on the UEFI secure boot infrastructure, that is fine.
Unfortunately I just don't know enough about all the different boot flows used by the different distros. It seems like crazy town. Does anyone have some pointers so I can do some study?
Debian/Ubuntu, Fedora and Suse all use UEFI [-> shim] -> GRUB ->
Linux
if the firmware running the installer image supports UEFI.
FreeBSD and OpenBSD can be started as UEFI payloads but they
typically
do not use GRUB.
Here is a good starting point: https://wiki.ubuntu.com/UEFI/SecureBoot
OK thank you. What are SHIM and MOK not incorporated into the boot loader?
Shim was created to install Linux on devices that only have Microsoft certificates in the KEK.
If you control the PK and KEK UEFI variables, you don't need shim.
Best regards
Heinrich