{"id":13699201,"url":"https://github.com/pop-os/firmware-manager","last_synced_at":"2025-04-04T02:07:49.742Z","repository":{"id":37385900,"uuid":"192803382","full_name":"pop-os/firmware-manager","owner":"pop-os","description":"Generic framework and GTK UI for firmware updates from system76-firmware and fwupd, written in Rust.","archived":false,"fork":false,"pushed_at":"2025-01-08T22:23:25.000Z","size":746,"stargazers_count":165,"open_issues_count":21,"forks_count":46,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-28T01:13:40.752Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pop-os.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-19T20:57:43.000Z","updated_at":"2025-03-18T14:31:58.000Z","dependencies_parsed_at":"2023-02-16T22:16:17.760Z","dependency_job_id":"a24635a2-8e42-4360-8bc2-3cb961533f1a","html_url":"https://github.com/pop-os/firmware-manager","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pop-os%2Ffirmware-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pop-os%2Ffirmware-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pop-os%2Ffirmware-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pop-os%2Ffirmware-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pop-os","download_url":"https://codeload.github.com/pop-os/firmware-manager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247107828,"owners_count":20884797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T20:00:19.847Z","updated_at":"2025-04-04T02:07:49.711Z","avatar_url":"https://github.com/pop-os.png","language":"Rust","funding_links":[],"categories":["Firmware Tools, Libraries, and Frameworks","Rust"],"sub_categories":[],"readme":"# Firmware Manager\n\nOne of the remaining issues with firmware management on Linux is the lack of options for graphical frontends to firmware management services like `fwupd` and `system76-firmware`. For `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 updating firmware from both services.\n\n\u003e `fwupd` is a system service which connects to [LVFS] to check for firmware updates to a wide variety of hardware from multiple vendors. `system76-firmware` is our own system service which connects to System76 to check for firmware updates for System76 hardware.\n\u003e\n\u003e **Privacy**\n\u003e\n\u003e To increase privacy, we have disabled telemetry reporting in fwupd on Pop!_OS.\n\nTo solve this problem, we've been working on the [Firmware Manager] project, which we will be shipping to all Pop!_OS users, and System76 hardware customers on any other distribution. It supports checking and updating firmware from the `fwupd` and `system76-firmware` services, is Wayland-compatible, and provides both a GTK application and library.\n\n\u003e Wayland disallows applications from being run as root, so applications must either call `pkexec` to prompt the user for permission to run a background process that is root, or connect to an existing background service provided the needed capabilities.\n\nIn Pop!_OS, the firmware manager will be integrated into GNOME Settings in a new **Firmware** panel under the **Devices** category with the GTK widget library. For other Linux distributions, and for those who do not use GNOME, the GTK application is available to provide the firmware manager widget as a standalone application in its own application window.\n\nAlthough we've created a GTK application and widget library for our use in Pop!_OS, the core framework is toolkit-agnostic, thereby enabling firmware manager frontends to be written in any toolkit. However, it should be noted that since the framework is written in Rust, frontends would need to use Rust in order to interact with it.\n\n[firmware manager]: https://github.com/pop-os/firmware-manager\n[lvfs]: https://fwupd.org/\n\n## GTK Application\n\nUbuntu, and other Linux distributions which would prefer to have a standalone desktop application, are free to use the included GTK application.\n\n![Screenshot of GTK Application](screenshots/gtk.png)\n\n\n## GNOME Settings Integration\n\nPop!_OS will be integrating a patch into GNOME Settings which embeds the GTK widget into a new **Firmware** panel in the **Devices** category section.\n\n![Screenshot of GNOME Settings Integration](screenshots/gnome-settings.png)\n\n## Distributing Firmware Manager\n\nWhen packaging the firmware manager with the GTK frontend, the only dependencies required are `libdbus`, `libgtk`, `libssl`, and `libudev`. The firmware manager uses DBus to communicate with the `system76-firmware` and `fwupd` daemons. Both of which are optional and do not need to be installed in order to use or compile the project. The firmware manager has an initial check for the existence of either daemon. If no daemon is installed, no firmware will be found. If one daemon is installed, then it will discover firmware managed by that service, if managed firmware is found on the system.\n\n As it is written in [Rust], Rustc and its Cargo counterpart are required to compile the project. The [rust-toolchain file] in the root directory of the source repository defines the minimum-supported version of the compiler. We will always depend on a version of Rust that is packaged in the most recent LTS of Ubuntu. [You can check what Ubuntu supports here].\n\nTo package the project so that it can be built offline in a schroot, there is a `make vendor` rule which uses the official `cargo-vendor` utility to fetch all crate dependencies locally, and then generates a tarball which can be distributed in or alongside your source packages. You can then instruct the makefile to build the project with the vendored dependencies by setting `VENDOR=1`, like so: `make VENDOR=1 prefix=/usr`.\n\n\u003e If your version of Cargo does not have the `cargo-vendor` feature, [you can install cargo-vendor separately here].\n\nFor any unfamiliar with Rust, crates are modules of source code with specific functionality that can be massively distributed through public registries like [Crates.io], or fetched directly by URL. They are statically-linked when used in a project which builds a library or binary. For applications, Cargo generates a [Cargo.lock file] which specifies the exact version of every crate that is depended on, and their SHA256 sums. This is to ensure that anyone pulling the project will have the same versions for crate dependencies as used by upstream.\n\n[rust]: https://www.rust-lang.org/\n[rust-toolchain file]: ./rust-toolchain\n[cargo.lock file]: ./Cargo.lock\n[crates.io]: https://crates.io\n[You can check what Ubuntu supports here]: https://packages.ubuntu.com/search?keywords=rustc\n[you can install cargo-vendor separately here]: https://github.com/alexcrichton/cargo-vendor\n\n## Implementation Details\n\nLike 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 `fwupd` and `system76-firmware` are supported.\n\nThe 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.\n\n**Visualization of project structure**\n\n```\n* firmware-manager\n    * firmware-manager-notify\n    * firmware-manager-gtk\n        * firmware-manager-gtk-ffi\n```\n\n### Core Library\n\nThe `firmware-manager` library provides functions for scanning firmware, and an event loop which receives and sends event signals through channels. One channel receives messages from the frontend, whereas the other sends messages to the frontend. This is designed to be run in a background thread in order to prevent a UI that uses the firmware manager from blocking as requests are being processed.\n\nAdditionally, the event API is expected to be used with the provided `slotmap`-based entity-component architecture. This allows a frontend to assign entity IDs to their requests, and receive those entity IDs back in responses. In doing so, frontends can avoid the need for complex runtime reference-counting, or creating reference cycles. The frontend has exclusive ownership of the data that an entity ID refers to.\n\n### GTK Application / Library\n\nThe `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.\n\nThis implementation takes full advantage of the slotmap EC, assigning its own component storages to keep track of state relative to a device entity, such as the widgets assigned to an entity, and information about their firmware.\n\n\u003e The included GTK application statically-links the Rust widget library into the binary.\n\n### Notification Binary\n\nThe `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.\n\n## Supporting Other Frontends\n\nAlthough 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!\n\n## How to Implement Frontend Support\n\nFrontends 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.\n\n## Build Instructions\n\nThis project uses a Makefile. When building the application, the `prefix` flag must be provided, so that the desktop entry file is generated to point to the correct path of the target binary after installation.\n\n```sh\nmake prefix=/usr\nsudo make install prefix=/usr\n```\n\nNote that the generated desktop entry is stored in the `target` directory, where the `pkgconfig` file is also stored after it is generated. If you need to regenerate the desktop entry with a different prefix, you can manually call the `desktop` rule.\n\n```\nmake desktop prefix=/usr\n```\n\n### Debug Binaries\n\nTo build a debug binary, pass `DEBUG=1` into make.\n\n```sh\nmake prefix=/usr DEBUG=1\nsudo make install DEBUG=1\n```\n\n### Vendoring\n\nTo vendor the project for packaging, call `make vendor`. To build a project that has been vendored, pass `VENDOR=1` to the makefile.\n\n```sh\nmake vendor\nmake prefix=/usr VENDOR=1\n```\n\n## API Overview\n\nThis section provides details about the API and how to call it from Rust or C.\n\n### Rust API\n\nThe primary API, which the C API is based upon. An example of the Rust API in practice in a GTK application can be found [here](./src/main.rs).\n\n```rust\nuse firmware_manager_gtk::FirmwareWidget;\n\n// Create a new firmware widget\n//\n// This spawns a background thread which listens for widget events until\n// the `Quit` signal is received, which occurs when the firmware widget\n// is dropped.\nlet mut firmware = FirmwareWidget::new();\n\n// Signal the widget's background thread to begin scanning for firmware.\nfirmware.scan();\n\n// Get the GTK widget from the firmware widget to add into a window.\nlet widget = firmware.container();\n```\n\n### C API\n\nThe Rust library also supports C interface with FFI rules in the Makefile for generating a dynamic C library with `pkg-config` support. This is integrated in GNOME Settings on Pop!_OS.\n\n```sh\nmake ffi prefix=/usr\nsudo make install-ffi prefix=/usr\n```\n\nWhich can then be imported into a C code base with:\n\n```c\n#include \u003cs76_firmware.h\u003e\n\n// Create a new firmware widget\nS76FirmwareWidget *firmware =\n    s76_firmware_widget_new ();\n\n// Signal the widget's background thread to begin scanning for firmware.\ns76_firmware_widget_scan (firmware);\n\n// Get the GTK widget from the firmware widget to attach it to a container.\nGtkWidget *firmware_widget =\n    s76_firmware_widget_container (firmware);\n\n// Destroy the widget and signal its background thread to quit.\ns76_firmware_widget_destroy (firmware);\n```\n\nThe C implementation of the Rust application is [here](./gtk/ffi/examples/c), demonstrated with the Meson build system.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpop-os%2Ffirmware-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpop-os%2Ffirmware-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpop-os%2Ffirmware-manager/lists"}