doc(bootflow): adapt bootflow doc to efibootguard and swupdate
This commit is contained in:
parent
f275e7e499
commit
162c0098b8
|
|
@ -1,10 +0,0 @@
|
||||||
digraph G {
|
|
||||||
fw [label = "Firmware";shape = rect;];
|
|
||||||
|
|
||||||
btl [label = "Bootloader";shape = rect;];
|
|
||||||
|
|
||||||
os [label = "Operating System";shape = rect;];
|
|
||||||
|
|
||||||
fw -> btl -> os [style = dashed;];
|
|
||||||
fw -> os;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
@startuml
|
||||||
|
!theme cloudscape-design
|
||||||
|
start
|
||||||
|
:**Firmware**;
|
||||||
|
note right
|
||||||
|
Implement a subset of the UEFI specification
|
||||||
|
Usually implemented by u-boot
|
||||||
|
end note
|
||||||
|
:**Bootloader**
|
||||||
|
efibootguard;
|
||||||
|
note right
|
||||||
|
The bootloader is responsible to find and load the Operating System
|
||||||
|
It's an UEFI application that can be signed
|
||||||
|
end note
|
||||||
|
:**Operating System**
|
||||||
|
Unified Kernel Image;
|
||||||
|
note right
|
||||||
|
The Operating System is a single UEFI application that can be signed
|
||||||
|
This application has to call the ExitBootService UEFI protocol
|
||||||
|
This application contains at least the Linux Kernel
|
||||||
|
end note
|
||||||
|
end
|
||||||
|
@enduml
|
||||||
|
|
@ -3,7 +3,7 @@ digraph G {
|
||||||
|
|
||||||
uboot [label = "u-boot with EFI/EBBR support";shape = rect;];
|
uboot [label = "u-boot with EFI/EBBR support";shape = rect;];
|
||||||
|
|
||||||
kernel [label = "OS (EFI Stub + Kernel + Initramfs";shape = rect;];
|
kernel [label = "UKI (EFI Stub + Kernel + DTS + Initramfs";shape = rect;];
|
||||||
|
|
||||||
rom -> uboot -> kernel;
|
rom -> uboot -> kernel;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
***********
|
||||||
|
Disk Layout
|
||||||
|
***********
|
||||||
|
|
||||||
|
Standard Disk Layout
|
||||||
|
====================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Disk Layout using GPT
|
||||||
|
======================
|
||||||
|
|
||||||
|
Modern product use a GPT partionning disk with at least 5 partitions:
|
||||||
|
|
||||||
|
- EFI
|
||||||
|
- PLATFORM0
|
||||||
|
- PLATFORM1
|
||||||
|
- BOOT0
|
||||||
|
- BOOT1
|
||||||
|
|
||||||
|
Order and position of theses partitions doesn't matter as long as the
|
||||||
|
right partition label, partition label and filesystem are used.
|
||||||
|
|
||||||
|
.. image:: disk/disk-layout.png
|
||||||
|
|
||||||
|
Partitions
|
||||||
|
==========
|
||||||
|
|
||||||
|
EFI
|
||||||
|
---
|
||||||
|
|
||||||
|
The EFI partition contains the bootloader (efibootguard).
|
||||||
|
|
||||||
|
.. image:: disk/part-efi.png
|
||||||
|
|
||||||
|
BOOT0 and BOOT1
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The BOOT0 and BOOT1 partition contains a kernel and a configuration files.
|
||||||
|
|
||||||
|
.. image:: disk/part-boot0.png
|
||||||
|
|
||||||
|
PLATFORM0 and PLATFORM1
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The PLATFORM0 and PLATFORM1 partitions contains a Linux root filesystem.
|
||||||
|
|
||||||
|
.. image:: disk/part-platform0.png
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
|
|
@ -0,0 +1,100 @@
|
||||||
|
************************
|
||||||
|
Bootloader: efibootguard
|
||||||
|
************************
|
||||||
|
|
||||||
|
Efibootguard is the default bootloader of CoreOS. It's an open source
|
||||||
|
bootloader based on UEFI made by Siemens and released under GPLv2, that
|
||||||
|
implement the A/B booting scheme.
|
||||||
|
|
||||||
|
Efibootguard allow us to have a redondant boot partition that contain a
|
||||||
|
configuration file for efibootguard and a signed Unified Kernel Image
|
||||||
|
|
||||||
|
A/B Switch
|
||||||
|
==========
|
||||||
|
|
||||||
|
Two partition are used to store two diffrent configuration. The first partition
|
||||||
|
is called boot0 and the second one boot1.
|
||||||
|
|
||||||
|
At boot, efibootguard find the configuration file stored inside each boot
|
||||||
|
partition and load it. Inside the configuration, the field "revision" is used
|
||||||
|
to select the configuration to use to boot the board. It will be the one
|
||||||
|
with the highest revision
|
||||||
|
|
||||||
|
.. uml::
|
||||||
|
|
||||||
|
@startuml
|
||||||
|
!theme cloudscape-design
|
||||||
|
start
|
||||||
|
partition A/B selector {
|
||||||
|
|
||||||
|
:read boot0 configuration;
|
||||||
|
:read boot1 configuration;
|
||||||
|
|
||||||
|
if (boot0.revision > boot1.revision") then (yes)
|
||||||
|
:select boot0;
|
||||||
|
else (no)
|
||||||
|
:select boot1;
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
State checking
|
||||||
|
==============
|
||||||
|
|
||||||
|
After having selecting the configuration to use, efibootguard will use the
|
||||||
|
state field to determine is the configuration is already know to work or not.
|
||||||
|
|
||||||
|
Theses states are possible:
|
||||||
|
|
||||||
|
- ok: the configuration is known to be working
|
||||||
|
- installed: the configuration was just updated and was never booted
|
||||||
|
- testing: the configuration was just updated and was already booted once
|
||||||
|
- failed: the configuration is not working
|
||||||
|
|
||||||
|
.. uml::
|
||||||
|
|
||||||
|
@startuml
|
||||||
|
!theme cloudscape-design
|
||||||
|
start
|
||||||
|
partition state checking {
|
||||||
|
switch (state?)
|
||||||
|
case ( ok )
|
||||||
|
:set state to ok;
|
||||||
|
case ( installed )
|
||||||
|
:set state to testing;
|
||||||
|
case ( testing )
|
||||||
|
:set state to failed;
|
||||||
|
:set revision to 0;
|
||||||
|
:reboot;
|
||||||
|
stop
|
||||||
|
case ( failed )
|
||||||
|
:set revision to 0;
|
||||||
|
:reboot;
|
||||||
|
stop
|
||||||
|
endswitch
|
||||||
|
}
|
||||||
|
end
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
Image loading
|
||||||
|
==============
|
||||||
|
|
||||||
|
The last part of the boot process just consist of reading kernel image
|
||||||
|
from the selected boot partition and then calling the load_image EFI function
|
||||||
|
to let the EFI firmware start the given image. The firmware will then first
|
||||||
|
check the signature of the kernel before starting it.
|
||||||
|
|
||||||
|
.. uml::
|
||||||
|
|
||||||
|
@startuml
|
||||||
|
!theme cloudscape-design
|
||||||
|
start
|
||||||
|
partition kernel loading {
|
||||||
|
: read unified kernel image from boot partition;
|
||||||
|
: load image to memory;
|
||||||
|
}
|
||||||
|
: call EFI load_image();
|
||||||
|
end
|
||||||
|
@enduml
|
||||||
|
|
@ -11,3 +11,6 @@ Belden CoreOS Boot Concepts
|
||||||
|
|
||||||
overview
|
overview
|
||||||
uboot
|
uboot
|
||||||
|
efibootguard
|
||||||
|
uki
|
||||||
|
disk
|
||||||
|
|
@ -13,8 +13,8 @@ In this document, the following terms have specific meanings:
|
||||||
.. glossary::
|
.. glossary::
|
||||||
|
|
||||||
Firmware
|
Firmware
|
||||||
Program that implement the boot and runtime services as defined by the
|
Program that implement some of the boot and runtime services defined by
|
||||||
:ext+uefi:ref:`UEFI specifications <maincontent>`.
|
the :ext+uefi:ref:`UEFI specifications <maincontent>`.
|
||||||
|
|
||||||
Application
|
Application
|
||||||
Program written according to the UEFI specification that can be started
|
Program written according to the UEFI specification that can be started
|
||||||
|
|
@ -25,17 +25,26 @@ In this document, the following terms have specific meanings:
|
||||||
configuration or autodetection.
|
configuration or autodetection.
|
||||||
|
|
||||||
Operating system
|
Operating system
|
||||||
Application that include at least the Linux Kernel and the initial RAM
|
Application that include at least the Linux Kernel.
|
||||||
disk.
|
|
||||||
|
Unified Kernel Image
|
||||||
|
Application that include the Linux kernel and the command line to pass to
|
||||||
|
the kernel and optionaly one or more device trees and a RAM disk
|
||||||
|
|
||||||
|
|
||||||
Generic Boot Flow
|
Generic Boot Flow
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. graphviz:: bootflow-generic.dot
|
.. uml:: bootflow-generic.plantuml
|
||||||
|
|
||||||
|
CoreOS use a standardized workflow based on UEFI: the firmware automatically
|
||||||
|
start the bootloader. The bootloader is stored inside the EFI partition, under:
|
||||||
|
`/EFI/BOOT/BOOT<ARCH>.EFI` where `<ARCH>` is:
|
||||||
|
|
||||||
|
- ARM for Arm32 CPU
|
||||||
|
- A64 for Aarch64 CPU
|
||||||
|
- X64 for Amd64 CPU
|
||||||
|
|
||||||
CoreOS use a standardized workflow: the firmware can start either an
|
|
||||||
optional bootloader or an operating system as an UEFI application.
|
|
||||||
|
|
||||||
Firmware
|
Firmware
|
||||||
========
|
========
|
||||||
|
|
@ -88,6 +97,7 @@ defined by the EBBR Specification. The part of the specification marked as
|
||||||
legacy or deprecated must not be used.
|
legacy or deprecated must not be used.
|
||||||
|
|
||||||
This means:
|
This means:
|
||||||
|
|
||||||
- Only GPT partionning disk are supported
|
- Only GPT partionning disk are supported
|
||||||
- No fixed offsets to firmware data
|
- No fixed offsets to firmware data
|
||||||
|
|
||||||
|
|
@ -105,38 +115,36 @@ The firmware for AMD64 should implement the UEFI specification.
|
||||||
Bootloader
|
Bootloader
|
||||||
==========
|
==========
|
||||||
|
|
||||||
CoreOS only support `systemd-boot` as bootloader. The usage of the bootloader
|
CoreOS only support `efibootguard` as bootloader.
|
||||||
is optional. It's primary use case is for system that don't use a firmware
|
|
||||||
provided by CoreOS.
|
|
||||||
|
|
||||||
|
|
||||||
Operating system
|
Operating system
|
||||||
================
|
================
|
||||||
|
|
||||||
The operating system image is an UEFI application that contain the kernel. We
|
The operating system image is an UEFI application that contain the kernel.
|
||||||
support two method to create this image:
|
|
||||||
|
Two ways can be used to generate this application:
|
||||||
|
|
||||||
|
Kernel built with the built-in EFI stub
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
This method use the EFI stub provided by the kernel.
|
||||||
|
|
||||||
|
|
||||||
Unified Kernel Images (UKI)
|
Unified Kernel Images (UKI)
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
This is the most secure method. The UEFI entry point is provided by
|
This is the most secure method. The UEFI entry point is provided by
|
||||||
`systemd-stub` and the image contains the Linux Kernel, the boot arguments of
|
`efibootguard/stub` and the image contains the Linux Kernel with it's built-in
|
||||||
the kernel, the os-release file and an initrd ram disk.
|
EFI stub, the boot arguments of the kernel and optionaly multiple device trees
|
||||||
|
and an initial RAM disk.
|
||||||
|
|
||||||
This allows to have all these part authenticated via UEFI secure boot.
|
This allows to have all these part authenticated via UEFI secure boot just by
|
||||||
|
signing the UKI.
|
||||||
|
|
||||||
.. warning::
|
.. important::
|
||||||
UKI are not supported for ARM32 target at the moment, due to a bug in objcopy.
|
|
||||||
See https://sourceware.org/bugzilla/show_bug.cgi?id=26218
|
|
||||||
|
|
||||||
.. note::
|
Only the Unified Kernel Image methods is supported by the CoreOS teams. Using
|
||||||
UKI has the advantages to be discoverable by the bootloader without any
|
the kernel directly should be used only for new hardware bring-up. By default
|
||||||
configuration file, and doesn't need a firmware that is able to set the
|
we only sign UKI to ensure that it's the only method used for hardware that
|
||||||
kernel command line.
|
ship with secure boot enabled.
|
||||||
|
|
||||||
Kernel built with the built-in EFI sub
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
This method use the EFI stub provided by the kernel. The initramfs image has to
|
|
||||||
be bundled with the Kernel, using `INITRAMFS_IMAGE_BUNDLE`, as otherwise it
|
|
||||||
will not be authenticated by UEFI secure boot.
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
digraph G {
|
|
||||||
start [label = "boot";];
|
|
||||||
|
|
||||||
mb [label = "Detect the main board name";shape = rect;];
|
|
||||||
|
|
||||||
mbdts [label = "Load main board device tree";shape = rect;];
|
|
||||||
|
|
||||||
ext [label = "Detect the extension module name";shape = rect;];
|
|
||||||
extdts [label = "Load a device tree overlay for each module";shape = rect;];
|
|
||||||
|
|
||||||
dtsprocess [label = "Add and remove device tree node as needed (DT Fixup)";shape = rect;];
|
|
||||||
|
|
||||||
stop [label = "Start UEFI application";];
|
|
||||||
|
|
||||||
start -> mb -> mbdts -> ext -> extdts -> dtsprocess -> stop;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
************************
|
****************
|
||||||
Using U-Boot as Firmware
|
Firmware: U-Boot
|
||||||
************************
|
****************
|
||||||
|
|
||||||
U-boot can be configured to support the EBBR specification. This can be
|
U-boot can be configured to support the EBBR specification. This can be
|
||||||
enabled by enabling both `CONFIG_EFI_LOADER` and
|
enabled by enabling both `CONFIG_EFI_LOADER` and
|
||||||
|
|
@ -21,13 +21,21 @@ to be changed at runtime.
|
||||||
Device tree handling
|
Device tree handling
|
||||||
====================
|
====================
|
||||||
|
|
||||||
As per the EBBR specification, the firmware is responsible to provide the
|
As per the EBBR specification, the firmware is responsible to provide a basic
|
||||||
device tree to the kernel.
|
device tree to the kernel.
|
||||||
|
|
||||||
This means that loading the main device tree and all the device tree overlay are
|
This means that we have to build u-boot with an embedded device tree. On a
|
||||||
is the responsibility of the firmware.
|
machine configuration, this mean settings the `UBOOT_BUILDENV_DEVICE_TREE`
|
||||||
|
variables.
|
||||||
|
|
||||||
|
The kernel can then override the built-in device-tree to use another.
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
The `compatible` field of the device-tree embedded inside `u-boot` has to
|
||||||
|
match with the one used inside the kernel. This allow us to automatically
|
||||||
|
load the right `device-tree` inside the unified kernel image (UKI).
|
||||||
|
|
||||||
.. graphviz:: uboot-dts-handling.dot
|
|
||||||
|
|
||||||
Features to implement per machine
|
Features to implement per machine
|
||||||
=================================
|
=================================
|
||||||
|
|
@ -35,73 +43,12 @@ Features to implement per machine
|
||||||
The u-boot provided by CoreOS should implement the following features for each
|
The u-boot provided by CoreOS should implement the following features for each
|
||||||
supported machine:
|
supported machine:
|
||||||
|
|
||||||
board_fit_config_name_match
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
This allows u-boot to select the device tree to use dynamically using board
|
|
||||||
detection. See `README.multi-dtb-fit`
|
|
||||||
|
|
||||||
|
|
||||||
extension_board_scan
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
The extension_board_scan function has to be implemented. This function should
|
|
||||||
return the list of add-ons board detected, with the filename of the
|
|
||||||
correspondig device-tree overlay.
|
|
||||||
|
|
||||||
DT Fixup
|
DT Fixup
|
||||||
--------
|
--------
|
||||||
|
|
||||||
U-Boot can create, modify and remove node from the device tree dynamically
|
An EFI application like a UKI can overwrite the built-in device tree with a
|
||||||
before starting the kernel. This can be used to pass dynamic information stored
|
custom one. The DT Fixup Protocol allow an application to ask the firmware to
|
||||||
inside a "board descriptor" eeprom or CPLD to the Kernel.
|
some runtime fix to the new device tree, like enabling or removing node.
|
||||||
|
|
||||||
Custom Features that are generic
|
This can be used to pass dynamic information stored inside a "board descriptor"
|
||||||
================================
|
eeprom or CPLD to the Kernel.
|
||||||
|
|
||||||
The u-boot provided by CoreOS should implement the following custom features:
|
|
||||||
|
|
||||||
File authentication
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
In order to be able to authenticate device tree, device-tree overlay file or
|
|
||||||
other file needed by the firmware, we need a command to authenticate a file that
|
|
||||||
was previously loaded is the `load` command.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
My proposal is to use the UEFI Capsule format, to reuse theses function from
|
|
||||||
u-boot:
|
|
||||||
|
|
||||||
- **efi_capsule_authenticate**: Authenticate the UEFI capsule using a x509
|
|
||||||
certificate built into u-boot
|
|
||||||
- **efi_remove_auth_hdr**: Can be used to point a pointer to the start of the
|
|
||||||
content of an authenticated capsule.
|
|
||||||
|
|
||||||
An UEFI Capsule is a generic container that can be signed using a x.509
|
|
||||||
private key. The public key is stored inside u-boot (it's not the same as
|
|
||||||
the keys used for UEFI secure-boot). See
|
|
||||||
https://u-boot.readthedocs.io/en/v2022.10/develop/uefi/uefi.html?highlight=capsule#enabling-capsule-authentication
|
|
||||||
|
|
||||||
|
|
||||||
extension_overlay_cmd
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
A custom command should be made for `extension_overlay_cmd`. The extension
|
|
||||||
subsystem use the command defined as extension_overlay_cmd to load
|
|
||||||
the overlay `${extension_overlay_name}` into `extension_overlay_addr`
|
|
||||||
|
|
||||||
This should reuse the file authentication mechanismus.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
A concept on where and how to securly store device tree and overlay needed
|
|
||||||
by the kernel has to be written.
|
|
||||||
|
|
||||||
My proposal is to use the UEFI Capsule format, to reuse theses function from
|
|
||||||
u-boot:
|
|
||||||
|
|
||||||
- **efi_capsule_authenticate**: Authenticate the UEFI capsule using a x509
|
|
||||||
certificate built into u-boot
|
|
||||||
- **efi_remove_auth_hdr**: Can be used to point a pointer to the start of the
|
|
||||||
content of an authenticated capsule.
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
******************************
|
||||||
|
OS: Unified Kernel Image (UKI)
|
||||||
|
******************************
|
||||||
|
|
||||||
|
|
@ -42,8 +42,8 @@ extensions = [
|
||||||
'sphinx.ext.intersphinx',
|
'sphinx.ext.intersphinx',
|
||||||
'sphinx.ext.todo',
|
'sphinx.ext.todo',
|
||||||
'sphinx.ext.graphviz',
|
'sphinx.ext.graphviz',
|
||||||
|
'sphinxcontrib.plantuml',
|
||||||
]
|
]
|
||||||
# 'sphinxcontrib.plantuml',
|
|
||||||
|
|
||||||
|
|
||||||
# external links and substitutions
|
# external links and substitutions
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue