# Configure and secure boot with systemd-boot and UKI
The systemd-boot unified extensible firmware interface (UEFI) boot manager provides options to control the boot flow and loads the user-selected boot loader.
The configuration files, kernel images, initrd images, and other EFI images must reside on the EFI partition.
To run the Qualcomm Linux kernel directly as EFI images, build them with `CONFIG_EFI_STUB`. The systemd-boot supports two configurations:
>
>
> - Type1: The Type1 configuration uses boot loader specification (BLS) description files. You can find these files in the `/loader/entries/` directory on the EFI.
> - Type2: The Type2 configuration uses unified kernel images (UKI). These images combine the kernel, initrd, and kernel command-line into a single EFI executable.
> Type2 offers better security because the UKI contains all the necessary information for the device to boot. Signing a UKI image secures all included entities.
> If UEFI secure boot is enabled, the system only loads signed images, making signing a requirement.
For more details, see [systemd-boot](https://www.freedesktop.org/software/systemd/man/latest/systemd-boot.html).
Note
To use a secure boot enabled device, signing is required.
## UKI
UKI is a combination of a UEFI boot stub program, a Qualcomm Linux kernel
image, an initrd, and other resources in a single UEFI portable
executable (PE) file. The UEFI boot stub looks for various resources
for the kernel invocation inside the UEFI PE binary. This allows
combining various resources inside a single UKI image,
which may then be signed using sbsign.
Qualcomm Linux uses sbsign to sign PE files, while non-PE files such as DTB are signed using OpenSSL.
For more details about UKI, see [`unified_kernel_image`](https://uapi-group.org/specifications/specs/unified_kernel_image/).
The following table shows the `uki.efi` content:
| Components of uki.efi file | Contents |
| --- | --- |
| Initrd = Init ramdisk | `initramfs-ostree-image-qcs6490-rb3gen2-vision-kit.cpio.gz` |
| Linux = Kernel Image | `Image` (as systemd-boot expects uncompressed kernel) |
| Uname = Kernel Release | `6.6.52` |
| Efi-arch = Architecture | `aa64` |
| Stub = System-boot efi stub | `linuxx64.efi.stub` |
| OS-release = OS-release |
|
### Image recipes
`meta-qcom-hwe/recipes-kernel/images` contains the following recipes:
- `linux-qcom-uki.bb` generates `uki.efi`.
- `esp-qcom-image.bb` generates a VFAT image, `efi.bin`, which contains `uki.efi` and `systemd-boot`.
The `meta-qcom-distro/classes/image-qcom-deploy.bbclass` class invokes the `esp-qcom-image`.
## EFI image
The EFI image, `efi.bin`, is a VFAT file system image stored in the EFI partition of the flash.
This VFAT file system contains the images necessary for the UEFI to load and transfer execution control to systemd-boot.
To transfer execution control to the systemd-boot manager, UEFI mounts `efi.bin`, loads `bootaa64.efi`,
and executes it. The systemd-boot manager parses the `loader.conf`, loads the kernel image, and transfers the control to it.
For more information about the structure of EFI, see [EFI system
partition](https://wiki.archlinux.org/title/EFI_system_partition).
The following is the sample structure of `efi.bin` from Qualcomm Linux.
It contains systemd-boot `bootaa64.efi` and Qualcomm Linux kernel `vmlinuz-`
under the `/ostree/poky-` directory.
>
>
> 
>
> **Figure: `efi.bin` file generated with OSTree support**
## Signing
Secure boot is a feature in the UEFI standard, but it’s not enabled by default in Qualcomm Linux.
When enabled, secure boot adds a layer of protection to the preboot process by maintaining a cryptographically
signed list of binaries that are run at device bootup, if successfully authenticated. This ensures that the device’s
boot firmware and Linux OS boot components, such as the boot manager, kernel, and initramfs, haven’t been tampered with.
UEFI secure boot uses a digital signature to validate the
authenticity and integrity of the binary code that it loads. The UEFI secure
variables store all the keys. Achieving UEFI secure boot involves using
the platform key (PK), key exchange key (KEK), database (DB),
and forbidden signatures database (DBX).
Using secure boot requires the keys PK, KEK, and DB. While
multiple KEK, DB, and DBX are allowed, only one PK is allowed.
Enabling UEFI secure boot requires registering the PK in the system.
Qualcomm recommends provisioning PK at the last step of the secure boot
enabling process. For more information about how Qualcomm has implemented
the UEFI secure boot feature, see [Secure
boot](https://docs.qualcomm.com/bundle/publicresource/topics/80-70023-11/features.html#secure-boot).
### Host tool `signing_tool.py` to sign Linux OS images generated by Qualcomm Linux builds
Enabling UEFI secure boot requires signing the EFI and DTB images.
Use the `signing_tool.py` host signing tool to streamline this process.
This command-line Python script runs on a Linux host computer (Ubuntu 20.04 or later versions).
It automates the signing of EFI and DTB images in two separate operations.
The tool also supports the feature to combine the DTB files.
The host signing tool is available for download on [GitHub](https://github.com/quic/host-signing-tool).
The host signing tool runs on a Linux machine with Python3 installed.
It can sign either the EFI image or the DTB image in a single
operation. To sign both the EFI and DTB images, you must invoke
the tool twice with different inputs.

**Figure: Linux machine with OpenSSL and sbsign**
The host tool expects unsigned EFI or DTB files, along with
certificates and keys, as input. After invoking, the tool unpacks the
unsigned image, signs the available items using the provided key and
certificate, and then repacks the images, replacing the unsigned
version with the signed one.
To combine DTB files, you must follow a different process
than the signing process. Use the tool to either combine a new DTB file
with a pre-existing `dtb.bin` or create a new concatenated `dtb.bin`
file from a list of available DTB files.
### Prerequisites
To run this tool, install the following on the Linux host computer:
- OpenSSL, sbsign, and mtools utilities
- Python3
- pip, subprocess, shlex, socket, glob, and shutil Python modules
### Configure the host signing tool
You must configure the host signing tool before starting the
operation.
The host tool requires providing the necessary information in a `config.ini` configuration file. The tool reads this file and
signs the image accordingly. The following code snippet shows the variables in the configuration file:
#### `config.ini` file
[common]
# Section - 1: Common Selection
# Select operation: 1. sign_image or 2. combine_dtb
operation = sign_image
# This option is useful for both operations(sign_image & combine_dtb). Possible values for file_path are 1. remote or 2. local
file_path = local
# This option is required for both operations(sign_image & combine_dtb) if file_path == remote
local_machine_private_key_path = /usr2//.ssh/id_rsa
# Section - 2: operation == sign_image related common selection
# Possible values for image_type are 1. efi or 2. dtb
image_type = efi
# This option is required if operation == sign_image & image_type == efi
loader_conf_timeout = 20
# Section - 3: operation == combine_dtb related common selection
# Possible values for combine_dtb_type are 1. combine_with_old_dtb, 2. combine_without_old_dtb
combine_dtb_type = combine_with_old_dtb
# Below options are required to fetch file from remote Linux machine in the same network (that is if file_path == remote)
# This option is useful if operation == sign_image & image_type == efi
[efi_config]
efi_remote_hostname =
efi_remote_username =
efi_remote_filepath =
# This option is useful if operation == sign_image. Both image_type requires this option
[keys_config]
keys_remote_hostname =
keys_remote_username =
keys_remote_filepath =
# This option is useful if operation == sign_image & image_type == dtb
[dtb_config]
dtb_remote_hostname =
dtb_remote_username =
dtb_remote_filepath =
# This option is useful if operation == combine_dtb.
[combine_dtb_config]
combine_dtb_remote_hostname =
combine_dtb_remote_username =
combine_dtb_remote_filepath =
Copy to clipboard
Table : Variables in config.ini file
| Variable in config.ini | Values | Description |
| --- | --- | --- |
| `operation` | `sign_image/combine_dtb` | Use this configuration to select either signing the image or combining DTB files. |
| `image_type` | `efi/dtb` | If `operation == sign_image`, use this configuration to select `efi` or `dtb` to sign separately. |
| `combine_dtb_type` | `combine_with_old_dtb/combine_without_old_dtb` | If `operation == combine_dtb`, use this configuration to select the type of combine DTB operation you want to perform.
>
>
> |
| `file_path` | `local/remote` | |
| `local_machine_private_key_path` | `` | This file establishes an SSH connection with a remote machine if `file_path = remote`. |
| `loader_conf_timeout` | `` | The systemd-boot wait time to let you choose to authenticate the binaries. This option is required to sign `efi.bin`. |
| `efi/keys/dtb/combine-dtb_remote_hostname` | `` | If `file_path = remote`, then the host tool selects the host name of the remote machine to copy the `efi/keys/dtb/combine-dtb` file from the remote machine using SCP. |
| `efi/keys/dtb/combine-dtb_remote_username` | `` | If `file_path = remote`, then the host tool selects the user name of the remote machine to copy the `efi/keys/dtb/combine-dtb` file from the remote machine using SCP, provided the username is created on the remote machine. |
| `efi/keys/dtb/combine-dtb_remote_filepath` | `` | If `file_path = remote`, then the host tool selects the path of a `efi/key/dtb/combine-dtb` file on the remote machine to copy that file from the remote machine using SCP. |
To configure the host signing tool using the `config.ini` file, do the following:
1. Set the `operation` variable to specify which operation must be performed. The options are either `sign_image` or `combine_dtb`.
2. If you select `operation == sign_image`, specify which image to sign by setting the `image_type` variable. The options are either `efi` or `dtb`.
3. Indicate the location of the unsigned EFI and DTB image, keys, and certificates using the `file_path` variable.
- If you select `local` in the configuration file, copy the EFI and DTB image, keys, and certificate files manually to the local working directory:
1. Create an `unsigned_binaries` directory in the same path as the script, and then copy the `efi.bin` and `dtb.bin` image into that directory.
2. Create a `keys` directory in the same path as the script and then copy the `db.auth`, `db.crt`, `db.key`, `KEK.auth`, and `PK.auth` files into that directory.
- If you want the script to copy the required files automatically from a remote Linux machine on the same network, select `remote` in the configuration file.
In the configuration file, provide information for the following variables:
- `local_machine_private_key_path` (mandatory)
- `[efi_config]` section (if `operation` is `sign_image` and if `image_type` is `efi`)
- `[keys_config]` section (if `operation` is `sign_image`)
- `[dtb_config]` section (if `operation` is `sign_image` and if `image_type` is `dtb`)
- `[combine_dtb_config]` section (if `operation` is `combine_dtb`)
Note
The script supports copying from another Linux machine over SCP within the same network.
4. When `image_type` is set to efi in the configuration file, update the `loader_conf_timeout` variable.
5. When you set `operation == combine_dtb`, specify the type of DTB combination operation by setting the `combine_dtb_type` variable. The options are either `combine_with_old_dtb` or `combine_without_old_dtb`.
1. If you select `combine_dtb_type == combine_with_old_dtb`, create an `unsigned_binaries` directory in the same path as the script and copy the `dtb.bin` image to that directory.
2. For both options, create a `dtb_files` directory in the same path as the script and copy all the DTB files that must be combined into that directory (either with the old combined DTB from `dtb.bin` or with each other only).
6. If you missed any configuration information, the script runs and prompts you for the missing details through the command line.
### Run host signing tool
1. After completing the code build process and obtaining the unsigned `efi.bin` and `dtb.bin` images, run the host signing tool.
2. Store the host signing tool files (`signing_tool.py` and `config.ini`) on a Linux machine. Ensure that both the files are in the same working directory.
3. Set up the host signing tool according to the configuration instructions.
4. Run the following command to launch the host tool from the command line: `$python3 signing_tool.py`
The host signing tool displays your selections and operational commands on the screen. It also displays errors in the command line.
After the tool completes its process, it creates a directory called `signed_binaries` in the same working directory. The signed `efi.bin` or `dtb.bin` image is stored in the directory. The tool deletes other user-created directories after signing.
5. Follow this process twice, once for `efi.bin` and once for `dtb.bin`. After each signing operation, delete the `signed_binaries` directory before starting a new operation.
### Host signing tool workflow
The following figure shows the workflow of the host signing tool:

**Figure: Host signing tool workflow**
- The host tool requires the `efi.bin` and `dtb.bin` paths (absolute path or network path).
- `efi.bin` with OSTree support contains `vmlinuz-x.y.z` (Qualcomm Linux kernel image) and `bootaa64.efi` (boot loader image).
- `dtb.bin` contains `combined-dtb.dtb`.
- The host tool requires the path of `certificate` and `key` (absolute path or network path) to sign the images.
- The host tool mounts `efi.bin` and `dtb.bin` on the FAT partition, which provides the following directory structure and follows its separate signing process:
The directory structure of `efi.bin`:
>
>
> 
>
> **Figure: efi.bin**
The directory structure of `efi.bin` with OSTree support:
>
>
> 
>
> **Figure: efi.bin with OSTree support**
The directory structure of `dtb.bin`:
>
>
> 
>
> **Figure: dtb.bin**
- After signing the images, the host tool copies the .auth files to the `/loader/keys/authkeys` directory for both `efi.bin` and `dtb.bin`.
- The host tool configures the wait time in the `systemd-boot` loader configuration. This wait time stops the kernel loading and allows you to review and select the `systemd-boot` menu options. The `loader.conf` file must be available in an updated `efi.bin` file.
>
>
> Note
>
>
> The signing process isn’t followed for the `dtb.bin` file.
- The host tool configures `/loader/loader.conf`.
- The syntax for `loader.conf` is `timeout x`, where x = timeout in seconds.
- After the image is signed, the host tool unmounts the `efi.bin/dtb.bin` from the FAT partition. Store the signed `efi.bin` and `dtb.bin` on the host computer on the similar path as the host tool in the `signed_binaries` directory.
- The following is the directory structure for signed `efi.bin` and `dtb.bin`:

**Figure: Directory structures of efi.bin and dtb.bin files**
### `efi.bin` signing process
- The host tool uses the `sbsign` utility to sign the `uki.efi` or vmlinuz.x.y.z and `bootaa64.efi` images separately.
- `sbsign` requires `certificate` and `key` for the signing process. Verify the following syntax where `dsk1.key` is key, `dsk1.crt` is certificate, and the output filename is the same as the input file:
sbsign --key --cert