Index | LX067 |
---|---|
Title | LXD VM instance EFI Variables edit CLI |
Subteam | LXD |
Status | Implemented |
Authors | Aleksandr Mikhalitsyn |
Stakeholders | Thomas Parrott |
Type | Implementation |
Created | Feb 7, 2024 |
Release | 5.21.0 |
Abstract
This feature will introduce a bunch of LXD CLI subcommands like lxc config uefi show, lxc config uefi edit, etc to allow EDKII NVRAM file manipulation and changing EFI variables values.
Rationale
It was requested by our colleagues from Foundations team as they want to have an convenient CLI interface to edit EFI variables mostly for EFI/SHIM/bootloader debugging.
Specification
Design
We want to use GitHub - awslabs/python-uefivars: Python package and helper tool to analyze, convert and modify UEFI variable stores as a internal low-level tool to manipulate with the EDKII NVRAM files. This package also provides an interface to convert an EDKII NVRAM file to JSON and back from JSON. It’s convenient from the implementation standpoint. JSON output looks like this:
$ uefivars -i edk2 -o json -I qemu.nvram 2>/dev/null
{
"version": 2,
"variables": [
{
"name": "Attempt 1",
"data": "000000000000000...WAS CUT BY ME...0000000000000",
"guid": "59324945-ec44-4c0d-b1cd-9db139df070c",
"attr": 3
},
We don’t want to expose this JSON format that python-uefivars uses directly, but instead we define an analogical format in our API and then on the LXD server side we will be able to convert from one format to another. Generally speaking, we can go with precisely the same structure, but, obviously, start with the version 1. The reason for that is we may want to switch the tool to something else in the future but remain compatible. We have seen (https://github.com/awslabs/python-uefivars/commit/1e464d77d81e9b74755bedc26b0f027650e9004e) that output format in this package was changed once.
Final structure can be like this:
{
"name:<UTF-8 encoded string>-guid:<UUID string>": {
"data": <HEX representation of the bytes array (hex.Encode in Golang or bytes.hex() in Python)>,
"attr": <decimal (?) represented attrs mask>,
(optional) "timestamp": <HEX representation>,
(optional) "digest": <HEX representation>,
},
<..>
}
As you can see we go with the combination of <name>-<UUID>
as a key in JSON map. That’s because the EFI variable name is not a unique and it’s perfectly fine to have a few EFI variables with the same name. What is unique is a pair (UUID, name)
. By doing that we just following a semantic that efivarfs
has:
$ ls -la /sys/firmware/efi/efivars/
total 0
drwxr-xr-x 2 root root 0 Feb 8 09:04 .
drwxr-xr-x 5 root root 0 Feb 8 09:04 ..
-rw-r--r-- 1 root root 76 Feb 8 09:04 AbtStatus-a0b1889e-00eb-445b-8ca9-e91ce43c907d
-rw-r--r-- 1 root root 14 Feb 8 09:04 AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4
It’s worth mentioning that the entire JSON string will be encoded as UTF-8. EFI variable names are supposed to be represented as UCS-2, but as we can represent any UCS-2 character in UTF-8 it’s safe just to use UTF-8 everywhere. Internally, python-uefi vars expects us to provide file encoded as UTF-8 (https://github.com/awslabs/python-uefivars/blob/04a6e47d13b2975e4f11581559b210ac2aa5e8c5/pyuefivars/json.py#L36).
API changes
Types
type InstanceEFI struct {
// EFI variables map
// Hashmap key format is <efi-variable-name>-<UUID>
// Example: AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4
Variables map[string]*InstanceEFIVariable `json:"variables" yaml:"variables"`
}
type InstanceEFIVariable struct {
// EFI variable data (HEX-encoded)
Data string `json:"data" yaml:"data"`
// EFI variable attributes
Attr uint32 `json:"attr" yaml:"attr"`
// EFI variable timestamp (HEX-encoded)
Timestamp string `json:"timestamp" yaml:"timestamp"`
// EFI variable digest (HEX-encoded)
Digest string `json:"digest" yaml:"digest"`
}
Routes
- GET
instances/{name}/efi_vars
to read all instance’s EFI variables - PUT
instances/{name}/efi_vars
to update instance’s EFI variables
Both routes are only valid for VM instance type.
CLI changes
Introduce new LXD CLI subcommands:
- lxc config uefi show
- lxc config uefi edit
- lxc config uefi set key=val
- lxc config uefi unset key
Database changes
No database changes.