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 something else is 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,
Paweł


Home | Main Index | Thread Index | Old Index