Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions source/chapter2-uefi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ Functions that are not available during runtime services shall return
:numref:`uefi_runtime_service_requirements` details which `EFI_RUNTIME_SERVICES`
are required to be implemented during boot services and runtime services.

.. versionchanged:: 2.5.0

.. _uefi_runtime_service_requirements:
.. list-table:: `EFI_RUNTIME_SERVICES` Implementation Requirements
:widths: 40 30 30
Expand Down Expand Up @@ -538,13 +540,16 @@ are required to be implemented during boot services and runtime services.
- Required
* - `GetVariable`
- Required
- Optional
- Required for file-backed variable stores. [#RTVarNote]_
Otherwise optional.
* - `GetNextVariableName`
- Required
- Optional
- Required for file-backed variable stores. [#RTVarNote]_
Otherwise optional.
* - `SetVariable`
- Required
- Optional
- Required for file-backed variable stores. [#RTVarNote]_
Otherwise optional.
* - `GetNextHighMonotonicCount`
- N/A
- Optional
Expand All @@ -561,6 +566,12 @@ are required to be implemented during boot services and runtime services.
- Optional
- Optional

.. [#RTVarNote] Firmware storing EFI variables in a file on storage shared
with the OS shall keep the variable services available during runtime
services by implementing the mechanism described in
:ref:`section-runtime-var-handover`.
See section :ref:`section-runtime-variable-access`.

Runtime Device Mappings
-----------------------

Expand Down Expand Up @@ -610,29 +621,42 @@ On AArch64 platforms, if `ResetSystem()` is not implemented then the Operating
System should fall back to making a [PSCI]_ call to reset or shutdown the
system.

.. _section-runtime-variable-access:

Runtime Variable Access
-----------------------

.. versionchanged:: 2.5.0

There are many platforms where it is difficult to implement `SetVariable()` for
non-volatile variables during runtime services because the firmware cannot
access storage after `ExitBootServices()` is called.

e.g., If firmware accesses an eMMC device directly at runtime, it will
collide with transactions initiated by the OS.
Neither U-Boot nor Tianocore have a generic solution for accessing or updating
variables stored on shared media. [#OPTEESupplicant]_
Firmware cannot, on its own, safely update a variable store located on
storage media shared with the OS. [#OPTEESupplicant]_

.. [#OPTEESupplicant] It is worth noting that OP-TEE has a similar problem
regarding secure storage.
OP-TEE's chosen solution is to rely on an OS supplicant agent to perform
storage operations on behalf of OP-TEE.
The same solution may be applicable to solving the UEFI non-volatile
variable problem, but it requires additional OS support to work.
Regardless, EBBR compliance does not require `SetVariable()` support
during runtime services.
Regardless, outside of the file-backed variable store case described
below, EBBR compliance does not require `SetVariable()` support during
runtime services.

https://optee.readthedocs.io/en/4.9.0/architecture/secure_storage.html

If firmware stores EFI variables in a file on a storage device shared with
the operating system, then it shall implement the mechanism described in
:ref:`section-runtime-var-handover`, which keeps `GetVariable()`,
`GetNextVariableName()` and `SetVariable()` available during runtime
services: variable modifications are applied to an in-memory copy of the
variable store, and the operating system writes the updated store content
back to the variable store file.

If a platform does not implement modifying non-volatile variables with
`SetVariable()` after `ExitBootServices()`,
then firmware shall return `EFI_UNSUPPORTED` for any call to `SetVariable()`,
Expand Down
149 changes: 142 additions & 7 deletions source/chapter5-variable-storage.rst
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
.. SPDX-License-Identifier: CC-BY-SA-4.0

*************************************
File Format For Storing EFI Variables
*************************************
********************
EFI Variable Storage
********************

.. versionadded:: 2.2.0

Some UEFI enabled devices can only store EFI variables as a file on a block
device. This implies that at runtime the operating system must manage changes
to the EFI variables by updating the file.

This chapter defines a file-format for EFI variables that both the firmware
and the operating system can rely on.
This chapter defines a file format for EFI variables that both the firmware
and the operating system can rely on, as well as a mechanism allowing the
operating system to persist variable modifications made with `SetVariable()`
during runtime services on behalf of the firmware.

File Format For Storing EFI Variables
=====================================

All integer fields are stored in little-endian byte order.

File header
===========
-----------

The following byte sequence is used to identify the file format:

Expand Down Expand Up @@ -70,7 +75,7 @@ Variables
not sorted.

Variable entries
================
----------------

Each variable is stored as a structure:

Expand Down Expand Up @@ -105,6 +110,128 @@ Data
vendor’s variable followed by `DataSize` bytes of actual content of the
variable.

.. _section-runtime-var-handover:

Runtime Access to File-Backed Variables
=======================================

.. versionadded:: 2.5.0

Firmware that stores EFI variables in a file usually cannot write to that
file after `ExitBootServices()`: the file resides on a storage device that is
controlled by the operating system at runtime, and any firmware access would
conflict with transactions initiated by the OS.

This section defines a mechanism through which such firmware keeps the
variable runtime services available after `ExitBootServices()` by servicing
them from memory, and delegates writing the variable store file to the
operating system. See section :ref:`section-runtime-variable-access` for when
implementing this mechanism is required.

Handover variables
------------------

Firmware implementing this mechanism shall provide the two variables
described below under the following vendor GUID: [#GuidNote]_

.. code-block:: c

#define EBBR_RT_VAR_FILE_GUID \
{ 0xb2ac5fc9, 0x92b7, 0x4acd, \
{ 0xae, 0xac, 0x11, 0xe8, 0x18, 0xc3, 0x13, 0x0c }}

.. [#GuidNote] The GUID value is fixed by existing implementations of this
mechanism. U-Boot defines it as `U_BOOT_EFI_RT_VAR_FILE_GUID`, and the
libefivar library detects the mechanism by looking up `RTStorageVolatile`
under this GUID.

Both variables shall have the `EFI_VARIABLE_BOOTSERVICE_ACCESS` and
`EFI_VARIABLE_RUNTIME_ACCESS` attributes, shall not have the
`EFI_VARIABLE_NON_VOLATILE` attribute, and shall be read-only: any call to
`SetVariable()` targeting them shall fail with `EFI_WRITE_PROTECTED`.

RTStorageVolatile
This variable contains the name of the variable store file as a NUL
terminated ASCII string. The file is located in the root directory of the
EFI System Partition holding the variable store, and the value shall not
contain any directory separator. E.g., U-Boot stores its EFI variables in
the file `ubootefi.var`.

VarToFile
This variable contains the complete content that the variable store file
must have in order to persist the current state of all EFI variables
carrying the `EFI_VARIABLE_NON_VOLATILE` attribute. Firmware shall
regenerate the content every time the variable is read, so that it
reflects all preceding `SetVariable()` calls, including calls made during
runtime services.

The operating system shall treat the content as an opaque binary blob.
Firmware using the file format defined in this chapter returns an
`EFI_VARIABLE_FILE` image holding all variables that have the
`EFI_VARIABLE_NON_VOLATILE` attribute set. [#FormatNote]_

.. [#FormatNote] The mechanism does not depend on the store file format,
as the operating system never interprets the store file content.
Firmware is nevertheless encouraged to use the file format defined in
this chapter.

Firmware requirements
---------------------

Firmware implementing this mechanism shall:

- Maintain a copy of the variable store in `EfiRuntimeServicesData` memory,
and service `GetVariable()` and `GetNextVariableName()` from that copy
during runtime services.

- Implement `SetVariable()` during runtime services by applying the
modification to the in-memory store, without accessing the variable store
file. Modifications are consequently volatile until the operating system
writes them back to the store file, including modifications to variables
that have the `EFI_VARIABLE_NON_VOLATILE` attribute.

- Advertise `EFI_RT_SUPPORTED_GET_VARIABLE`,
`EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME` and
`EFI_RT_SUPPORTED_SET_VARIABLE` in the `EFI_RT_PROPERTIES_TABLE` described
in :UEFI:`4.6.2`.

The in-memory store imposes restrictions during runtime services. The
following operations shall fail:

- Creating, modifying, or deleting authenticated variables (see
`Limitations`_ below).

- Creating, modifying, or deleting volatile variables.

- Modifying or deleting variables that do not have the
`EFI_VARIABLE_RUNTIME_ACCESS` attribute. These variables shall also be
hidden from `GetVariable()` and `GetNextVariableName()`.

- Changing the attributes of an existing variable.

Operating system requirements
-----------------------------

To make a variable modification performed during runtime services
persistent, the operating system shall:

1. Read the `RTStorageVolatile` variable to obtain the name of the variable
store file, and locate that file in the root directory of the EFI System
Partition.

2. Read the `VarToFile` variable after the modification.

3. Write the content of `VarToFile` to the variable store file.

Modifications that have not been written back to the variable store file,
including modifications to variables that have the
`EFI_VARIABLE_NON_VOLATILE` attribute, are lost when the system resets.

The operating system should update the variable store file atomically, so
that an interrupted update cannot corrupt the store. The variable store file
is created by the firmware; the operating system should only update an
existing file, and should not create the file when it is absent.

Limitations
===========

Expand All @@ -119,3 +246,11 @@ signing certificates of nonce-based authenticated variables. [#CertNote]_

.. [#CertNote] Tianocore EDK II keeps signer certificates of authenticated
variables in variables `certdb` and `certdbv`.

Variables modified through the mechanism described in
:ref:`section-runtime-var-handover` only persist across reset if the
operating system writes the updated store content back to the variable store
file. Additionally, on systems with multiple EFI System Partitions,
`RTStorageVolatile` names the variable store file but not the partition
holding it, so identifying the correct partition is left to the operating
system.