| 1 | ============== |
| 2 | UEFI variables |
| 3 | ============== |
| 4 | |
| 5 | Guest UEFI variable management |
| 6 | ============================== |
| 7 | |
| 8 | The traditional approach for UEFI Variable storage in qemu guests is |
| 9 | to work as close as possible to physical hardware. That means |
| 10 | providing pflash as storage and leaving the management of variables |
| 11 | and flash to the guest. |
| 12 | |
| 13 | Secure boot support comes with the requirement that the UEFI variable |
| 14 | storage must be protected against direct access by the OS. All update |
| 15 | requests must pass the sanity checks. (Parts of) the firmware must |
| 16 | run with a higher privilege level than the OS so this can be enforced |
| 17 | by the firmware. On x86 this has been implemented using System |
| 18 | Management Mode (SMM) in qemu and kvm, which again is the same |
| 19 | approach taken by physical hardware. Only privileged code running in |
| 20 | SMM mode is allowed to access flash storage. |
| 21 | |
| 22 | Communication with the firmware code running in SMM mode works by |
| 23 | serializing the requests to a shared buffer, then trapping into SMM |
| 24 | mode via SMI. The SMM code processes the request, stores the reply in |
| 25 | the same buffer and returns. |
| 26 | |
| 27 | Host UEFI variable service |
| 28 | ========================== |
| 29 | |
| 30 | Instead of running the privileged code inside the guest we can run it |
| 31 | on the host. The serialization protocol can be reused. The |
| 32 | communication with the host uses a virtual device, which essentially |
| 33 | configures the shared buffer location and size, and traps to the host |
| 34 | to process the requests. |
| 35 | |
| 36 | The ``uefi-vars`` device implements the UEFI virtual device. It comes |
| 37 | in ``uefi-vars-x64`` and ``uefi-vars-sysbus`` flavours. The device |
| 38 | reimplements the handlers needed, specifically |
| 39 | ``EfiSmmVariableProtocol`` and ``VarCheckPolicyLibMmiHandler``. It |
| 40 | also consumes events (``EfiEndOfDxeEventGroup``, |
| 41 | ``EfiEventReadyToBoot`` and ``EfiEventExitBootServices``). |
| 42 | |
| 43 | The advantage of the approach is that we do not need a special |
| 44 | privilege level for the firmware to protect itself, i.e. it does not |
| 45 | depend on SMM emulation on x64, which allows the removal of a bunch of |
| 46 | complex code for SMM emulation from the linux kernel |
| 47 | (CONFIG_KVM_SMM=n). It also allows support for secure boot on arm |
| 48 | without implementing secure world (el3) emulation in kvm. |
| 49 | |
| 50 | Of course there are also downsides. The added device increases the |
| 51 | attack surface of the host, and we are adding some code duplication |
| 52 | because we have to reimplement some edk2 functionality in qemu. |
| 53 | |
| 54 | usage on x86_64 |
| 55 | --------------- |
| 56 | |
| 57 | .. code:: |
| 58 | |
| 59 | qemu-system-x86_64 \ |
| 60 | -device uefi-vars-x64,jsonfile=/path/to/vars.json |
| 61 | |
| 62 | usage on aarch64 |
| 63 | ---------------- |
| 64 | |
| 65 | .. code:: |
| 66 | |
| 67 | qemu-system-aarch64 -M virt \ |
| 68 | -device uefi-vars-sysbus,jsonfile=/path/to/vars.json |