Browse Source
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Message-ID: <20250225163031.1409078-25-kraxel@redhat.com>pull/291/head
3 changed files with 76 additions and 0 deletions
@ -0,0 +1,68 @@ |
|||
============== |
|||
UEFI variables |
|||
============== |
|||
|
|||
Guest UEFI variable management |
|||
============================== |
|||
|
|||
The traditional approach for UEFI Variable storage in qemu guests is |
|||
to work as close as possible to physical hardware. That means |
|||
providing pflash as storage and leaving the management of variables |
|||
and flash to the guest. |
|||
|
|||
Secure boot support comes with the requirement that the UEFI variable |
|||
storage must be protected against direct access by the OS. All update |
|||
requests must pass the sanity checks. (Parts of) the firmware must |
|||
run with a higher privilege level than the OS so this can be enforced |
|||
by the firmware. On x86 this has been implemented using System |
|||
Management Mode (SMM) in qemu and kvm, which again is the same |
|||
approach taken by physical hardware. Only privileged code running in |
|||
SMM mode is allowed to access flash storage. |
|||
|
|||
Communication with the firmware code running in SMM mode works by |
|||
serializing the requests to a shared buffer, then trapping into SMM |
|||
mode via SMI. The SMM code processes the request, stores the reply in |
|||
the same buffer and returns. |
|||
|
|||
Host UEFI variable service |
|||
========================== |
|||
|
|||
Instead of running the privileged code inside the guest we can run it |
|||
on the host. The serialization protocol can be reused. The |
|||
communication with the host uses a virtual device, which essentially |
|||
configures the shared buffer location and size, and traps to the host |
|||
to process the requests. |
|||
|
|||
The ``uefi-vars`` device implements the UEFI virtual device. It comes |
|||
in ``uefi-vars-x86`` and ``uefi-vars-sysbus`` flavours. The device |
|||
reimplements the handlers needed, specifically |
|||
``EfiSmmVariableProtocol`` and ``VarCheckPolicyLibMmiHandler``. It |
|||
also consumes events (``EfiEndOfDxeEventGroup``, |
|||
``EfiEventReadyToBoot`` and ``EfiEventExitBootServices``). |
|||
|
|||
The advantage of the approach is that we do not need a special |
|||
privilege level for the firmware to protect itself, i.e. it does not |
|||
depend on SMM emulation on x64, which allows the removal of a bunch of |
|||
complex code for SMM emulation from the linux kernel |
|||
(CONFIG_KVM_SMM=n). It also allows support for secure boot on arm |
|||
without implementing secure world (el3) emulation in kvm. |
|||
|
|||
Of course there are also downsides. The added device increases the |
|||
attack surface of the host, and we are adding some code duplication |
|||
because we have to reimplement some edk2 functionality in qemu. |
|||
|
|||
usage on x86_64 |
|||
--------------- |
|||
|
|||
.. code:: |
|||
|
|||
qemu-system-x86_64 \ |
|||
-device uefi-vars-x86,jsonfile=/path/to/vars.json |
|||
|
|||
usage on aarch64 |
|||
---------------- |
|||
|
|||
.. code:: |
|||
|
|||
qemu-system-aarch64 -M virt \ |
|||
-device uefi-vars-sysbus,jsonfile=/path/to/vars.json |
|||
@ -0,0 +1,7 @@ |
|||
known issues and limitations |
|||
---------------------------- |
|||
|
|||
* works only on little endian hosts |
|||
- accessing structs in guest ram is done without endian conversion. |
|||
* works only for 64-bit guests |
|||
- UINTN is mapped to uint64_t, for 32-bit guests that would be uint32_t |
|||
Loading…
Reference in new issue