In the last few weeks, I've been working on a new solution to firmware management on the Linux desktop. A generic framework which combines fwupd and system76-firmware; with a GTK frontend library and application; that is written in Rust.
One of the remaining issues with firmware management on Linux is the lack of options for graphical frontends to firmware management services like
fwupd, the only solutions available were to distribute either GNOME Software, or KDE Discover; which is not viable for Linux distributions which have their own application centers, or frontends to package managers. For
system76-firmware, an official GTK application exists, but it only supports updating System76 firmware, when it would be more ideal if it could support both.
fwupdis a system service which connects to LVFS to check for firmware updates to a wide variety of hardware from multiple vendors.
system76-firmwareis our own system service which connects to System76 to check for firmware updates for System76 hardware.
To solve this problem, we've been working on the Firmware Manager project, which we will be shipping in both Pop!_OS and Ubuntu. It supports both
system76-firmware, is Wayland-compatible, and provides both a GTK application and GTK library. In Pop!_OS, it will be integrated into GNOME Settings in a new Firmware panel under the Devices category using the GTK library. For Ubuntu, the GTK application will be provided, rather than integrated into GNOME Settings.
Wayland disallows applications from being run as root, so applications must either call
pkexecto prompt the user for permission to run a background process that is root, or connect to an existing background service provided the needed capabilities.
Ubuntu, and other Linux distributions which would prefer to have a standalone desktop application, are free to use the included GTK application.
GNOME Settings Integration
Pop!_OS will be integrating a patch into GNOME Settings which embeds the GTK widget into a new Firmware panel in the Devices category section.
Like all of our projects today, it is written in Rust, and adheres to current best practices. The project is configured as a workspace, with the core crate providing a generic library for discovering and managing firmware from multiple firmware services. Both
system76-firmware are supported. The core is used as the foundation for the two members of this workspace: a notification binary to provide desktop notifications about firmware updates; and a GTK project which serves as both a widget library and desktop application.
Visualization of project structure
* firmware-manager * firmware-manager-notify * firmware-manager-gtk * firmware-manager-gtk-ffi
firmware-manager-gtk member of the project provides the firmware widget as a library, and an application which places that widget into a window. This member contains a C FFI sub-member, which builds a dynamic library with a C API and header, and can be used to integrate the widget into any GTK application written in C. The included GTK application statically-links the Rust widget library.
firmware-manager-notify member comes with a systemd user timer so that it is executed at login, and then periodically run again at set intervals to check for updates again. When updates are found, a clickable notification will be displayed, which will either open the Firmware panel in GNOME Settings, or the standalone desktop application, depending on which is available on the system.
firmware-manager library provides functions for scanning firmware, and an event loop which receives and sends signals through channels. This is designed to be run in a background thread to prevent a UI that uses the firmware manager from blocking as requests are being processed.
Supporting Other Frontends
Although the project will release with only a GTK frontend, it is possible for anyone to use it as the foundations for developing a frontend written in any other graphical toolkit. All functionality in the core library is GUI-agnostic, and the entity-component architecture can be extended to their specialized needs. If you write a frontend for another toolkit and want it included in the project, feel free to submit a pull request!
How to Implement Frontend Support
Frontends are expected to store information about devices in the included entity-component architecture in the
firmware-manager. Events sent to firmware manager's event loop requires the entity IDs to be sent along with messages. This makes it easier to keep cyclic references out of widget signals, and to identify which firmware a response is referring to. Widgets belonging to a specific firmware device need only send a message through their sender with their attached entity ID.