Hi,
> a heads up and public documentation after a very useful internal
> discussion yesterday:
>
> EFI Boot Guard roughly falls into two pieces, namely the EFI loader and
> the Linux tools/libs. As one purpose of the loader is to compensate
> incomplete or possibly unsafe boot path selections/rollbacks via the
> firmware, the loader is not part of (safe) OTA updates. The userland
> tools may reside in updateable rootfs images, thus could move forward
> without breaking a rollback.
>
> Now, this may lead to userland becoming much more recent than the loader
> on concrete system in the field. The interface between both is the
> BGENV.DAT on the respective boot partitions. Luckily, it's format
> (BG_ENVDATA) didn't change in structure and semantic since release v0.2.
> So you may mix an older (not prehistoric) loader version with newer
> userland - if you have good reasons to do so.
>
> However, that compatibility may not always be givin in the future - who
> knows. The challenge will then be that our current structure does not
> foresee any versioning of the structure itself ("revision" is that of
> the managed boot partition). We should therefore change this in order to
> become extensible.
>
> How to do that without breaking existing installations from today?
> Luckily, there is one variable that we can use for this, and that is the
> file size of BGENV.DAT. We will have to grow it, at least by a word that
> holds the structure version, and loader as well as userland tools need
> to check via the size if they see version 1 (current file size) or
> version 2 (extended struct with version field).
Well, it's rather implicit specifying the environment version by file
size.... However, if you can ensure the environment file size is
strictly monotonically increasing on changes (and as well on changes not
increasing the file size by an artificial increase), you don't need
the extra struct field 'version' as there's already a bijective mapping
between file size and version.
Having an environment 'version' field is not an end in itself though, so
what's to be added to the "core" struct fields (BG_ENVDATA) besides 'version'?
That said, we do have "user-defined variables" in the environment
exactly for this use case: to store more information in the environment
than the "core" struct fields allow for. Can't this mechanism be
leveraged?
Granted, even if, this mechanism is also (compile-time) limited (in
space), per default to #define ENV_MEM_USERVARS 131072.
So, to be truly extensible, the environment file format should be
converted from a fixed-length to a run-length encoded format, then
making a 'version' field mandatory to know which particular struct
version to read from the environment file ― if you stick to the binary
format, that is...
> The plan is to add such an extension soon, possibly before the next
> release. That shall come in a backward-compatible manner for userland. A
> newer loader may simply demand the extended structure, though, to make
> things simpler.
The (implicit) assumption here is that userspace is always newer than
the EFI loader binary, right? Otherwise, if a new(er) EFI loader binary
demands a particular environment version that the old(er) userspace
does not know of, you're again in the weeds. This may happen, e.g., for
old(er) rescue media or the like.
> One feature request from the internal discussion remains open so far:
> How to read out the version of the installed loader from the userland
> tools (and display it)? Unsure about this one so far, if BGENV.DAT
> should carry it (risk of becoming stale) or if userland should add
> support for extracting it from the installed loader binary or if we
> should skip that.
The only source of truth for this information is the EFI loader binary
itself. So, assuming you can read the EFI loader binary from userspace,
you can leverage the ― for the purpose of UEFI unused ― PE header fields
for this by encoding the version in, e.g., the MajorImageVersion and
MinorImageVersion fields. Of course, you have to have precautionary
measures in place in the userspace tools so not to write information to
the environment that the EFI loader binary cannot handle ― judged on by
the EFI loader binary's encoded version.
Currently, the EFI binary binary's MajorImageVersion and
MinorImageVersion are both 0 which then indicates compatibility with the
initial and currently only environment version.
You may also encode the expected environment file size (if you want to
go that route) a.k.a. 'version' in some PE header field so that the
EFI loader binary can judge on whether the loaded environment file is
digestible for it or not...
Kind regards,
Christian
--
Dr. Christian Storm
Siemens AG, Technology, T RDA IOT SES-DE
Otto-Hahn-Ring 6, 81739 München, Germany
--
You received this message because you are subscribed to the Google Groups "EFI
Boot Guard" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/efibootguard-dev/20210812114508.cr2wcu5r2wwk3zdq%40MD1ZFJVC.ad001.siemens.net.