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.
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.
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 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.
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.
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
Best regards
Heinrich