tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Adding ESRT and EFI vars support for fwupd



Hello NetBSD devs,

Background
----------

As some might know, FreeBSD gained an interface for querying ESRT about
a year ago ([1], [2]), which was done as part of [3].

[1]:
https://reviews.freebsd.org/rGd12d651f8692cfcaf6fd0a6e8264c29547f644c9
[2]:
https://reviews.freebsd.org/rG24f398e7a153a05a7e94ae8dd623e2b6d28d94eb
[3]: https://nlnet.nl/project/fwdup-BSD/

Adding it allowed to make UEFI capsule plugin of fwupd [4] work for
FreeBSD [5] to perform firmware updates on EFI systems.
Now it's turn for NetBSD and we would like to ask about requirements
and recommendations on the API and its implementation such that they
would be accepted by the upstream.

[4]: https://fwupd.org/
[5]:
https://github.com/fwupd/fwupd/blob/main/plugins/uefi-capsule/fu-uefi-backend-freebsd.c

The same project is being done for OpenBSD as well [6]

[6]: https://www.mail-archive.com/tech%openbsd.org@localhost/msg70825.html

ESRT
----

The initial idea for accessing ESRT from userland is to use sysctl()
like so:
```
void *esrt;
size_t esrt_len;
int mib[] = { CTL_HW, HW_ESRT };
esrt_len = 0;
if (sysctl(mib, 2, NULL, &esrt_len, NULL, 0) == -1 && errno != ENOMEM)
err(1, "sysctl");esrt = malloc(esrt_len);
if (esrt == NULL)
err(1, "malloc");
if (sysctl(mib, 2, esrt, &esrt_len, NULL, 0) == -1)
err(1, "sysctl");
```

However, FreeBSD decided in favour of ioctl() on /dev/efi.

The main question is - where should the implementation of ESRT tables
go into?
Should it be generic and span multiple architectures, or should it be
limited to for example only x86?

I found out that EFI is already handled by the x86 architecture, in
`src/sys/arch/x86/x86/efi.c`. So, the implementation would probably go
there or a new file in the same location, if the decision was to reduce
the scope of this feature to a single arch.

EFI variables
-------------

I don't see an implementation of `efivar` or `efiboot` or anything
similar, so it needs to be added and provide at least this API subset
to be usable with fwupd:
* efi_append_variable() appends data of size to the variable specified
by guid and name
* efi_del_variable() deletes the variable specified by guid and name
* efi_get_variable() gets variable's data_size, and its attributes are
stored in attributes
* efi_get_variable_attributes() gets attributes for the variable
specified by guid and name
* efi_get_variable_size() gets the size of the data for the variable
specified by guid and name
* efi_get_next_variable_name() iterates across the currently extant
variables, passing back a guid and name
* efi_guid_to_name() translates from an efi_guid_t to a well known name
* efi_guid_to_symbol() translates from an efi_guid_t to a unique
(within libefivar) C-style symbol name
* efi_guid_to_str() allocates a suitable string and populates it with
string representation of a UEFI GUID
* efi_name_to_guid() translates from a well known name to an efi_guid_t
* efi_set_variable() sets the variable specified by guid and name
* efi_str_to_guid() parses a UEFI GUID from string form to an
efi_guid_t
* efi_variables_supported() checks if EFI variables are accessible
* efi_generate_file_device_path() generates an EFI file device path for
an EFI binary from a filesystem path

Probably should be implemented as a minimal port of efivar [7] with
sufficient functionality rather than a separate project. Either way,
this too needs new kernel API for accessing EFI variables. Will
sysctl() do or a new pseudo-device or is something else needed? Usage
of existing implementations can be seen in FreeBSD [8] and Linux [9]
(Linux uses sysfs for this). I also saw an implementation of a
pseudo-driver which allows operations on EFI variables [10], which
would suffice as an API, but unfortunately it wasn't merged yet. Could
it be used in our case?

[7]: https://github.com/rhboot/efivar
[8]:
https://github.com/freebsd/freebsd-src/blob/release/12.2.0/lib/libefivar/efivar.c
[9]: https://github.com/rhboot/efivar/blob/main/src/efivarfs.c
[10]:
https://github.com/NetBSD/src/commit/25ff60a647236a2f67fc08ecac96a14fecffd6f1

Expectations
------------

Please help us shape this API, so the community can be happy with it :)
The implementation is a separate topic, but please let me know if you
have any specific ideas about it right away, so as to help avoid any
unnecessary rounds of reviews.

Kind regards,
Pawel



Home | Main Index | Thread Index | Old Index