Hi Simon,
Heinrich provided some great answers on the technical details. I'll try
not to retrace his answers, but there are a few conceptual model bits
that I think are worth talking about...
On 28/09/2020 17: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.
I'll assume for both of the cases you describe below that the UEFI boot
path (bootefi) is used instead of the traditional bootm.
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.
Case 2:
Firmware loads EFI app and provides EFI boot services to it. How the
system actually boots is under control of the app.
As far as bootefi is concerned, case 1 & case 2 are identical. The image
to be run is loaded into memory and bootefi executes the payload. In
case 1 the payload in Linux's built-in UEFI stub. In case 2 the payload
is grub.efi, shell.efi, shim.efi, etc.
bootefi differs from bootm in that instead of a bare vmlinuz image or a
FIT image, the loaded image is a PECOFF executable. U=Boot parses the
PECOFF headers, loads the sections into memory and jumps to the entry
point. It also leaves a pointer to an in-memory information table with
callbacks into firmware functions for accessing basic services (console,
block device, network, graphics, filesystem, etc).
If the image is Linux, then the stub will do a small amount of setup
before calling ExitBootServices(), which tells firmware to stop managing
hardware because the kernel is taking over. (In UEFI terms, this is call
an "OS loader" image)
If the image is a transient binary like Grub or the UEFI shell, it can
use firmware facilities to load additional files (e.g., initrd, kernel,
etc) before jumping into another PE/COFF binary. For example, Grub will
typically load the kernel into memory, which itself is a PE/COFF image,
and then jump to its entry point.
If an image doesn't call ExitBootServices(), and instead exits, control
returns to firmware as one would expect.
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.
Of the items you've listed above, DT selection does indeed need work,
but the rest is quite well specified. The UEFI spec has very clear
specifications on how the boot image is selected via the BOOTxxxx
variables and the format of the binaries. Secure Boot is also
standardized so that when Secure Boot is turned on, firmware will only
execute images signed by a recognized key.
It is no more arbitrarily complex than booting an OS kernel. When
compared against bootm, both boot flows load an image into memory, and
both jump to the image starting point. In both cases the OS can do
whatever it wants after the firmware jumps into it, and in both cases if
security is enabled then the binaries must be signed.
Where UEFI differs is that it continues to offer {console,net,block,fs}
services for as long as the image chooses to use them so that early boot
code doesn't need to carry its own implementations.
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?
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?
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?
A great way to get familiar with it is to play around with the UEFI code
already in U-Boot with the UEFI Self Certification test suite. Building
the SCT is straight forward, and there are some instructions for doing
so here:
https://github.com/glikely/edk2-test-manifest
If you enable UEFI in U-Boot and copy the SCT to a USB drive, u-boot
should be able to find and run the UEFI shell from the USB drive.
There is also good documentation on the U-Boot implementation:
https://github.com/u-boot/u-boot/blob/master/doc/uefi/uefi.rst
Cheers,
g.
_______________________________________________
boot-architecture mailing list
boot-architecture@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/boot-architecture