Release fwupd 1.5.1

-----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEEFj61ARkiXbPfj0nqF6y6jfqXDhcFAl+gHTsUHHJpY2hhcmRA
 aHVnaHNpZS5jb20ACgkQF6y6jfqXDhfxbQgAsN8WqqKcO1jb6E/ILQinfIIB9DYT
 t9p+7f9XrDtB8XAlUyvRF2UOQblLIYkzDRnUwozz3qxWPhpredeOPN/aJTHfk+qJ
 f/IsBhkPQX/ai1T62iEp0DLBlnrdWAk8RU1ZWxcQtUgnt+WoZQYIg7cDdzgbjLa2
 0KW8nl6q8oXAssyxnBa/oBdGUE9r6WehfYPAPvanoFtXCtMLJYGha51DbxvbWe9M
 5dNv4skG2vS+BoZaxPGgRqjFaOYLfApPR3lTxlfTyGF7ukQi0q7q8lyLfVrXqq1Z
 elqwiSeDdR//bW8bsj3d83o93nq7AtPtWuw9LX2HseDY9TFbnOSqxOZrHg==
 =AVqs
 -----END PGP SIGNATURE-----

New upstream version (1.5.1)
This commit is contained in:
Mario Limonciello 2020-11-13 09:42:26 -06:00
commit 79d8b60fe7
514 changed files with 38048 additions and 5951 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
end_of_line = lf
[*.py]
indent_style = space
indent_size = 4
[*.{c|h}]
indent_style = tab
indent_size = 8

View File

@ -0,0 +1,64 @@
---
name: Bug report (Dell WD19)
about: Create a report to help us improve
title: 'Dell WD19 upgrade issue'
labels: bug
assignees: 'superm1'
---
**Describe the bug**
A clear and concise description of what the bug is.
**Steps to Reproduce**
Steps to reproduce the behavior.
**Expected behavior**
A clear and concise description of what you expected to happen.
**fwupd version information**
Please provide the version of the daemon and client.
```shell
$ fwupdmgr --version
```
Please note how you installed it (`apt`, `dnf`, `pacman`, source, etc):
**fwupd device information**
Please provide the output of the external fwupd devices recognized in your system.
```shell
$ fwupdmgr get-devices --filter=~internal
```
**Dock SKU**
Please mention which module is installed in your WD19.
- [ ] WD19 (Single-C)
- [ ] WD19TB (Thunderbolt)
- [ ] WD19DC (Dual-C)
**Peripherals connected to the dock**
Please describe all devices connected to the dock. Be as specific as possible,
including USB devices, hubs, monitors, and downstream type-C devices.
**Verbose daemon logs**
First enable daemon verbose logs collection.
```shell
fwupdmgr modify-config "VerboseDomains" "*"
```
Then try to reproduce the issue. Even if it doesn't reproduce, please attach the
daemon verbose logs collected from the system journal.
```shell
journalctl -b -u fwupd.service
```
**Additional questions**
- Operating system and version:
- Have you tried unplugging the dock or any peripherals from your machine?
- Have you tried to power cycle the dock from the AC adapter?
- Is this a regression?

9
.gitignore vendored
View File

@ -21,3 +21,12 @@
/*.xz
/*.gz
__pycache__
plugins/acpi-dmar/tests/
plugins/acpi-facp/tests/
plugins/ata/tests/
plugins/dfu/tests/
plugins/nvme/tests/
plugins/synaptics-mst/tests/
plugins/synaptics-prometheus/tests/
plugins/tpm-eventlog/tests/
plugins/uefi-dbx/tests/

View File

@ -78,7 +78,7 @@ Enterprise use
The flow of updates can be controlled in the enterprise using the
"approved updates" feature. This allows the domain administrator to filter
the possible updates from a central server (e.g. the LVFS, or a mirror)
to only firmware that have been tested specifically in your organisation.
to only firmware that have been tested specifically in your organization.
The list of approved updates can be enabled by adding `ApprovalRequired=true`
to the remote configuration file, e.g. `lvfs.conf`. Once enabled, the
@ -103,7 +103,7 @@ Other frontends
After the firmware has been downloaded a popup will be displayed in GNOME
Software to perform the update.
2. [KDE Discover](https://userbase.kde.org/Discover) is the software centre,
2. [KDE Discover](https://userbase.kde.org/Discover) is the software center,
generally bundled with KDE Plasma. With the release of
[KDE Plasma 5.14](https://www.kde.org/announcements/plasma-5.14.0.php),
a new fwupd backend has been implemented in KDE Discover for firmware updates.
@ -125,3 +125,4 @@ There are several automated fuzzing tests in fwupd. These take some time to run:
ninja fuzz-synaptics-rmi
ninja fuzz-firmware
ninja fuzz-smbios
ninja fuzz-efidbx

12
RELEASE
View File

@ -2,14 +2,22 @@ fwupd Release Notes
Write release entries:
git log --format="%s" --cherry-pick --right-only 1.4.5... | grep -i -v trivial | grep -v Merge | sort | uniq
git log --format="%s" --cherry-pick --right-only 1.5.0... | grep -i -v trivial | grep -v Merge | sort | uniq
Add any user visible changes into ../data/org.freedesktop.fwupd.metainfo.xml
appstream-util appdata-to-news ../data/org.freedesktop.fwupd.metainfo.xml > NEWS
Update translations:
ninja-build fwupd-pot
tx push --source
tx pull --all --force --minimum-perc=5
ninja-build fix-translations
git add ../po/*.po
2. Commit changes to git:
# MAKE SURE THIS IS CORRECT
export release_ver="1.4.6"
export release_ver="1.5.1"
git commit -a -m "Release fwupd ${release_ver}"
git tag -s -f -m "Release fwupd ${release_ver}" "${release_ver}"

View File

@ -31,5 +31,5 @@ this repository.
Failing that, please report the issue against the `fwupd` component in Red Hat
bugzilla, with the security checkbox set. You should get a response within 3
days. We have no bug bountry program, but we're happy to credit you in updates
days. We have no bug bounty program, but we're happy to credit you in updates
if this is what you would like us to do.

View File

@ -2,6 +2,7 @@ FROM archlinux/base
%%%OS%%%
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV CI_NETWORK true
RUN echo fubar > /etc/machine-id
RUN rm /usr/share/libalpm/hooks/package-cleanup.hook
RUN echo fubar > /etc/machine-id

View File

@ -1,5 +1,6 @@
FROM %%%ARCH_PREFIX%%%debian:testing
%%%OS%%%
ENV CI_NETWORK true
RUN echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" >> /etc/apt/sources.list
RUN echo 'Package: *\n\
Pin: release a=testing\n\

View File

@ -1,5 +1,6 @@
FROM ubuntu:devel
%%%OS%%%
ENV CI_NETWORK true
ENV CC clang
RUN echo fubar > /etc/machine-id
%%%ARCH_SPECIFIC_COMMAND%%%

View File

@ -3,6 +3,12 @@ set -e
set -x
shopt -s extglob
#clone test firmware
if [ "$CI_NETWORK" = "true" ]; then
./contrib/ci/get_test_firmware.sh
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests
fi
# prepare the build tree
rm -rf build
mkdir build && pushd build
@ -13,8 +19,8 @@ popd
chown nobody . -R
# install and run TPM simulator necessary for plugins/uefi/uefi-self-test
pacman -S --noconfirm ibm-sw-tpm2 tpm2-tools
tpm_server &
pacman -S --noconfirm swtpm tpm2-tools
swtpm socket --tpm2 --server port=2321 --ctrl type=tcp,port=2322 --flags not-need-init --tpmstate "dir=$PWD" &
trap "kill $!" EXIT
# extend a PCR0 value for test suite
sleep 2

View File

@ -15,6 +15,7 @@ meson .. \
--libexecdir=$target \
--bindir=$target \
-Dbuild=standalone \
-Dpolkit=false \
-Dplugin_coreboot=false \
-Dplugin_flashrom=false \
-Dplugin_uefi=false \
@ -22,7 +23,7 @@ meson .. \
-Dplugin_altos=false \
-Dplugin_dell=false \
-Dplugin_nvme=false \
-Dplugin_tpm=false \
-Dtpm=false \
-Dsystemd=false \
-Dplugin_emmc=false \
-Dplugin_amt=false \
@ -40,6 +41,10 @@ meson .. \
-Dlibjcat:man=false \
-Dlibjcat:gpg=false \
-Dlibjcat:introspection=false \
-Dgusb:tests=false \
-Dgusb:docs=false \
-Dgusb:introspection=false \
-Dgusb:vapi=false \
-Dgudev=false $@
VERSION=$(meson introspect . --projectinfo | jq -r .version)
ninja -v

View File

@ -2,6 +2,13 @@
set -e
set -x
#clone test firmware
if [ "$CI_NETWORK" = "true" ]; then
./contrib/ci/get_test_firmware.sh
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests
fi
#build
rm -rf build
mkdir -p build
cd build

View File

@ -2,6 +2,9 @@
set -e
set -x
# remove when tpm2-tss is fixed
mkdir -p /usr/include/tss
#although it's debian, we don't build packages
if [ "$OS" = "debian-s390x" ]; then
./contrib/ci/debian_s390x.sh
@ -23,6 +26,20 @@ sed s/quilt/native/ debian/source/format -i
#generate control file
./contrib/ci/generate_debian.py
#check if we have all deps available
#if some are missing, we're going to use subproject instead and
#packaging CI will fail
if ! dpkg-checkbuilddeps; then
./contrib/ci/ubuntu.sh
exit 0
fi
#clone test firmware
if [ "$CI_NETWORK" = "true" ]; then
./contrib/ci/get_test_firmware.sh
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests
fi
#disable unit tests if fwupd is already installed (may cause problems)
if [ -x /usr/lib/fwupd/fwupd ]; then
export DEB_BUILD_OPTIONS=nocheck

View File

@ -20,6 +20,7 @@ meson .. \
-Dplugin_uefi=false \
-Dplugin_dell=false \
-Dplugin_modem_manager=false \
-Dplugin_msr=false \
-Dplugin_redfish=false \
-Dintrospection=false \
-Dgtkdoc=false \

View File

@ -766,7 +766,7 @@
</distro>
<distro id="debian">
<control>
<version>(>= 0.2.9)</version>
<version>(>= 0.3.5)</version>
</control>
<package variant="x86_64" />
<package variant="s390x">libgusb-dev:s390x</package>
@ -774,7 +774,7 @@
</distro>
<distro id="ubuntu">
<control>
<version>(>= 0.2.9)</version>
<version>(>= 0.3.3)</version>
</control>
<package variant="x86_64" />
</distro>

View File

@ -54,7 +54,7 @@ mkdir -p dist
cp $HOME/rpmbuild/RPMS/*/*.rpm dist
if [ "$CI" = "true" ]; then
sed "s,^BlacklistPlugins=test;invalid,BlacklistPlugins=," -i /etc/fwupd/daemon.conf
sed "s,^DisabledPlugins=test;invalid,DisabledPlugins=," -i /etc/fwupd/daemon.conf
# set up enough PolicyKit and D-Bus to run the daemon
mkdir -p /run/dbus

View File

@ -0,0 +1,8 @@
#!/bin/sh
#clone fwupd-test-firmware
rm -rf fwupd-test-firmware
git clone https://github.com/fwupd/fwupd-test-firmware
#set up build tests to work
cp fwupd-test-firmware/ci-tests/* . -R
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests

View File

@ -2,14 +2,21 @@
set -e
set -x
#clone test firmware
if [ "$CI_NETWORK" = "true" ]; then
./contrib/ci/get_test_firmware.sh
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests
fi
# Builds using GPG and PKCS7 turned off to make
# sure no assumptions of a trust backend
rm -rf build
meson build \
-Dman=false \
-Ddaemon=false \
-Ddaemon=true \
-Dpolkit=false \
-Dgusb:tests=false \
-Dplugin_tpm=false \
-Dtpm=false \
-Dplugin_modem_manager=false \
-Dplugin_flashrom=false \
-Dplugin_uefi=false \

View File

@ -2,7 +2,14 @@
set -e
set -x
#clone test firmware
if [ "$CI_NETWORK" = "true" ]; then
./contrib/ci/get_test_firmware.sh
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests
fi
#evaluate using Ubuntu's buildflags
#evaluate using Debian/Ubuntu's buildflags
eval "$(dpkg-buildflags --export=sh)"
#filter out -Bsymbolic-functions
export LDFLAGS=$(dpkg-buildflags --get LDFLAGS | sed "s/-Wl,-Bsymbolic-functions\s//")

View File

@ -1,6 +1,6 @@
#!/usr/bin/python3
#
# Copyright (C) 2017 Max Ehrlich max.ehr@gmail.com
# Copyright (C) 2017 Max Ehrlich maxehr@gmail.com
#
# SPDX-License-Identifier: LGPL-2.1+
#
@ -107,7 +107,7 @@ def main(args):
print('Creating metainfo')
make_firmware_metainfo(args, dir)
print('Cabbing firmware files')
print('Creating cabinet file')
create_firmware_cab(args, dir)
print('Done')

View File

@ -1,6 +1,6 @@
%global glib2_version 2.45.8
%global libxmlb_version 0.1.3
%global libgusb_version 0.2.11
%global libgusb_version 0.3.5
%global libsoup_version 2.51.92
%global libjcat_version 0.1.0
%global systemd_version 231
@ -22,6 +22,15 @@
%global have_uefi 1
%endif
# flashrom is only available on these arches
%ifarch i686 x86_64 armv7hl aarch64 ppc64le
%global have_flashrom 1
%endif
%ifarch i686 x86_64
%global have_msr 1
%endif
# redfish is only available on this arch
%ifarch x86_64
%global have_redfish 1
@ -73,7 +82,9 @@ BuildRequires: json-glib-devel >= %{json_glib_version}
BuildRequires: vala
BuildRequires: bash-completion
BuildRequires: git-core
%if 0%{?have_flashrom}
BuildRequires: flashrom-devel >= 1.2-2
%endif
%if 0%{?have_modem_manager}
BuildRequires: ModemManager-glib-devel >= 1.10.0
@ -133,6 +144,14 @@ Provides: fwupdate
Provides: fwupdate-efi
%endif
# optional, but a really good idea
%if 0%{?have_modem_manager}
Recommends: %{name}-plugin-modem-manager
%endif
%if 0%{?have_flashrom}
Recommends: %{name}-plugin-flashrom
%endif
%description
fwupd is a daemon to allow session software to update device firmware.
@ -147,11 +166,28 @@ Files for development with %{name}.
%package tests
Summary: Data files for installed tests
BuildArch: noarch
%description tests
Data files for installed tests.
%if 0%{?have_modem_manager}
%package plugin-modem-manager
Summary: fwupd plugin using ModemManger
%description plugin-modem-manager
This provides the optional package which is only required on hardware that
might have mobile broadband hardware. It is probably not required on servers.
%endif
%if 0%{?have_flashrom}
%package plugin-flashrom
Summary: fwupd plugin using flashrom
%description plugin-flashrom
This provides the optional package which is only required on hardware that
can be flashed using flashrom. It is probably not required on servers.
%endif
%prep
%autosetup -p1
@ -172,7 +208,16 @@ Data files for installed tests.
%else
-Dplugin_dummy=false \
%endif
%if 0%{?have_flashrom}
-Dplugin_flashrom=true \
%else
-Dplugin_flashrom=false \
%endif
%if 0%{?have_msr}
-Dplugin_msr=true \
%else
-Dplugin_msr=false \
%endif
-Dplugin_thunderbolt=true \
%if 0%{?have_redfish}
-Dplugin_redfish=true \
@ -182,11 +227,11 @@ Data files for installed tests.
%if 0%{?have_uefi}
-Dplugin_uefi=true \
-Dplugin_nvme=true \
-Dplugin_tpm=true \
-Dtpm=true \
%else
-Dplugin_uefi=false \
-Dplugin_nvme=false \
-Dplugin_tpm=false \
-Dtpm=false \
%endif
%if 0%{?have_dell}
-Dplugin_dell=true \
@ -205,6 +250,9 @@ Data files for installed tests.
%meson_build
%if 0%{?enable_tests}
%if 0%{?enable_ci}
./contrib/ci/get_test_firmware.sh
%endif
%check
%meson_test
%endif
@ -256,6 +304,9 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%config(noreplace)%{_sysconfdir}/fwupd/thunderbolt.conf
%dir %{_libexecdir}/fwupd
%{_libexecdir}/fwupd/fwupd
%ifarch i686 x86_64
%{_libexecdir}/fwupd/fwupd-detect-cet
%endif
%{_libexecdir}/fwupd/fwupdoffline
%if 0%{?have_uefi}
%{_libexecdir}/fwupd/efi/*.efi
@ -281,6 +332,10 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%config(noreplace)%{_sysconfdir}/fwupd/remotes.d/vendor-directory.conf
%config(noreplace)%{_sysconfdir}/pki/fwupd
%{_sysconfdir}/pki/fwupd-metadata
%if 0%{?have_msr}
%{_sysconfdir}/modules-load.d/fwupd-msr.conf
%endif
%{_sysconfdir}/modules-load.d/fwupd-platform-integrity.conf
%{_datadir}/dbus-1/system.d/org.freedesktop.fwupd.conf
%{_datadir}/bash-completion/completions/fwupdmgr
%{_datadir}/bash-completion/completions/fwupdtool
@ -328,12 +383,17 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
/usr/lib/udev/rules.d/*.rules
/usr/lib/systemd/system-shutdown/fwupd.shutdown
%dir %{_libdir}/fwupd-plugins-3
%{_libdir}/fwupd-plugins-3/libfu_plugin_acpi_dmar.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_acpi_facp.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_altos.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_amt.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_ata.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_bcm57xx.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_bios.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_ccgx.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_colorhug.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_coreboot.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_cros_ec.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_csr.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_cpu.so
%if 0%{?have_dell}
@ -343,20 +403,28 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%{_libdir}/fwupd-plugins-3/libfu_plugin_dell_dock.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_dfu.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_ebitdo.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_elantp.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_emmc.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_ep963x.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_fastboot.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_flashrom.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_fresco_pd.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_iommu.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_jabra.so
%if 0%{?have_modem_manager}
%{_libdir}/fwupd-plugins-3/libfu_plugin_modem_manager.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_lockdown.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_sleep.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_swap.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_tainted.so
%if 0%{?have_msr}
%{_libdir}/fwupd-plugins-3/libfu_plugin_msr.so
%endif
%{_libdir}/fwupd-plugins-3/libfu_plugin_nitrokey.so
%if 0%{?have_uefi}
%{_libdir}/fwupd-plugins-3/libfu_plugin_nvme.so
%endif
%{_libdir}/fwupd-plugins-3/libfu_plugin_optionrom.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_pci_bcr.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_pci_mei.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_platform_integrity.so
%if 0%{?have_redfish}
%{_libdir}/fwupd-plugins-3/libfu_plugin_redfish.so
%endif
@ -390,11 +458,21 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%{_libdir}/fwupd-plugins-3/libfu_plugin_vli.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_wacom_raw.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_wacom_usb.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_goodixmoc.so
%ghost %{_localstatedir}/lib/fwupd/gnupg
%if 0%{?have_uefi}
%{_datadir}/locale/*/LC_IMAGES/fwupd*
%endif
%if 0%{?have_modem_manager}
%files plugin-modem-manager
%{_libdir}/fwupd-plugins-3/libfu_plugin_modem_manager.so
%endif
%if 0%{?have_flashrom}
%files plugin-flashrom
%{_libdir}/fwupd-plugins-3/libfu_plugin_flashrom.so
%endif
%files devel
%{_datadir}/gir-1.0/Fwupd-2.0.gir
%{_datadir}/gir-1.0/FwupdPlugin-1.0.gir
@ -405,14 +483,17 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%{_libdir}/pkgconfig/fwupd.pc
%{_libdir}/pkgconfig/fwupdplugin.pc
%if 0%{?enable_tests}
%files tests
%dir %{_datadir}/installed-tests/fwupd
%{_datadir}/installed-tests/fwupd/fwupd-tests.xml
%{_datadir}/installed-tests/fwupd/*.test
%{_datadir}/installed-tests/fwupd/*.cab
%{_datadir}/installed-tests/fwupd/*.sh
%{_libexecdir}/installed-tests/fwupd/*
%dir %{_sysconfdir}/fwupd/remotes.d
%config(noreplace)%{_sysconfdir}/fwupd/remotes.d/fwupd-tests.conf
%endif
%changelog
* #LONGDATE# Richard Hughes <richard@hughsie.com> #VERSION#-0.#BUILD##ALPHATAG#

View File

@ -4,23 +4,5 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# VIA USB 3.0 VL811 Hub
SUBSYSTEM=="usb", DRIVER=="hub", ATTRS{idVendor}=="2109", ATTRS{idProduct}=="0810", ENV{FWUPD_GUID}="adbb9034-b577-42c2-a661-1ee4f49ef64c", ENV{FWUPD_VENDOR}="VIA", ENV{FWUPD_MODEL}="USB 3.0 VL811 Hub"
# VIA USB 3.0 VL811+ Hub
SUBSYSTEM=="usb", DRIVER=="hub", ATTRS{idVendor}=="2109", ATTRS{idProduct}=="0811", ENV{FWUPD_GUID}="54f84d05-c917-4c50-8b35-44feabaaa323", ENV{FWUPD_VENDOR}="VIA", ENV{FWUPD_MODEL}="USB 3.0 VL811+ Hub"
# VIA USB 3.0 VL812 Hub
SUBSYSTEM=="usb", DRIVER=="hub", ATTRS{idVendor}=="2109", ATTRS{idProduct}=="0812", ENV{FWUPD_GUID}="cd0314ec-b80f-4d1a-a24f-c409183a8b2d", ENV{FWUPD_VENDOR}="VIA", ENV{FWUPD_MODEL}="USB 3.0 VL812 Hub"
# VIA USB 3.0 VL812 B2 Hub
SUBSYSTEM=="usb", DRIVER=="hub", ATTRS{idVendor}=="2109", ATTRS{idProduct}=="2812", ENV{FWUPD_GUID}="26470009-97a8-4028-867a-bbbac6ee7bf0", ENV{FWUPD_VENDOR}="VIA", ENV{FWUPD_MODEL}="USB 3.0 VL812 B2 Hub"
ENV{FWUPD_GUID}=="*?", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id"
ENV{FWUPD_GUID}=="*?", ENV{ID_MODEL_FROM_DATABASE}=="", IMPORT{builtin}="hwdb --subsystem=usb"
# PCI cards with ROM
SUBSYSTEM=="pci", TEST=="/sys$devpath/rom", ENV{FWUPD_GUID}="$attr{vendor}:$attr{device}"
# NVMe hardware
SUBSYSTEM=="nvme", ENV{ID_VENDOR_FROM_DATABASE}=="", IMPORT{builtin}="hwdb --subsystem=pci"

View File

@ -2,6 +2,7 @@ _fwupdagent_cmd_list=(
'get-devices'
'get-updates'
'get-upgrades'
'security'
)
_fwupdagent_opts=(

View File

@ -18,13 +18,16 @@ _fwupdmgr_cmd_list=(
'get-topology'
'get-updates'
'get-upgrades'
'get-plugins'
'install'
'modify-config'
'modify-remote'
'reinstall'
'refresh'
'report-history'
'security'
'set-approved-firmware'
'switch-branch'
'unlock'
'unblock-firmware'
'update'
@ -39,6 +42,7 @@ _fwupdmgr_opts=(
'--offline'
'--allow-reinstall'
'--allow-older'
'--allow-branch-switch'
'--force'
'--assume-yes'
'--no-history'
@ -46,10 +50,11 @@ _fwupdmgr_opts=(
'--no-metadata-check'
'--no-reboot-check'
'--no-safety-check'
'--show-all-devices'
'--show-all'
'--sign'
'--filter'
'--disable-ssl-strict'
'--ignore-power'
)
_show_filters()
@ -97,7 +102,7 @@ _fwupdmgr()
esac
case $command in
activate|clear-results|downgrade|get-releases|get-results|unlock|verify|verify-update)
activate|clear-results|downgrade|get-releases|get-results|unlock|verify|verify-update|get-updates|switch-branch)
if [[ "$prev" = "$command" ]]; then
_show_device_ids
else

View File

@ -4,7 +4,9 @@ _fwupdtool_cmd_list=(
'esp-list'
'esp-mount'
'esp-unmount'
'firmware-build'
'firmware-convert'
'firmware-extract'
'firmware-parse'
'get-updates'
'get-upgrades'
@ -23,14 +25,18 @@ _fwupdtool_cmd_list=(
'install-blob'
'monitor'
'reinstall'
'security'
'switch-branch'
'self-sign'
'smbios-dump'
'attach'
'detach'
'firmware-read'
'firmware-dump'
'refresh'
'verify-update'
'watch'
'unbind-driver'
'bind-driver'
)
_fwupdtool_opts=(
@ -39,13 +45,16 @@ _fwupdtool_opts=(
'--allow-reinstall'
'--allow-older'
'--force'
'--show-all-devices'
'--plugin-whitelist'
'--show-all'
'--plugins'
'--prepare'
'--cleanup'
'--filter'
'--disable-ssl-strict'
'--no-safety-check'
'--ignore-checksum'
'--ignore-vid-pid'
'--ignore-power'
)
_show_filters()
@ -84,7 +93,7 @@ _fwupdtool()
command=${COMP_WORDS[1]}
case $prev in
--plugin-whitelist)
--plugins)
_show_plugins
return 0
;;
@ -95,7 +104,7 @@ _fwupdtool()
esac
case $command in
get-details|install|install-blob|firmware-read)
get-details|install|install-blob|firmware-dump)
#find files
if [[ "$prev" = "$command" ]]; then
_filedir
@ -104,7 +113,7 @@ _fwupdtool()
_show_modifiers
fi
;;
attach|detach|activate|verify-update|reinstall)
attach|detach|activate|verify-update|reinstall|get-updates)
if [[ "$prev" = "$command" ]]; then
_show_device_ids
#modifiers

View File

@ -1,12 +1,12 @@
[fwupd]
# Allow blacklisting specific devices by their GUID
# Allow blocking specific devices by their GUID
# Uses semicolons as delimiter
BlacklistDevices=
DisabledDevices=
# Allow blacklisting specific plugins
# Allow blocking specific plugins
# Uses semicolons as delimiter
BlacklistPlugins=test;invalid
DisabledPlugins=test;invalid
# Maximum archive size that can be loaded in Mb, with 0 for the default
ArchiveSizeMax=0

View File

@ -0,0 +1,12 @@
{
"name": "NetXtreme BCM5719",
"guids": [
"ec5b8a9e-973b-58cc-935b-8322fabaebe9"
],
"releases": [
{
"version": "0.4.44",
"file": "dfbb6529d3f7051497cc7e736848b5b6e276ff93b39bc765948663606dc87c25-bcm5719-0.4.44.cab"
}
]
}

View File

@ -0,0 +1,16 @@
{
"name": "Lenovo USB-C Mini Dock [VL817]",
"guids": [
"f281c1df-c3d5-5f8a-984d-e9548ffc95fe"
],
"releases": [
{
"version": "4.154",
"file": "c782946a9cf743abc37edefe35dec1b8b2d2a88b29f7058091b0a7ae3fa38e49-Lenovo-Mini_Dock_New.cab"
},
{
"version": "4.94",
"file": "39da9917934ce162baefa3a67adfccd338bfd054933d6c40c0c887ab0d48e83f-Lenovo-Mini_Dock_Old.cab"
}
]
}

View File

@ -0,0 +1,16 @@
{
"name": "Lenovo USB-C Mini Dock [VL211]",
"guids": [
"d636c717-44c4-5fcf-9d7f-b96f9c5f6608"
],
"releases": [
{
"version": "4.43",
"file": "c782946a9cf743abc37edefe35dec1b8b2d2a88b29f7058091b0a7ae3fa38e49-Lenovo-Mini_Dock_New.cab"
},
{
"version": "4.33",
"file": "39da9917934ce162baefa3a67adfccd338bfd054933d6c40c0c887ab0d48e83f-Lenovo-Mini_Dock_Old.cab"
}
]
}

View File

@ -0,0 +1,16 @@
{
"name": "Lenovo USB-C Mini Dock [VL103]",
"guids": [
"3ae6610b-5c33-5714-96e3-05735eb9b2a5"
],
"releases": [
{
"version": "138.4.24.38",
"file": "c782946a9cf743abc37edefe35dec1b8b2d2a88b29f7058091b0a7ae3fa38e49-Lenovo-Mini_Dock_New.cab"
},
{
"version": "138.4.23.38",
"file": "39da9917934ce162baefa3a67adfccd338bfd054933d6c40c0c887ab0d48e83f-Lenovo-Mini_Dock_Old.cab"
}
]
}

View File

@ -18,7 +18,8 @@ complete -c fwupdmgr -l version -d 'Show client and daemon versions'
complete -c fwupdmgr -l offline -d 'Schedule installation for next reboot when possible'
complete -c fwupdmgr -l allow-reinstall -d 'Allow reinstalling existing firmware versions'
complete -c fwupdmgr -l allow-older -d 'Allow downgrading firmware versions'
complete -c fwupdmgr -l force -d 'Override warnings and force the action'
complete -c fwupdmgr -l allow-branch-switch -d 'Allow switching firmware branch'
complete -c fwupdmgr -l force -d 'Force the action by relaxing some runtime checks'
complete -c fwupdmgr -s y -l assume-yes -d 'Answer yes to all questions'
complete -c fwupdmgr -l sign -d 'Sign the uploaded data with the client certificate'
complete -c fwupdmgr -l no-unreported-check -d 'Do not check for unreported history'
@ -26,12 +27,14 @@ complete -c fwupdmgr -l no-metadata-check -d 'Do not check for old metadata'
complete -c fwupdmgr -l no-reboot-check -d 'Do not check for reboot after update'
complete -c fwupdmgr -l no-safety-check -d 'Do not perform device safety checks'
complete -c fwupdmgr -l no-history -d 'Do not write to the history database'
complete -c fwupdmgr -l show-all-devices -d 'Show devices that are not updatable'
complete -c fwupdmgr -l disable-ssl-strict -d 'Ignore SSL strict checks when downloading files'
complete -c fwupdmgr -l show-all -d 'Show all results'
complete -c fwupdmgr -l disable-ssl-strict -d 'Ignore SSL strict checks when downloading'
complete -c fwupdmgr -l filter -d 'Filter with a set of device flags'
complete -c fwupdmgr -l ignore-power -d 'Ignore requirement of external power source'
# complete subcommands
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a activate -d 'Activate devices'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a block-firmware -d 'Blocks a specific firmware from being installed'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a clear-history -d 'Erase all firmware update history'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a clear-offline -d 'Clears any updates scheduled to be updated offline'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a clear-results -d 'Clears the results from the last update'
@ -39,6 +42,7 @@ complete -c fwupdmgr -n '__fish_use_subcommand' -x -a disable-remote -d 'Disable
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a downgrade -d 'Downgrades the firmware on a device'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a enable-remote -d 'Enables a given remote'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-approved-firmware -d 'Gets the list of approved firmware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-blocked-firmware -d 'Gets the list of blocked firmware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-details -d 'Gets details about a firmware file'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-devices -d 'Get all devices that support firmware updates'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-history -d 'Show history of firmware updates'
@ -47,19 +51,22 @@ complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-remotes -d 'Gets the c
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-results -d 'Gets the results from the last update'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a get-updates -d 'Gets the list of updates for connected hardware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a install -d 'Install a firmware file on this hardware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a modify-config -d 'Modifies a daemon configuration value.'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a modify-config -d 'Modifies a daemon configuration value'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a modify-remote -d 'Modifies a given remote'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a refresh -d 'Refresh metadata from remote server'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a reinstall -d 'Reinstall current firmware on the device.'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a reinstall -d 'Reinstall current firmware on the device'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a report-history -d 'Share firmware history with the developers'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a set-approved-firmware -d 'Sets the list of approved firmware.'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a security -d 'Gets the host security attributes'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a set-approved-firmware -d 'Sets the list of approved firmware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a switch-branch -d 'Switch the firmware branch on the device'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a unblock-firmware -d 'Unblocks a specific firmware from being installed'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a unlock -d 'Unlocks the device for firmware access'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a update -d 'Updates all firmware to latest versions available'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a verify -d 'Checks cryptographic hash matches firmware'
complete -c fwupdmgr -n '__fish_use_subcommand' -x -a verify-update -d 'Update the stored cryptographic hash with current ROM contents'
# commands exclusively consuming device IDs
set -l deviceid_consumers activate clear-results downgrade get-releases get-results reinstall unlock update verify verify-update
set -l deviceid_consumers activate clear-results downgrade get-releases get-results get-updates reinstall switch-branch unlock update verify verify-update
# complete device IDs
complete -c fwupdmgr -n "__fish_seen_subcommand_from $deviceid_consumers" -x -a "(__fish_fwupdmgr_devices)"
# complete files and device IDs

View File

@ -4,4 +4,8 @@
[ -f @localstatedir@/lib/fwupd/pending.db ] || exit 0
# activate firmware when we have a read-only filesysten
@bindir@/fwupdtool activate
if !@bindir@/fwupdtool activate; then
ret=$?
[ "$ret" -eq "2" ] && exit 0
exit $ret
fi

View File

@ -9,7 +9,7 @@ By default this test suite is disabled.
Enabling
=======
To enable the test suite:
1. Modify `/etc/fwupd/daemon.conf` to remove the `test` plugin from `BlacklistPlugins`
1. Modify `/etc/fwupd/daemon.conf` to remove the `test` plugin from `DisabledPlugins`
```
# sed "s,^Enabled=false,Enabled=true," -i /etc/fwupd/remotes.d/fwupd-tests.conf
```

View File

@ -1 +1 @@
fakedevice123 -n
0x1020003

View File

@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Version: GnuPG v2.0.22 (GNU/Linux)
iQEcBAABAgAGBQJZQqynAAoJEEim2A5FOLrCVcsH/3Vn56wSeRCol0rOeXvoupg2
qpTAmqUvlubv2vX1IDbcL/lHIIEAHAlN/4LRHUh+Om0T7bMKX1uSfmcgCyUTBxl0
fm3TfXRhybi9VtZ5ZpwWxGsFsCNC9eOU0i8tB1zp9e9KjDPiYnluFkTRQ+Aw3u1u
tKBMTk6Z+VQlIUFrsveFYmPMGDkvn8AWbJCz6E4jc8can/lP/9djSi91mCqtEq/j
YTBz4OwfU80MRrSgoxykHgcB1RiT43ywfKlpHQzcO+rqCV7rv7LkXIEzBdWRZstk
XmboCnEKuMxtr+vXlGqU4n+upQkYur3Vs+07ut1OewQnJT3eeZbAH0mr42MVf7c=
=MQJe
iQEcBAABAgAGBQJfey1HAAoJEEim2A5FOLrCn2MIAK6BnVojGYSwHVpZm58b05Xs
rNqozg5pvfDfB0Bde1S0T/4TlDEnJNUku0Gz5IFNbR3ENT5VnJgBkE5xa8Rmv6cy
Gm30CmX+UE1E8qK4BVhUdbNN8bEmeMtzUMK2KfpwMXlIqcpSjpln76PQIxMHj+3P
600bkcppkLEKhiOo+THNhiHxPYJ+wjSSPm3paeMmUuApIvP4YFH8uQ5qkKLdLDVI
V5QOx3O5P3avmHu936GILG9EwV3TkR1eNOe33OqtrGvpoMTcsxUF0Wc/qmUD066d
c9hkTe01paQoN0HW/RMgrIaMnLFwK2mBcwySOo6TU9MIyQfDmLGN3u12nCrmRH8=
=Rq70
-----END PGP SIGNATURE-----

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2017 Richard Hughes <richard@hughsie.com> -->
<component type="firmware">
<id>fakedevice.firmware</id>
<name>FakeDevice Firmware</name>
<id>org.fwupd.fakedevice.firmware</id>
<name>FakeDevice</name>
<summary>Firmware for the ACME Corp Integrated Webcam</summary>
<description>
<p>

View File

@ -1 +1 @@
fakedevice124 -n
0x1020004

View File

@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Version: GnuPG v2.0.22 (GNU/Linux)
iQEcBAABAgAGBQJZQqy9AAoJEEim2A5FOLrCRLEH/27k0IfUtfGS8T5CPTvwW8kF
Cf6EIzw+2HgjbxLdeMNHwiHCBdIR58z44O1I9Xy6gY1vF3H4kKft6oBAUFDH0Ja5
YpQHXMZVSNdnwdg57cyC67kLOycHTSDlLXKB74tU3R4J8xntA1cY+DSYmCs2uAjq
3T3ExfjrX6PGbRhbNr8vBUQckCxcGvEZNOws2081mTosEQNpIxFyJ2tbbKLR60d0
5O/UDjNEYfUFCGy7MycXePEIOR+rO6KuEQ3vjJnv80UKE8msFxJTM1iKwct+B2HI
JNecCsx14BGDXCiE0Xc0heunfWiBHmNS2lymrHsU2Z82VrFqP0obD2cm64PBf0Y=
=Wsq/
iQEcBAABAgAGBQJfey2FAAoJEEim2A5FOLrCl88IAKCggwAz3qBrBfrc91sYHCq5
OthMyftOUTQ4JpfISY38k20pwFEhsSHKdKAYDKEVO2jopw+Cr9oTyFycWK20R2lz
tUn4e1EF8zQ29OLxGbvgGlP5/4vPJ2Cv5ujkub6LtNBrOMkNJ6+bB6G8nJZRTElU
e3wi9+E9oKPBgP40A/y79pzPiFMxXl1piYjU3JNeofd3nbtmyRqb6VAs9exQ94+p
CMWWZaJ9igxSAsQiE/NxZpO8qgG3KEmsW7yXRiaIe6xHxb49+JQdjxqS8Oc/C9sX
FSiVHDPzlUegZtcRWZy2zeSNTqmu8vzNSei0xEaLCaQ6PO+pQibxS2VZI/jDLdQ=
=Gha4
-----END PGP SIGNATURE-----

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2017 Richard Hughes <richard@hughsie.com> -->
<component type="firmware">
<id>fakedevice.firmware</id>
<name>FakeDevice Firmware</name>
<id>org.fwupd.fakedevice.firmware</id>
<name>FakeDevice</name>
<summary>Firmware for the ACME Corp Integrated Webcam</summary>
<description>
<p>

27
data/installed-tests/fwupd.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
exec 2>&1
dirname=`dirname $0`
run_test()
{
$dirname/$1
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
}
run_test acpi-dmar-self-test
run_test acpi-facp-self-test
run_test ata-self-test
run_test nitrokey-self-test
run_test linux-swap-self-test
run_test nvme-self-test
run_test wacom-usb-self-test
run_test redfish-self-test
run_test optionrom-self-test
run_test vli-self-test
run_test uefi-dbx-self-test
run_test synaptics-prometheus-self-test
run_test dfu-self-test
# success!
exit 0

View File

@ -0,0 +1,3 @@
[Test]
Type=session
Exec=sh -c "@installedtestsbindir@/fwupd.sh"

View File

@ -43,7 +43,7 @@ rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
# ---
echo "Installing test firmware..."
fwupdmgr install ${dirname}/fakedevice124.cab
fwupdmgr update $device -y
rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
# ---
@ -58,7 +58,7 @@ rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
# ---
echo "Downgrading to older release (requires network access)"
fwupdmgr downgrade $device
fwupdmgr downgrade $device -y
rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
# ---
@ -68,7 +68,7 @@ rc=$?; if [[ $rc != 2 ]]; then error $rc; fi
# ---
echo "Updating all devices to latest release (requires network access)"
fwupdmgr --no-unreported-check --no-metadata-check --no-reboot-check update
fwupdmgr --no-unreported-check --no-metadata-check --no-reboot-check update -y
rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
# ---

View File

@ -1,7 +1,6 @@
installed_test_datadir = join_paths(datadir, 'installed-tests', 'fwupd')
con2 = configuration_data()
con2.set('installedtestsdir', installed_test_datadir)
con2.set('installedtestsbindir', installed_test_bindir)
con2.set('bindir', bindir)
configure_file(
@ -12,6 +11,14 @@ configure_file(
install_dir: installed_test_datadir,
)
configure_file(
input : 'fwupd.test.in',
output : 'fwupd.test',
configuration : con2,
install: true,
install_dir: installed_test_datadir,
)
install_data([
'fwupdmgr.sh',
'fwupd-tests.xml',
@ -19,6 +26,12 @@ install_data([
install_dir : installed_test_datadir,
)
install_data([
'fwupd.sh',
],
install_dir : installed_test_bindir,
)
custom_target('installed-cab123',
input : [
'fakedevice123.bin',

View File

@ -30,97 +30,82 @@
</content_rating>
<provides>
<binary>fwupdmgr</binary>
<binary>fwupdtool</binary>
<binary>fwupdtpmevlog</binary>
<binary>fwupdagent</binary>
</provides>
<releases>
<release version="1.4.6" date="2020-09-07">
<release version="1.5.1" date="2020-11-02">
<description>
<p>This release adds the following features:</p>
<ul>
<li>Add a re-implementation of the rhboot dbxtool</li>
<li>Add commands to fwupdtool for interacting with the ESP</li>
<li>Add support for the LabTop Mk IV</li>
<li>Add support for the Realtek RTD21XX I²C protocol</li>
<li>Add X-Configuration category to use for dbx updates</li>
<li>Allow blocking specific firmware releases by checksum</li>
<li>Allow plugins to set remove delay only on the child</li>
<li>Allow updating the dbx, validating it is safe to apply</li>
<li>Support download of large DFU firmware</li>
<li>Support polling the status from device in dfuManifest state</li>
<li>Include the amount of NVRAM size in use in the LVFS failure report</li>
</ul>
<p>This release fixes the following bugs:</p>
<ul>
<li>Add missing Synaptics Prometheus GUIDs for ConfigId</li>
<li>Allow DFU device to attach to runtime without a bus reset</li>
<li>Be more careful doing multiple writes to the same device</li>
<li>Cancel the file monitor before disposal to avoid a potential deadlock</li>
<li>Correctly label the vebdor for more NVMe devices</li>
<li>Specify a remove delay for Poly USB Cameras</li>
<li>Use newer libxmlb features to properly display more AppStream markup</li>
<li>Delete unused EFI variables when deploying firmware</li>
<li>Fix probe warning for the Logitech Unifying device</li>
<li>Make bcm57xx hotplug more reliable</li>
<li>Recognize authorized thunderbolt value of 2</li>
<li>Remove the duplicate parent-child data in FwupdDevice and FuDevice</li>
<li>Show a less scary fwupdate output for devices without info</li>
<li>Show a link to discover more information about a specific plugin failure</li>
<li>Use a different Device ID for the OptionROM devices</li>
<li>Use UDisks to find out if swap devices are encrypted</li>
</ul>
</description>
</release>
<release version="1.4.5" date="2020-07-30">
<release version="1.5.0" date="2020-10-26">
<description>
<p>This release adds the following features:</p>
<ul>
<li>Add dual-image feature for VL103 backup firmware</li>
<li>Add more CCGX hybrid dock support</li>
<li>Add a compatible re-implementation of the rhboot dbxtool</li>
<li>Add async versions of the library for GUI tools</li>
<li>Add commands for interacting with the ESP to fwupdtool</li>
<li>Add firmware-extract subcommand to fwupdtool</li>
<li>Add FwupdPlugin so we can convey enumerated system errors to the end user</li>
<li>Add plugin for Goodix fingerprint sensors</li>
<li>Add plugin that can update the BCM5719 network adapter</li>
<li>Add plugin to update Elan Touchpads using HID</li>
<li>Add support for a delayed activation flow for Thunderbolt</li>
<li>Add support for ChromeOS Quiche and Gingerbread</li>
<li>Add support for Hyper hardware</li>
<li>Add support for the Host Security ID</li>
<li>Add support for ThunderBolt retimers</li>
<li>Add switch-branch command to fwupdtool and fwupdmgr</li>
<li>Allow blocking specific firmware releases by checksum</li>
<li>Allow constructing a firmware with multiple images</li>
<li>Allow firmware to require specific features from front-end clients</li>
<li>Modernize the thunderbolt plugin for future hardware</li>
<li>Support LVFS::UpdateImage in GUI clients</li>
<li>Allow updating the dbx using the LVFS, validating it is safe to apply</li>
<li>Include the HSI results and attributes in the uploaded report</li>
<li>Support loading DMI data from DT systems</li>
<li>Support LVFS::UpdateImage for GUI clients</li>
</ul>
<p>This release fixes the following bugs:</p>
<ul>
<li>Be more defensive when remotes are missing required keys</li>
<li>Check all AppStream components when verifying</li>
<li>Check for free space after cleaning up ESP</li>
<li>Fix TPM PCR0 calculation</li>
<li>Only show UpdateMessage when state is success</li>
<li>Read the modem vendor ID correctly</li>
<li>Set the runtime version to 0.0.0 for pre-1.0.0 Thelio Io firmware</li>
<li>Support compiling libqmi-glib 1.26.0 and later</li>
<li>Use the GPIOB reset for the MiniDock VL103</li>
<li>Wait for the root device to be replugged when updating the MSP430</li>
</ul>
</description>
</release>
<release version="1.4.4" date="2020-06-10">
<description>
<p>This release fixes the following regression:</p>
<ul>
<li>Fix refreshing when checking for downgraded metadata</li>
</ul>
</description>
</release>
<release version="1.4.3" date="2020-06-09">
<description>
<p>This release adds the following features:</p>
<ul>
<li>Add support for HP DMC dock devices</li>
</ul>
<p>This release fixes the following bugs:</p>
<ul>
<li>Always enforce the metadata signature has a valid timestamp</li>
<li>Capture the dock SKU in metadata</li>
<li>Check the device requirements when returning from GetDetails</li>
<li>Force the prometheus minor version from 0x02 to 0x01</li>
<li>Prevent Dell dock updates to occur via synaptics-mst plugin</li>
</ul>
</description>
</release>
<release version="1.4.2" date="2020-05-18">
<description>
<p>This release fixes the following bugs:</p>
<ul>
<li>Add several more ATA OUI quirks</li>
<li>Avoid communicating with DFU devices when bitManifestationTolerant is off</li>
<li>Correct the display of final calculated PCRs</li>
<li>Delay activation for Dell Thunderbolt updates</li>
<li>Do not use synaptics-rmi on the Dell K12A</li>
<li>Fix switching wacom-raw to bootloader mode</li>
<li>Switch the default of EnumerateAllDevices to false</li>
<li>Use GPIOB to reset the VL817 found in two Lenovo products</li>
<li>Allow compiling the daemon without polkit support</li>
<li>Always look at all TPM eventlog supported algorithms</li>
<li>Change all instances of master/slave to initiator/target</li>
<li>Correctly order devices when using logical parents</li>
<li>Do not dedupe NVMe or VLI PD devices</li>
<li>Do not expose the VLI shared-SPI devices on the USB2 recovery device</li>
<li>Do not fix up the version on post-update mismatch</li>
<li>Download the metadata first when using 'fwupdtool refresh'</li>
<li>Drop efivar dependency</li>
<li>Drop support for ThunderBolt force power due to hardware issues</li>
<li>Fix setting BootNext correctly when multiple updates are scheduled</li>
<li>Fix the topology of the audio device on the Lenovo TR dock</li>
<li>Make return code different for get-updates with no updates</li>
<li>Make specific authorizations also imply others</li>
<li>Make TPM support more optional</li>
<li>Parse the HEX version before comparing for equality</li>
<li>Prevent dell-dock updates to occur via synaptics-mst plugin</li>
<li>Record the UEFI failure in more cases</li>
<li>Retry the HID SetReport to fix flashing the TB3 dock</li>
<li>Show an error when a plugin is missing dependencies</li>
<li>Use libxmlb bound parameters to speed up the device verification</li>
<li>Use pkttyagent to request user passwords if running without GUI</li>
<li>Use the JCat file to select the metadata file</li>
</ul>
</description>
</release>
@ -195,6 +180,32 @@
</ul>
</description>
</release>
<release version="1.3.9" date="2020-03-04">
<description>
<p>This release adds the following features:</p>
<ul>
<li>Added completion script for fish shell</li>
<li>Inihbit all power management actions using logind when updating</li>
</ul>
<p>This release fixes the following bugs:</p>
<ul>
<li>Always check for PLAIN when doing vercmp() operations</li>
<li>Always return AppStream markup for remote agreements</li>
<li>Apply UEFI capsule update even with single valid capsule</li>
<li>Check the device protocol before de-duping devices</li>
<li>Copy the version and format from donor device in get-details</li>
<li>Correctly append the release to devices in `fwupdtool get-details`</li>
<li>Decrease minimum battery requirement to 10%</li>
<li>Discard the reason upgrades aren't available</li>
<li>Do not fail loading in /etc/machine-id is not available</li>
<li>Fix a critical warning when installing some firmware</li>
<li>For the `get-details` command make sure to always show devices</li>
<li>Set the MSP430 version format to pair</li>
<li>Switch off the ATA verbose logging by default</li>
<li>Use unknown for version format by default on get-details</li>
</ul>
</description>
</release>
<release version="1.3.8" date="2020-02-13">
<description>
<p>This release adds the following features:</p>
@ -513,7 +524,7 @@
<li>Do not fail to start the daemon if tpm2_pcrlist hangs</li>
<li>Do not fail when scheduling more than one update to be run offline</li>
<li>Do not let failing to find DBus prevent fwuptool from starting</li>
<li>Do not schedule an update on battery power if it requires AC power</li>
<li>Do not schedule an update on battery power if it requires an external power source</li>
<li>Include all device checksums in the LVFS report</li>
<li>Rename the shimx64.efi binary for known broken firmware</li>
<li>Upload the UPDATE_INFO entry for the UEFI UX capsule</li>

View File

@ -5,6 +5,8 @@ Enabled=true
Title=Linux Vendor Firmware Service
MetadataURI=https://cdn.fwupd.org/downloads/firmware.xml.gz
ReportURI=https://fwupd.org/lvfs/firmware/report
SecurityReportURI=https://fwupd.org/lvfs/hsireports/upload
OrderBefore=fwupd
AutomaticReports=false
AutomaticSecurityReports=false
ApprovalRequired=false

View File

@ -0,0 +1 @@
1.2.3-4

View File

@ -0,0 +1 @@
ColorHug

View File

@ -0,0 +1 @@
To Be Filled By O.E.M.

Binary file not shown.

View File

@ -0,0 +1 @@
Hughski Limited

Binary file not shown.

Binary file not shown.

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
fwupd (1.5.1-1) UNRELEASED; urgency=medium
* New upstream version (1.5.1)
-- Mario Limonciello <mario.limonciello@dell.com> Fri, 13 Nov 2020 09:42:10 -0600
fwupd (1.4.6-2) unstable; urgency=medium
* Add udisks2 to recommends

1
debian/control.in vendored
View File

@ -49,6 +49,7 @@ Depends: ${misc:Depends},
shared-mime-info
Recommends: python3,
bolt,
secureboot-db,
udisks2,
fwupd-signed
Provides: fwupdate

View File

@ -3,6 +3,8 @@
#find them. for more information see:
#https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=872458
usr/share/installed-tests/*
usr/libexec/installed-tests/fwupd/fwupd.sh
usr/libexec/installed-tests/fwupd/*-self-test
usr/lib/*/fwupd-plugins-3/libfu_plugin_test.so
usr/lib/*/fwupd-plugins-3/libfu_plugin_invalid.so
debian/lintian/fwupd-tests usr/share/lintian/overrides

View File

@ -7,7 +7,7 @@ set -e
if [ "$1" = configure ] && [ -z "$2" ]; then
if [ -f /etc/fwupd/daemon.conf ]; then
if [ "$CI" = "true" ]; then
sed "s,^BlacklistPlugins=test;invalid,BlacklistPlugins=," -i /etc/fwupd/daemon.conf
sed "s,^DisabledPlugins=test;invalid,DisabledPlugins=," -i /etc/fwupd/daemon.conf
else
echo "To enable test suite, modify /etc/fwupd/daemon.conf"
fi

View File

@ -6,7 +6,7 @@ set -e
if [ "$1" = remove -o "$1" = purge ]; then
if [ -f /etc/fwupd/daemon.conf ]; then
if [ "$CI" = "true" ]; then
sed "s,^BlacklistPlugins=,BlacklistPlugins=test;invalid," -i /etc/fwupd/daemon.conf
sed "s,^DisabledPlugins=,DisabledPlugins=test;invalid," -i /etc/fwupd/daemon.conf
else
echo "To disable test suite, modify /etc/fwupd/daemon.conf"
fi

View File

@ -9,6 +9,7 @@ usr/share/polkit-1/*
usr/share/locale
usr/share/metainfo/*
usr/libexec/fwupd/fwupd
usr/libexec/fwupd/fwupd-detect-cet
usr/libexec/fwupd/fwupdoffline
usr/share/man/man1/*
lib/systemd/system/*

View File

@ -9,3 +9,7 @@ fwupd: library-not-linked-against-libc usr/lib/*/fwupd-plugins-3/libfu_plugin_ue
fwupd: executable-not-elf-or-script usr/libexec/fwupd/efi/*.efi
fwupd: portable-executable-missing-security-features usr/libexec/fwupd/efi/*.efi SafeSEH
fwupd: library-not-linked-against-libc usr/lib/*/fwupd-plugins-3/libfu_plugin_modem_manager.so
fwupd: library-not-linked-against-libc usr/lib/*/fwupd-plugins-3/libfu_plugin_pci_bcr.so
fwupd: library-not-linked-against-libc usr/lib/*/fwupd-plugins-3/libfu_plugin_pci_mei.so
fwupd: library-not-linked-against-libc usr/lib/*/fwupd-plugins-3/libfu_plugin_iommu.so
fwupd: library-not-linked-against-libc usr/lib/*/fwupd-plugins-3/libfu_plugin_msr.so

11
debian/rules vendored
View File

@ -14,9 +14,6 @@ ifneq ($(CI),)
export CI=--werror --wrap-mode=default
endif
regenerate_control:
OS=debian-x86_64 ./contrib/ci/generate_debian.py
SB_STYLE := debian
deb_version := $(shell dpkg-parsechangelog --show-field Version)
export FLASHROM=-Dplugin_flashrom=false
@ -47,9 +44,9 @@ override_dh_auto_configure:
export DELL="-Dplugin_dell=false"; \
fi; \
if pkg-config --exists efivar; then \
export UEFI="-Dplugin_uefi=true -Dplugin_redfish=true -Dplugin_nvme=true"; \
export UEFI="-Dplugin_uefi=true -Dplugin_redfish=true -Dplugin_nvme=true -Dplugin_msr=true"; \
else \
export UEFI="-Dplugin_uefi=false -Dplugin_redfish=false -Dplugin_nvme=false"; \
export UEFI="-Dplugin_uefi=false -Dplugin_redfish=false -Dplugin_nvme=false -Dplugin_msr=false"; \
fi; \
dh_auto_configure -- $$UEFI $$DELL $$FLASHROM $$CI -Dplugin_dummy=true -Dgtkdoc=true
@ -61,9 +58,7 @@ override_dh_install:
if [ -d debian/tmp/usr/libexec/fwupd/efi/ ]; then \
dh_install -pfwupd usr/libexec/fwupd/efi ;\
fi
if [ -z "$$CI" ]; then \
dh_missing -a --fail-missing; \
fi
dh_missing -a --fail-missing
#this is placed in fwupd-tests
rm -f debian/fwupd/usr/lib/*/fwupd-plugins-3/libfu_plugin_test.so

6
debian/tests/ci vendored
View File

@ -1,5 +1,7 @@
#!/bin/sh
set -e
sed "s,^BlacklistPlugins=.*,BlacklistPlugins=," -i /etc/fwupd/daemon.conf
sed "s,^DisabledPlugins=.*,DisabledPlugins=," -i /etc/fwupd/daemon.conf
sed "s,^VerboseDomains=.*,VerboseDomains=*," -i /etc/fwupd/daemon.conf
gnome-desktop-testing-runner fwupd
git clone https://github.com/fwupd/fwupd-test-firmware
export G_TEST_SRCDIR=`pwd`/fwupd-test-firmware/installed-tests
CI_NETWORK=true gnome-desktop-testing-runner fwupd

View File

@ -26,8 +26,10 @@
</para>
</partintro>
<xi:include href="xml/fwupd-client.xml"/>
<xi:include href="xml/fwupd-client-sync.xml"/>
<xi:include href="xml/fwupd-device.xml"/>
<xi:include href="xml/fwupd-release.xml"/>
<xi:include href="xml/fwupd-plugin.xml"/>
<xi:include href="xml/fwupd-remote.xml"/>
<xi:include href="xml/fwupd-error.xml"/>
<xi:include href="xml/fwupd-enums.xml"/>
@ -67,405 +69,10 @@
<xi:include href="xml/fu-usb-device.xml"/>
</reference>
<reference id="tutorial">
<title>Plugin Tutorial</title>
<partintro>
<section>
<title>Introduction</title>
<para>
At the heart of fwupd is a plugin loader that gets run at startup,
when devices get hotplugged and when updates are done.
The idea is we have lots of small plugins that each do one thing, and
are ordered by dependencies against each other at runtime.
Using plugins we can add support for new hardware or new policies
without making big changes all over the source tree.
</para>
<para>
There are broadly 3 types of plugin methods:
</para>
<itemizedlist>
<listitem>
<para>
<emphasis role="strong">Mechanism</emphasis>: Upload binary data
into a specific hardware device.
</para>
</listitem>
<listitem>
<para>
<emphasis role="strong">Policy</emphasis>: Control the system when
updates are happening, e.g. preventing the user from powering-off.
</para>
</listitem>
<listitem>
<para>
<emphasis role="strong">Helpers</emphasis>: Providing more
metadata about devices, for instance handling device quirks.
</para>
</listitem>
</itemizedlist>
<para>
In general, building things out-of-tree isn't something that we think is
a very good idea; the API and ABI <emphasis>internal</emphasis> to fwupd is still
changing and there's a huge benefit to getting plugins upstream where
they can undergo review and be ported as the API adapts.
For this reason we don't install the plugin headers onto the system,
although you can of course just install the <code>.so</code> binary file
manually.
</para>
<para>
A plugin only needs to define the vfuncs that are required, and the
plugin name is taken automatically from the suffix of the
<filename>.so</filename> file.
</para>
<example>
<title>A sample plugin</title>
<programlisting>
/*
* Copyright (C) 2017 Richard Hughes
*/
#include &lt;fu-plugin.h&gt;
#include &lt;fu-plugin-vfuncs.h&gt;
struct FuPluginData {
gpointer proxy;
};
void
fu_plugin_initialize (FuPlugin *plugin)
{
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_RUN_BEFORE, "dfu");
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
}
void
fu_plugin_destroy (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
destroy_proxy (data->proxy);
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
data->proxy = create_proxy ();
if (data->proxy == NULL) {
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED,
"failed to create proxy");
return FALSE;
}
return TRUE;
}
</programlisting>
</example>
<para>
We have to define when our plugin is run in reference to other plugins,
in this case, making sure we run before the <code>dfu</code> plugin.
For most plugins it does not matter in what order they are run and
this information is not required.
</para>
</section>
<section>
<title>Creating an abstract device</title>
<para>
This section shows how you would create a device which is exported
to the daemon and thus can be queried and updated by the client software.
The example here is all hardcoded, and a true plugin would have to
derive the details about the <code>FuDevice</code> from the hardware,
for example reading data from <code>sysfs</code> or <code>/dev</code>.
</para>
<example>
<title>Example adding a custom device</title>
<programlisting>
#include &lt;fu-plugin.h&gt;
gboolean
fu_plugin_coldplug (FuPlugin *plugin, GError **error)
{
g_autoptr(FuDevice) dev = NULL;
fu_device_set_id (dev, "dummy-1:2:3");
fu_device_add_guid (dev, "2d47f29b-83a2-4f31-a2e8-63474f4d4c2e");
fu_device_set_version (dev, "1.2.3");
fu_device_get_version_lowest (dev, "1.2.2");
fu_device_get_version_bootloader (dev, "0.1.2");
fu_device_add_icon (dev, "computer");
fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
fu_plugin_device_add (plugin, dev);
return TRUE;
}
</programlisting>
</example>
<para>
This shows a lot of the plugin architecture in action. Some notable points:
</para>
<itemizedlist>
<listitem>
<para>
The device ID (<code>dummy-1:2:3</code>) has to be unique on the
system between all plugins, so including the plugin name as a
prefix is probably a good idea.
</para>
</listitem>
<listitem>
<para>
The GUID value can be generated automatically using
<code>fu_device_add_guid(dev,"some-identifier")</code> but is quoted
here explicitly.
The GUID value has to match the <code>provides</code> value in the
<code>.metainfo.xml</code> file for the firmware update to succeed.
</para>
</listitem>
<listitem>
<para>
Setting a display name and an icon is a good idea in case the
GUI software needs to display the device to the user.
Icons can be specified using a full path, although icon theme names
should be preferred for most devices.
</para>
</listitem>
<listitem>
<para>
The <code>FWUPD_DEVICE_FLAG_UPDATABLE</code> flag tells the client
code that the device is in a state where it can be updated.
If the device needs to be in a special mode (e.g. a bootloader) then
the <code>FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER</code> flag can also be
used.
If the update should only be allowed when there is AC power available
to the computer (i.e. not on battery) then
<code>FWUPD_DEVICE_FLAG_REQUIRE_AC</code> should be used as well.
There are other flags and the API documentation should be used when
choosing what flags to use for each kind of device.
</para>
</listitem>
<listitem>
<para>
Setting the lowest allows client software to refuse downgrading
the device to specific versions.
This is required in case the upgrade migrates some kind of data-store
so as to be incompatible with previous versions.
Similarly, setting the version of the bootloader (if known) allows
the firmware to depend on a specific bootloader version, for instance
allowing signed firmware to only be installable on hardware with
a bootloader new enough to deploy it
</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Mechanism Plugins</title>
<para>
Although it would be a wonderful world if we could update all hardware
using a standard shared protocol this is not the universe we live in.
Using a mechanism like DFU or UpdateCapsule means that fwupd will just
work without requiring any special code, but for the real world we need
to support vendor-specific update protocols with layers of backwards
compatibility.
</para>
<para>
When a plugin has created a device that is <code>FWUPD_DEVICE_FLAG_UPDATABLE</code>
we can ask the daemon to update the device with a suitable
<code>.cab</code> file.
When this is done the daemon checks the update for compatibility with
the device, and then calls the vfuncs to update the device.
</para>
<example>
<title>Updating a device</title>
<programlisting>
gboolean
fu_plugin_update (FuPlugin *plugin,
FuDevice *dev,
GBytes *blob_fw,
FwupdInstallFlags flags,
GError **error)
{
gsize sz = 0;
guint8 *buf = g_bytes_get_data (blob_fw, &amp;sz);
/* write 'buf' of size 'sz' to the hardware */
return TRUE;
}
</programlisting>
</example>
<para>
It's important to note that the <code>blob_fw</code> is the binary
firmware file (e.g. <code>.dfu</code>) and <emphasis role="strong">not</emphasis>
the <code>.cab</code> binary data.
</para>
<para>
If <code>FWUPD_INSTALL_FLAG_FORCE</code> is used then the usual checks
done by the flashing process can be relaxed (e.g. checking for quirks),
but please don't brick the users hardware even if they ask you to.
</para>
</section>
<section>
<title>Policy Helpers</title>
<para>
For some hardware, we might want to do an action before or after
the actual firmware is squirted into the device.
This could be something as simple as checking the system battery
level is over a certain threshold, or it could be as complicated as
ensuring a vendor-specific GPIO is asserted when specific types
of hardware are updated.
</para>
<example>
<title>Running before a device update</title>
<programlisting>
gboolean
fu_plugin_update_prepare (FuPlugin *plugin, FuDevice *device, GError **error)
{
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_REQUIRE_AC &amp;&amp; !on_ac_power ()) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_AC_POWER_REQUIRED,
"Cannot install update "
"when not on AC power");
return FALSE;
}
return TRUE;
}
</programlisting>
</example>
<example>
<title>Running after a device update</title>
<programlisting>
gboolean
fu_plugin_update_cleanup (FuPlugin *plugin, FuDevice *device, GError **error)
{
return g_file_set_contents ("/var/lib/fwupd/something",
fu_device_get_id (device), -1, error);
}
</programlisting>
</example>
</section>
<section>
<title>Detaching to bootloader mode</title>
<para>
Some hardware can only be updated in a special bootloader mode, which
for most devices can be switched to automatically.
In some cases the user to do something manually, for instance
re-inserting the hardware with a secret button pressed.
</para>
<para>
Before the device update is performed the fwupd daemon runs an optional
<code>update_detach()</code> vfunc which switches the device to
bootloader mode.
After the update (or if the update fails) an the daemon runs an
optional <code>update_attach()</code> vfunc which should switch the
hardware back to runtime mode.
Finally an optional <code>update_reload()</code> vfunc is run to
get the new firmware version from the hardware.
</para>
<para>
The optional vfuncs are <emphasis role="strong">only</emphasis> run
on the plugin currently registered to handle the device ID, although
the registered plugin can change during the attach and detach phases.
</para>
<example>
<title>Running before a device update</title>
<programlisting>
gboolean
fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error)
{
if (hardware_in_bootloader)
return TRUE;
return _device_detach(device, error);
}
</programlisting>
</example>
<example>
<title>Running after a device update</title>
<programlisting>
gboolean
fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error)
{
if (!hardware_in_bootloader)
return TRUE;
return _device_attach(device, error);
}
</programlisting>
</example>
<example>
<title>Running after a device update on success</title>
<programlisting>
gboolean
fu_plugin_update_reload (FuPlugin *plugin, FuDevice *device, GError **error)
{
g_autofree gchar *version = _get_version(plugin, device, error);
if (version == NULL)
return FALSE;
fu_device_set_version(device, version);
return TRUE;
}
</programlisting>
</example>
</section>
<section>
<title>The Plugin Object Cache</title>
<para>
The fwupd daemon provides a per-plugin cache which allows objects
to be added, removed and queried using a specified key.
Objects added to the cache must be <code>GObject</code>s to enable the
cache objects to be properly refcounted.
</para>
</section>
<section>
<title>Debugging a Plugin</title>
<para>
If the fwupd daemon is started with <code>--plugin-verbose=$plugin</code>
then the environment variable <code>FWUPD_$PLUGIN_VERBOSE</code> is
set process-wide.
This allows plugins to detect when they should output detailed debugging
information that would normally be too verbose to keep in the journal.
For example, using <code>--plugin-verbose=logitech_hidpp</code> would set
<code>FWUPD_LOGITECH_HID_VERBOSE=1</code>.
</para>
</section>
<section>
<title>Using existing code to develop a plugin</title>
<para>
It is not usually possible to <em>share</em> a plugin codebase with
firmware update programs designed for other operating systems.
Matching the same rationale as the Linux kernel, trying to use one
code base between projects with a compatibility shim layer in-between
is real headache to maintain.
</para>
<para>
The general consensus is that trying to use a abstraction layer for
hardware is a very bad idea as you're not able to take advantage of the
platform specific helpers -- for instance quirk files and the custom
GType device creation.
The time the <em>vendor</em> saves by creating a shim layer and
importing existing source code into fwupd will be overtaken 100x by
<em>upstream</em> maintenance costs longer term, which isn't fair.
</para>
<para>
In a similar way, using C++ rather than GObject C means expanding the
test matrix to include clang in C++ mode and GNU g++ too.
It's also doubled the runtime requirements to now include both the C
standard library as well as the C++ standard library and increases the
dependency surface.
</para>
<para>
Most rewritten fwupd plugins at up to x10 smaller than the standalone
code as they can take advantage of helpers provided by fwupd rather
than re-implementing error handling, device quirking and data chunking.
</para>
</section>
</partintro>
</reference>
<xi:include href="tutorial.xml"/>
<!--
<xi:include href="hsi.xml"/>
-->
<index id="api-index-full">
<title>API Index</title>

877
docs/hsi.xml Normal file
View File

@ -0,0 +1,877 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
<reference id="hsi">
<title>Host Security ID Specification</title>
<warning>
<para>
This specification is still in active development: it is incomplete,
subject to change, and may have errors; use this at your own risk.
It is based on publicly available information.
</para>
</warning>
<!-- only show when document has been verified by all the below people
<info>
<authorgroup>
<author>
<personname>
<firstname>Richard</firstname>
<surname>Hughes</surname>
</personname>
<affiliation>
<orgname>Red Hat</orgname>
</affiliation>
</author>
<author>
<personname>
<firstname>Mario</firstname>
<surname>Limonciello</surname>
</personname>
<affiliation>
<orgname>Dell</orgname>
</affiliation>
</author>
<author>
<personname>
<firstname>Alex</firstname>
<surname>Bazhaniuk</surname>
</personname>
<affiliation>
<orgname>Eclypsium</orgname>
</affiliation>
</author>
<author>
<personname>
<firstname>Alex</firstname>
<surname>Matrosov</surname>
</personname>
<affiliation>
<orgname>Nvidia</orgname>
</affiliation>
</author>
</authorgroup>
</info>
-->
<partintro>
<refsect1 id="introduction">
<title>Introduction</title>
<para>
Not all system vendors prioritize building a secure platform.
The truth is that <emphasis role="strong">security costs money</emphasis>.
Vendors have to choose between saving a few cents on a bill-of-materials
by sharing a SPI chip, or correctly implementing BootGuard.
Discovering security vulnerabilities often takes an external researcher
filing a disclosure.
These disclosures are often technical in nature and difficult for an
average consumer to decipher.
</para>
<para>
The Linux Vendor Firmware Service (LVFS) could provide some
<emphasis role="strong">easy-to-understand</emphasis> information to
people buying hardware.
The service already knows a huge amount of information about machines
from signed reports uploaded to the LVFS and from analyzing firmware binaries.
However this information alone does not explain firmware security to the
user in a way they can actually interpret.
</para>
</refsect1>
<refsect2 id="other-tools">
<title>Other Tools</title>
<para>
Traditionally, figuring out the true security of your hardware and firmware
requires sifting through the marketing documentation provided by the
OEM and in many cases just “trusting” they did it right.
Tools such as Chipsec can check the hardware configuration, but they do
not work out of the box and use technical jargon that an average user
cannot interpret.
Unfortunately, running a tool like Chipsec requires that you actively
turn off some security layers such as UEFI Secure Boot, and allow 3rd
party unsigned kernel modules to be loaded.
</para>
</refsect2>
<refsect1 id="verifying">
<title>Verifying Host Firmware Security</title>
<para>
To start out some core protections must be assigned a relative importance.
Then an evaluation must be done to determine how each vendor is conforming
to the model.
For instance, a user might say that for home use any hardware the bare
minimum security level (<code>HSI:1</code>) is <emphasis>good enough</emphasis>.
For a work laptop the company IT department might restrict the choice of
models to anything meeting the criteria of level <code>HSI:2</code> or
above.
A journalist or a security researcher would only buy level <code>HSI:3</code>
and above.
The reality is that <code>HSI:4</code> is going to be more expensive
than some unbranded hardware that is rated <code>HSI:0</code>.
</para>
<para>
To be trusted, this rating information should be distributed in a
centralized agnostic database such as the LVFS.
</para>
<para>
Of course, tools need to detect implementation errors, and to verify that
the model that is measured does indeed match the HSI level advertised by
the LVFS.
Some existing compliance solutions place the burden on the OEM to define
what firmware security has been implemented, which is easy to get wrong
and in some cases impossible to verify.
</para>
<para>
For this reason HSI will only measure security protections that can be
verified by the end user without requiring any extra hardware to be
connected, additional software to be installed, or disabling any existing
security layers to measure.
</para>
<para>
The HSI specification is primarily designed for laptop and desktop
hardware, although some tests <emphasis>may</emphasis> still make sense
on server or embedded hardware.
It is not expected that non-consumer hardware will publish an HSI number.
</para>
</refsect1>
<refsect2 id="runtime-behaviour">
<title>Runtime Behavior</title>
<para>
Orthogonal to the security features provided by the firmware there are
other security considerations related to the firmware which may require
internet access to discover or that runtime OS changes directly affect
the security of the firmware.
It would not make sense to have <emphasis>have updates on the LVFS</emphasis>
as a requirement for a specific security level as this would mean
offline the platform might be a higher level initially but as soon as
it is brought online it is downgraded which would be really confusing to
users.
The <emphasis>core</emphasis> security level will not change at
Operating System runtime, but the suffix may.
</para>
</refsect2>
<refsect2 id="hsi-level0">
<title>HSI:0 (Insecure)</title>
<para>
The lowest security level with little or no detected firmware protections.
This is the default security level if no tests can be run or some tests
in the next security level have failed.
</para>
</refsect2>
<refsect2 id="hsi-level1">
<title>HSI:1 (Critical)</title>
<para>
This security level corresponds to the most basic of security protections
considered essential by security professionals.
Any failures at this level would have critical security impact and could
likely be used to compromise the system firmware without physical access.
</para>
</refsect2>
<refsect2 id="hsi-level2">
<title>HSI:3 (Theoretical)</title>
<para>
This security level corresponds to firmware security issues that pose a
theoretical concern or where any exploit would be difficult or
impractical to use.
At this level various technologies may be employed to protect the boot
process from modification by an attacker with local access to the machine.
</para>
</refsect2>
<refsect2 id="hsi-level4">
<title>HSI:4 (System Protection)</title>
<para>
This security level corresponds to out-of-band protection of the system
firmware perhaps including recovery.
</para>
</refsect2>
<refsect2 id="hsi-level5">
<title>HSI:5 (System Attestation)</title>
<para>
This security level corresponds to out-of-band attestation of the system
firmware.
There are currently no tests implemented for HSI:5 and so this security
level cannot yet be obtained.
</para>
</refsect2>
<refsect3 id="org.fwupd.hsi.Fwupd.Updates">
<title>HSI Runtime Suffix <code>U</code></title>
<para>
Updates available on the <ulink url="https://fwupd.org/">
Linux Vendor Firmware Service </ulink> which are less than 12 months old.
</para>
</refsect3>
<refsect3 id="org.fwupd.hsi.Fwupd.Attestation">
<title>HSI Runtime Suffix <code>A</code></title>
<para>
Attestation data is available to verify the current system firmware.
For most UEFI platforms, this is usually the Trusted Platform Module (TPM)
PCR0 hash, but other attestation checksums could be used.
</para>
</refsect3>
<refsect3 id="runtime-bang">
<title>HSI Runtime Suffix <code>!</code></title>
<para>
A runtime security issue detected.
</para>
<itemizedlist>
<listitem id="org.fwupd.hsi.Uefi.SecureBoot">
<para>
UEFI <ulink url="https://wiki.ubuntu.com/UEFI/SecureBoot">
Secure Boot</ulink> has been turned off. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
<listitem id="org.fwupd.hsi.Kernel.Tainted">
<para>
The kernel is <ulink url="https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html">
tainted</ulink> due to a non-free module or critical firmware issue. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
<listitem id="org.fwupd.hsi.Kernel.Lockdown">
<para>
The kernel is not <ulink url="https://mjg59.dreamwidth.org/50577.html">
locked down</ulink>. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
<listitem id="org.fwupd.hsi.Kernel.Swap">
<para>
Unencrypted <ulink url="https://wiki.archlinux.org/index.php/Dm-crypt/Swap_encryption">
swap partition</ulink>. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
<listitem id="org.fwupd.hsi.Fwupd.Plugins">
<para>
The installed fwupd is running with <ulink url="https://github.com/fwupd/fwupd/tree/master/plugins">
custom or modified plugins</ulink>. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
</refsect3>
<refsect2 id="tests">
<title>Tests included in fwupd</title>
<para>
The set of tests is currently x86 UEFI-centric, but will be expanded
in the future for various ARM or RISC-V firmware protections as required.
Where the requirement is architecture or processor specific it has been noted.
</para>
</refsect2>
<refsect3 id="org.fwupd.hsi.Uefi.SecureBoot">
<title>UEFI SecureBoot</title>
<para>
UEFI Secure boot is a verification mechanism for ensuring that code
launched by firmware is trusted.
</para>
<para>
Secure Boot requires that each binary loaded at boot is validated
against trusted certifictes.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 SecureBoot must be available for use on UEFI systems.
<emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://wiki.ubuntu.com/UEFI/SecureBoot">
UEFI Wiki Entry
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Spi.Bioswe">
<title>BIOS Write Enable (BWE)</title>
<para>
Intel hardware provides this mechanism to protect the SPI ROM chip
located on the motherboard from being overwritten by the operating system.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 the ``BIOSWE`` bit must be unset. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="http://www.intel.com/content/www/us/en/chipsets/6-chipset-c200-chipset-datasheet.html">
Intel C200 Datasheet
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Spi.Ble">
<title>BIOS Lock Enable (BLE)</title>
<para>
If the lock bit is set then System Management Interrupts (SMIs) are
raised when setting BIOS Write Enable.
The <code>BLE</code>` bit must be enabled in the PCH otherwise
<code>BIOSWE</code> can easily be unset.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should be set. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="http://www.intel.com/content/www/us/en/chipsets/6-chipset-c200-chipset-datasheet.html">
Intel C200 Datasheet
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Spi.SmmBwp">
<title>SMM Bios Write Protect (SMM_BWP)</title>
<para>
This bit set defines when the BIOS region can be written by the host.
The <code>SMM_BWP</code> bit must be set to make the BIOS region
non-writable unless all processors are in system management mode.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should be set <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="http://www.intel.com/content/www/us/en/chipsets/6-chipset-c200-chipset-datasheet.html">
Intel C200 Datasheet
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Tpm.Version20">
<title>TPM 2.0 Present</title>
<para>
A TPM securely stores platform specific secrets that can only be divulged
to trusted consumers in a secure environment.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should be available for use by the OS or applications <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://en.wikipedia.org/wiki/Trusted_Platform_Module">
Wikipedia TPM Article
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Mei.ManufacturingMode">
<title>ME not in manufacturing mode</title>
<para>
There have been some unfortunate cases of the ME being distributed in
manufacturing mode.
In manufacturing mode many features from the ME can be interacted with
that decrease the platforms security.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should be unset <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="http://blog.ptsecurity.com/2018/10/intel-me-manufacturing-mode-macbook.html">
ME Manufacturing Mode: obscured dangers
</ulink>
</listitem>
<listitem>
<ulink url="https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00086.html">
Intel security advisory SA-00086
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Mei.OverrideStrap">
<title>ME Flash Descriptor Override</title>
<para>
The Flash Descriptor Security Override Strap is not accessible to end
users on consumer boards and Intel stresses that this is for debugging only.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should be unset <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://chromium.googlesource.com/chromiumos/third_party/flashrom/+/master/Documentation/mysteries_intel.txt">
Chromium documentation for Intel ME
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Mei.Version">
<title>CSME Version</title>
<para>
Converged Security and Manageability Engine is a standalone management
module that can manage and control some local devices without the host
CPU involvement.
The CSME lives in the PCH and can only be updated by the OEM vendor.
The version of the CSME module can be checked to detect the most common
and serious vulnerabilities.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should not be vulnerable to CVE-2017-5705, CVE-2017-5708,
CVE-2017-5711, CVE-2017-5712, CVE-2017-5711, CVE-2017-5712, CVE-2017-5706,
CVE-2017-5709, CVE-2017-5707 or CVE-2017-5710 <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00086.html">
Intel CSME Security Review Cumulative Update
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.IntelDci">
<title>Intel DCI</title>
<para>
Newer Intel CPUs support debugging over USB3 via a proprietary Direct
Connection Interface (DCI) with the use of off-the-shelf hardware.
DCI should always be disabled and locked on production hardware.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 this should be disabled. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
<listitem>
<para>
For HSI-2 this should be locked. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://www.intel.co.uk/content/www/uk/en/support/articles/000029393/processors.html">
Intel Direct Connect Interface
</ulink>
</listitem>
<listitem>
<ulink url="https://github.com/chipsec/chipsec/blob/master/chipsec/cfg/8086/pch_4xxlp.xml#L270">
Chipsec 4xxlp register definitions
</ulink>
</listitem>
<listitem>
<ulink url="https://github.com/riscv/riscv-edk2-platforms/blob/85a50de1b459d1d6644a402081120770aa6dd8c7/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Include/Register/PchRegsDci.h">
RISC-V EDK PCH register definitions
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Tpm.ReconstructionPcr0">
<title>PCR0 TPM Event Log Reconstruction</title>
<para>
The TPM event log records which events are registered for the PCR0 hash.
When reconstructed the event log values should always match the TPM PCR0.
If extra events are included in the event log, or some are missing,
the reconstitution will fail.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-2 this should match the TPM-provided PCR0 <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://www.kernel.org/doc/html/latest/security/tpm/tpm_event_log.html">
Linux Kernel TPM Documentation
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.AcpiDmar">
<title>Pre-boot DMA protection</title>
<para>
The IOMMU on modern systems is used to mitigate against DMA attacks.
All I/O for devices capable of DMA is mapped into a private virtual
memory region.
The ACPI DMAR table is used to set up pre-boot DMA protection which
eliminates some firmware attacks.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-2 this should be available <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit">
Wikipedia IOMMU article
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.IntelBootguard">
<title>Intel BootGuard</title>
<para>
BootGuard is a processor feature that prevents the machine from running
firmware images not released by the system manufacturer.
It forms a root-of-trust by fusing in cryptographic keys into the processor
itself that are used to verify the Authenticated Code Modules found in
the SPI flash.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-1 verified boot must be enabled with ACM protection. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
<listitem>
<para>
For HSI-2 the error enforcement policy must be set to “immediate shutdown”. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://github.com/coreboot/coreboot/blob/master/src/soc/intel/jasperlake/include/soc/me.h">
Coreboot documentation
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.SuspendToRam">
<title>Suspend to RAM disabled</title>
<para>
Suspend to Ram (S3) keeps the raw contents of the DRAM refreshed when
the system is asleep.
This means that the memory modules can be physically removed and the
contents recovered, or a cold boot attack can be performed with a USB device.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-3 the firmware should be configured to prefer using suspend
to idle instead of suspend to ram or to not offer suspend to
RAM. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://en.wikipedia.org/wiki/Cold_boot_attack">
Wikipedia article on cold boot attacks
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.IntelCet">
<title>Intel CET Available</title>
<para>
Control enforcement technology is available on new Intel platforms and
prevents exploits from hijacking the control-flow transfer instructions
for both forward-edge (indirect call/jmp) and back-edge transfer (ret).
</para>
<itemizedlist>
<listitem>
<para>
For HSI-3 this should be available and enabled <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf">
Intel CET Technology Preview
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.EncryptedRam">
<title>DRAM total memory encryption (TME)</title>
<para>
Total memory encryption technology is used by the firmware on supported
SOCs to encrypt all data on external memory buses.
It mitigates against an attacker being able to capture memory data while
the system is running or to capture memory by removing a DRAM chip.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-4 this should be supported and enabled <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://software.intel.com/content/www/us/en/develop/blogs/intel-releases-new-technology-specification-for-memory-encryption.html">
Intel TME Press Release
</ulink>
</listitem>0
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.IntelSmap">
<title>Supervisor Mode Access Prevention</title>
<para>
Without Supervisor Mode Access Prevention, the supervisor code usually
has full read and write access to user-space memory mappings.
This can make exploits easier to write, as it allows the kernel to
access user-space memory when it did not intend to.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-4 the SMAP and SMEP features should be available on the CPU. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention">
Wikipedia SMAP Article
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.Iommu">
<title>Kernel DMA protection</title>
<para>
The IOMMU on modern systems is used to mitigate against DMA attacks.
All I/O for devices capable of DMA is mapped into a private virtual
memory region.
Common implementations are Intel VT-d and AMD-Vi.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-2 this should be available for use. <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
<note>
<para>
See also:
<itemizedlist>
<listitem>
<ulink url="https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit">
Wikipedia IOMMU article
</ulink>
</listitem>
</itemizedlist>
</para>
</note>
</refsect3>
<refsect3 id="org.fwupd.hsi.SuspendToIdle">
<title>Suspend-to-Idle</title>
<para>
The platform should be set up with Suspend-to-Idle as the default S3
sleep state.
</para>
<itemizedlist>
<listitem>
<para>
For HSI-3 this should be set <emphasis>v1.5.0</emphasis>
</para>
</listitem>
</itemizedlist>
</refsect3>
<refsect1 id="conclusions">
<title>Conclusion</title>
<para>
Any system with a Host Security ID of <code>0</code> can easily be
modified from userspace.
PCs with confidential documents should have a <code>HSI:3</code> or
higher level of protection.
In a graphical tool that would show details about the computer (such as
GNOME Control Centers details tab) the OS could display a field
indicating Host Security ID.
The ID should be shown with an alert color if the security is not at
least <code>HSI:1</code> or the suffix is <code>!</code>.
</para>
<para>
On Linux <code>fwupd</code> is used to enumerate and update firmware.
It exports a property <code>HostSecurityId</code> and a
<code>GetHostSecurityAttrs()</code> method.
The attributes are supposed to represent the <emphasis>system as a whole</emphasis>
but individual (internal) devices are able to make a claim that they
worsened the state of the security of the system.
Certain attributes can “obsolete” other attributes.
An example is BIOSGuard will set obsoletes to <code>org.intel.prx</code>.
</para>
<para>
A plugin method gets called on each plugin which adds attributes directly
from the hardware or kernel.
Several attributes may be dependent upon the kernel performing measurements
and it will take time for these to be upstreamed.
In some cases security level measurements will only be possible on systems
with a newer kernel.
</para>
<para>
The long term goal is to increase the <code>HSI:x</code> level of systems
being sold to consumers.
By making some of the <code>HSI:x</code> attributes part of the LVFS
uploaded report we can allow users to compare vendors and models before
purchasing hardware.
</para>
</refsect1>
<refsect2 id="ommissions">
<title>Intentional Omissions</title>
</refsect2>
<refsect3 id="intel-sgx">
<title>Intel SGX</title>
<para>
This is not widely used as it has several high severity security issues.
</para>
</refsect3>
<refsect3 id="intel-mpx">
<title>Intel MPX</title>
<para>
MPX support was removed from GCC and the Linux kernel in 2019 and it is
now considered obsolete.
</para>
</refsect3>
<refsect1 id="further-work">
<title>Further Work</title>
<para>
More internal and external devices should be factored into the security
equation.
For now the focus for further tests should be around internal device
firmware as it is what can be most directly controlled by fwupd and the
hardware manufacturer.
</para>
<para>
Security conscious manufacturers are actively participating in the
development of future initiatives in the Trusted Computing Group (TCG).
As those become ratified standards that are available in hardware,
there are opportunities for synergy with this specification.
</para>
</refsect1>
</partintro>
</reference>

View File

@ -5,6 +5,11 @@ gnome.gtkdoc(
join_paths(meson.source_root(), 'libfwupdplugin'),
join_paths(meson.build_root(), 'libfwupd'),
join_paths(meson.build_root(), 'libfwupdplugin'),
join_paths(meson.current_source_dir()),
],
content_files : [
'tutorial.xml',
'hsi.xml',
],
main_xml : 'fwupd-docs.xml',
install : true

402
docs/tutorial.xml Normal file
View File

@ -0,0 +1,402 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
<reference id="tutorial">
<title>Plugin Tutorial</title>
<partintro>
<section>
<title>Introduction</title>
<para>
At the heart of fwupd is a plugin loader that gets run at startup,
when devices get hotplugged and when updates are done.
The idea is we have lots of small plugins that each do one thing, and
are ordered by dependencies against each other at runtime.
Using plugins we can add support for new hardware or new policies
without making big changes all over the source tree.
</para>
<para>
There are broadly 3 types of plugin methods:
</para>
<itemizedlist>
<listitem>
<para>
<emphasis role="strong">Mechanism</emphasis>: Upload binary data
into a specific hardware device.
</para>
</listitem>
<listitem>
<para>
<emphasis role="strong">Policy</emphasis>: Control the system when
updates are happening, e.g. preventing the user from powering-off.
</para>
</listitem>
<listitem>
<para>
<emphasis role="strong">Helpers</emphasis>: Providing more
metadata about devices, for instance handling device quirks.
</para>
</listitem>
</itemizedlist>
<para>
In general, building things out-of-tree isn't something that we think is
a very good idea; the API and ABI <emphasis>internal</emphasis> to fwupd is still
changing and there's a huge benefit to getting plugins upstream where
they can undergo review and be ported as the API adapts.
For this reason we don't install the plugin headers onto the system,
although you can of course just install the <code>.so</code> binary file
manually.
</para>
<para>
A plugin only needs to define the vfuncs that are required, and the
plugin name is taken automatically from the suffix of the
<filename>.so</filename> file.
</para>
<example>
<title>A sample plugin</title>
<programlisting>
/*
* Copyright (C) 2017 Richard Hughes
*/
#include &lt;fu-plugin.h&gt;
#include &lt;fu-plugin-vfuncs.h&gt;
struct FuPluginData {
gpointer proxy;
};
void
fu_plugin_initialize (FuPlugin *plugin)
{
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_RUN_BEFORE, "dfu");
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
}
void
fu_plugin_destroy (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
destroy_proxy (data->proxy);
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
data->proxy = create_proxy ();
if (data->proxy == NULL) {
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED,
"failed to create proxy");
return FALSE;
}
return TRUE;
}
</programlisting>
</example>
<para>
We have to define when our plugin is run in reference to other plugins,
in this case, making sure we run before the <code>dfu</code> plugin.
For most plugins it does not matter in what order they are run and
this information is not required.
</para>
</section>
<section>
<title>Creating an abstract device</title>
<para>
This section shows how you would create a device which is exported
to the daemon and thus can be queried and updated by the client software.
The example here is all hardcoded, and a true plugin would have to
derive the details about the <code>FuDevice</code> from the hardware,
for example reading data from <code>sysfs</code> or <code>/dev</code>.
</para>
<example>
<title>Example adding a custom device</title>
<programlisting>
#include &lt;fu-plugin.h&gt;
gboolean
fu_plugin_coldplug (FuPlugin *plugin, GError **error)
{
g_autoptr(FuDevice) dev = NULL;
fu_device_set_id (dev, "dummy-1:2:3");
fu_device_add_guid (dev, "2d47f29b-83a2-4f31-a2e8-63474f4d4c2e");
fu_device_set_version (dev, "1.2.3");
fu_device_get_version_lowest (dev, "1.2.2");
fu_device_get_version_bootloader (dev, "0.1.2");
fu_device_add_icon (dev, "computer");
fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
fu_plugin_device_add (plugin, dev);
return TRUE;
}
</programlisting>
</example>
<para>
This shows a lot of the plugin architecture in action. Some notable points:
</para>
<itemizedlist>
<listitem>
<para>
The device ID (<code>dummy-1:2:3</code>) has to be unique on the
system between all plugins, so including the plugin name as a
prefix is probably a good idea.
</para>
</listitem>
<listitem>
<para>
The GUID value can be generated automatically using
<code>fu_device_add_guid(dev,"some-identifier")</code> but is quoted
here explicitly.
The GUID value has to match the <code>provides</code> value in the
<code>.metainfo.xml</code> file for the firmware update to succeed.
</para>
</listitem>
<listitem>
<para>
Setting a display name and an icon is a good idea in case the
GUI software needs to display the device to the user.
Icons can be specified using a full path, although icon theme names
should be preferred for most devices.
</para>
</listitem>
<listitem>
<para>
The <code>FWUPD_DEVICE_FLAG_UPDATABLE</code> flag tells the client
code that the device is in a state where it can be updated.
If the device needs to be in a special mode (e.g. a bootloader) then
the <code>FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER</code> flag can also be
used.
If the update should only be allowed when there is AC power available
to the computer (i.e. not on battery) then
<code>FWUPD_DEVICE_FLAG_REQUIRE_AC</code> should be used as well.
There are other flags and the API documentation should be used when
choosing what flags to use for each kind of device.
</para>
</listitem>
<listitem>
<para>
Setting the lowest allows client software to refuse downgrading
the device to specific versions.
This is required in case the upgrade migrates some kind of data-store
so as to be incompatible with previous versions.
Similarly, setting the version of the bootloader (if known) allows
the firmware to depend on a specific bootloader version, for instance
allowing signed firmware to only be installable on hardware with
a bootloader new enough to deploy it
</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Mechanism Plugins</title>
<para>
Although it would be a wonderful world if we could update all hardware
using a standard shared protocol this is not the universe we live in.
Using a mechanism like DFU or UpdateCapsule means that fwupd will just
work without requiring any special code, but for the real world we need
to support vendor-specific update protocols with layers of backwards
compatibility.
</para>
<para>
When a plugin has created a device that is <code>FWUPD_DEVICE_FLAG_UPDATABLE</code>
we can ask the daemon to update the device with a suitable
<code>.cab</code> file.
When this is done the daemon checks the update for compatibility with
the device, and then calls the vfuncs to update the device.
</para>
<example>
<title>Updating a device</title>
<programlisting>
gboolean
fu_plugin_update (FuPlugin *plugin,
FuDevice *dev,
GBytes *blob_fw,
FwupdInstallFlags flags,
GError **error)
{
gsize sz = 0;
guint8 *buf = g_bytes_get_data (blob_fw, &amp;sz);
/* write 'buf' of size 'sz' to the hardware */
return TRUE;
}
</programlisting>
</example>
<para>
It's important to note that the <code>blob_fw</code> is the binary
firmware file (e.g. <code>.dfu</code>) and <emphasis role="strong">not</emphasis>
the <code>.cab</code> binary data.
</para>
<para>
If <code>FWUPD_INSTALL_FLAG_FORCE</code> is used then the usual checks
done by the flashing process can be relaxed (e.g. checking for quirks),
but please don't brick the users hardware even if they ask you to.
</para>
</section>
<section>
<title>Policy Helpers</title>
<para>
For some hardware, we might want to do an action before or after
the actual firmware is squirted into the device.
This could be something as simple as checking the system battery
level is over a certain threshold, or it could be as complicated as
ensuring a vendor-specific GPIO is asserted when specific types
of hardware are updated.
</para>
<example>
<title>Running before a device update</title>
<programlisting>
gboolean
fu_plugin_update_prepare (FuPlugin *plugin, FuDevice *device, GError **error)
{
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_REQUIRE_AC &amp;&amp; !on_ac_power ()) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_AC_POWER_REQUIRED,
"Cannot install update "
"when not on AC power");
return FALSE;
}
return TRUE;
}
</programlisting>
</example>
<example>
<title>Running after a device update</title>
<programlisting>
gboolean
fu_plugin_update_cleanup (FuPlugin *plugin, FuDevice *device, GError **error)
{
return g_file_set_contents ("/var/lib/fwupd/something",
fu_device_get_id (device), -1, error);
}
</programlisting>
</example>
</section>
<section>
<title>Detaching to bootloader mode</title>
<para>
Some hardware can only be updated in a special bootloader mode, which
for most devices can be switched to automatically.
In some cases the user to do something manually, for instance
re-inserting the hardware with a secret button pressed.
</para>
<para>
Before the device update is performed the fwupd daemon runs an optional
<code>update_detach()</code> vfunc which switches the device to
bootloader mode.
After the update (or if the update fails) an the daemon runs an
optional <code>update_attach()</code> vfunc which should switch the
hardware back to runtime mode.
Finally an optional <code>update_reload()</code> vfunc is run to
get the new firmware version from the hardware.
</para>
<para>
The optional vfuncs are <emphasis role="strong">only</emphasis> run
on the plugin currently registered to handle the device ID, although
the registered plugin can change during the attach and detach phases.
</para>
<example>
<title>Running before a device update</title>
<programlisting>
gboolean
fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error)
{
if (hardware_in_bootloader)
return TRUE;
return _device_detach(device, error);
}
</programlisting>
</example>
<example>
<title>Running after a device update</title>
<programlisting>
gboolean
fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error)
{
if (!hardware_in_bootloader)
return TRUE;
return _device_attach(device, error);
}
</programlisting>
</example>
<example>
<title>Running after a device update on success</title>
<programlisting>
gboolean
fu_plugin_update_reload (FuPlugin *plugin, FuDevice *device, GError **error)
{
g_autofree gchar *version = _get_version(plugin, device, error);
if (version == NULL)
return FALSE;
fu_device_set_version(device, version);
return TRUE;
}
</programlisting>
</example>
</section>
<section>
<title>The Plugin Object Cache</title>
<para>
The fwupd daemon provides a per-plugin cache which allows objects
to be added, removed and queried using a specified key.
Objects added to the cache must be <code>GObject</code>s to enable the
cache objects to be properly refcounted.
</para>
</section>
<section>
<title>Debugging a Plugin</title>
<para>
If the fwupd daemon is started with <code>--plugin-verbose=$plugin</code>
then the environment variable <code>FWUPD_$PLUGIN_VERBOSE</code> is
set process-wide.
This allows plugins to detect when they should output detailed debugging
information that would normally be too verbose to keep in the journal.
For example, using <code>--plugin-verbose=logitech_hidpp</code> would set
<code>FWUPD_LOGITECH_HID_VERBOSE=1</code>.
</para>
</section>
<section>
<title>Using existing code to develop a plugin</title>
<para>
It is not usually possible to <em>share</em> a plugin codebase with
firmware update programs designed for other operating systems.
Matching the same rationale as the Linux kernel, trying to use one
code base between projects with a compatibility shim layer in-between
is real headache to maintain.
</para>
<para>
The general consensus is that trying to use a abstraction layer for
hardware is a very bad idea as you're not able to take advantage of the
platform specific helpers -- for instance quirk files and the custom
GType device creation.
The time the <em>vendor</em> saves by creating a shim layer and
importing existing source code into fwupd will be overtaken 100x by
<em>upstream</em> maintenance costs longer term, which isn't fair.
</para>
<para>
In a similar way, using C++ rather than GObject C means expanding the
test matrix to include clang in C++ mode and GNU g++ too.
It's also doubled the runtime requirements to now include both the C
standard library as well as the C++ standard library and increases the
dependency surface.
</para>
<para>
Most rewritten fwupd plugins at up to x10 smaller than the standalone
code as they can take advantage of helpers provided by fwupd rather
than re-implementing error handling, device quirking and data chunking.
</para>
</section>
</partintro>
</reference>

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include "fwupd-client.h"
#ifdef HAVE_GIO_UNIX
#include <gio/gunixinputstream.h>
#endif
#ifdef HAVE_GIO_UNIX
void fwupd_client_get_details_stream_async (FwupdClient *self,
GUnixInputStream *istr,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
void fwupd_client_install_stream_async (FwupdClient *self,
const gchar *device_id,
GUnixInputStream *istr,
const gchar *filename_hint,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
void fwupd_client_update_metadata_stream_async(FwupdClient *self,
const gchar *remote_id,
GUnixInputStream *istr,
GUnixInputStream *istr_sig,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
#endif

2054
libfwupd/fwupd-client-sync.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,173 @@
/*
* Copyright (C) 2016-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include "fwupd-client.h"
gboolean fwupd_client_connect (FwupdClient *self,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_devices (FwupdClient *self,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_plugins (FwupdClient *self,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_history (FwupdClient *self,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_releases (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_downgrades (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_upgrades (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_details (FwupdClient *self,
const gchar *filename,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_details_bytes (FwupdClient *self,
GBytes *bytes,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_verify (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_verify_update (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_unlock (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_modify_config (FwupdClient *self,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_activate (FwupdClient *self,
GCancellable *cancellable,
const gchar *device_id,
GError **error);
gboolean fwupd_client_clear_results (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
FwupdDevice *fwupd_client_get_results (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_host_security_attrs (FwupdClient *self,
GCancellable *cancellable,
GError **error);
FwupdDevice *fwupd_client_get_device_by_id (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_devices_by_guid (FwupdClient *self,
const gchar *guid,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_install (FwupdClient *self,
const gchar *device_id,
const gchar *filename,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_install_bytes (FwupdClient *self,
const gchar *device_id,
GBytes *bytes,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_install_release (FwupdClient *self,
FwupdDevice *device,
FwupdRelease *release,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_update_metadata (FwupdClient *self,
const gchar *remote_id,
const gchar *metadata_fn,
const gchar *signature_fn,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_update_metadata_bytes (FwupdClient *self,
const gchar *remote_id,
GBytes *metadata,
GBytes *signature,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_refresh_remote (FwupdClient *self,
FwupdRemote *remote,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_modify_remote (FwupdClient *self,
const gchar *remote_id,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_modify_device (FwupdClient *self,
const gchar *device_id,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
GError **error);
GHashTable *fwupd_client_get_report_metadata (FwupdClient *self,
GCancellable *cancellable,
GError **error);
GPtrArray *fwupd_client_get_remotes (FwupdClient *self,
GCancellable *cancellable,
GError **error);
FwupdRemote *fwupd_client_get_remote_by_id (FwupdClient *self,
const gchar *remote_id,
GCancellable *cancellable,
GError **error);
gchar **fwupd_client_get_approved_firmware (FwupdClient *self,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_set_approved_firmware (FwupdClient *self,
gchar **checksums,
GCancellable *cancellable,
GError **error);
gchar **fwupd_client_get_blocked_firmware (FwupdClient *self,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_set_blocked_firmware (FwupdClient *self,
gchar **checksums,
GCancellable *cancellable,
GError **error);
gchar *fwupd_client_self_sign (FwupdClient *self,
const gchar *value,
FwupdSelfSignFlags flags,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_set_feature_flags (FwupdClient *self,
FwupdFeatureFlags feature_flags,
GCancellable *cancellable,
GError **error);
GBytes *fwupd_client_download_bytes (FwupdClient *self,
const gchar *url,
FwupdClientDownloadFlags flags,
GCancellable *cancellable,
GError **error);
GBytes *fwupd_client_upload_bytes (FwupdClient *self,
const gchar *url,
const gchar *payload,
const gchar *signature,
FwupdClientUploadFlags flags,
GCancellable *cancellable,
GError **error);

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@
#include "fwupd-enums.h"
#include "fwupd-device.h"
#include "fwupd-plugin.h"
#include "fwupd-remote.h"
G_BEGIN_DECLS
@ -67,171 +68,319 @@ typedef enum {
} FwupdClientUploadFlags;
FwupdClient *fwupd_client_new (void);
gboolean fwupd_client_connect (FwupdClient *client,
void fwupd_client_connect_async (FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_connect_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_devices (FwupdClient *client,
void fwupd_client_get_devices_async (FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_devices_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_history (FwupdClient *client,
void fwupd_client_get_plugins_async (FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_plugins_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_releases (FwupdClient *client,
void fwupd_client_get_history_async (FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_history_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
void fwupd_client_get_releases_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_releases_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_downgrades (FwupdClient *client,
void fwupd_client_get_downgrades_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_downgrades_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_upgrades (FwupdClient *client,
void fwupd_client_get_upgrades_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_upgrades_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_details (FwupdClient *client,
const gchar *filename,
void fwupd_client_get_details_bytes_async (FwupdClient *self,
GBytes *bytes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_details_bytes_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_verify (FwupdClient *client,
void fwupd_client_verify_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_verify_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_verify_update (FwupdClient *client,
void fwupd_client_verify_update_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_verify_update_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_unlock (FwupdClient *client,
void fwupd_client_unlock_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_unlock_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_modify_config (FwupdClient *client,
void fwupd_client_modify_config_async (FwupdClient *self,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_modify_config_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_activate (FwupdClient *client,
GCancellable *cancellable,
const gchar *device_id,
GError **error);
gboolean fwupd_client_clear_results (FwupdClient *client,
void fwupd_client_activate_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_activate_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
FwupdDevice *fwupd_client_get_results (FwupdClient *client,
void fwupd_client_clear_results_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_clear_results_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
FwupdDevice *fwupd_client_get_device_by_id (FwupdClient *client,
void fwupd_client_get_results_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
FwupdDevice *fwupd_client_get_results_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GPtrArray *fwupd_client_get_devices_by_guid (FwupdClient *client,
void fwupd_client_get_host_security_attrs_async(FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_host_security_attrs_finish(FwupdClient *self,
GAsyncResult *res,
GError **error);
void fwupd_client_get_device_by_id_async (FwupdClient *self,
const gchar *device_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
FwupdDevice *fwupd_client_get_device_by_id_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
void fwupd_client_get_devices_by_guid_async (FwupdClient *self,
const gchar *guid,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_devices_by_guid_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_install (FwupdClient *client,
void fwupd_client_install_async (FwupdClient *self,
const gchar *device_id,
const gchar *filename,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_install_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_install_bytes (FwupdClient *client,
void fwupd_client_install_bytes_async (FwupdClient *self,
const gchar *device_id,
GBytes *bytes,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_install_bytes_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_install_release (FwupdClient *client,
void fwupd_client_install_release_async (FwupdClient *self,
FwupdDevice *device,
FwupdRelease *release,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_install_release_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_update_metadata (FwupdClient *client,
const gchar *remote_id,
const gchar *metadata_fn,
const gchar *signature_fn,
GCancellable *cancellable,
GError **error);
gboolean fwupd_client_update_metadata_bytes (FwupdClient *client,
void fwupd_client_update_metadata_bytes_async (FwupdClient *self,
const gchar *remote_id,
GBytes *metadata,
GBytes *signature,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_update_metadata_bytes_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_refresh_remote (FwupdClient *client,
void fwupd_client_refresh_remote_async (FwupdClient *self,
FwupdRemote *remote,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_refresh_remote_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_modify_remote (FwupdClient *client,
void fwupd_client_modify_remote_async (FwupdClient *self,
const gchar *remote_id,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_modify_remote_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_modify_device (FwupdClient *client,
void fwupd_client_modify_device_async (FwupdClient *self,
const gchar *device_id,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_modify_device_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
FwupdStatus fwupd_client_get_status (FwupdClient *client);
gboolean fwupd_client_get_tainted (FwupdClient *client);
gboolean fwupd_client_get_daemon_interactive (FwupdClient *client);
guint fwupd_client_get_percentage (FwupdClient *client);
const gchar *fwupd_client_get_daemon_version (FwupdClient *client);
const gchar *fwupd_client_get_host_product (FwupdClient *client);
const gchar *fwupd_client_get_host_machine_id (FwupdClient *client);
GPtrArray *fwupd_client_get_remotes (FwupdClient *client,
void fwupd_client_get_report_metadata_async (FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GHashTable *fwupd_client_get_report_metadata_finish(FwupdClient *self,
GAsyncResult *res,
GError **error);
FwupdRemote *fwupd_client_get_remote_by_id (FwupdClient *client,
FwupdStatus fwupd_client_get_status (FwupdClient *self);
gboolean fwupd_client_get_tainted (FwupdClient *self);
gboolean fwupd_client_get_daemon_interactive (FwupdClient *self);
guint fwupd_client_get_percentage (FwupdClient *self);
const gchar *fwupd_client_get_daemon_version (FwupdClient *self);
const gchar *fwupd_client_get_host_product (FwupdClient *self);
const gchar *fwupd_client_get_host_machine_id (FwupdClient *self);
const gchar *fwupd_client_get_host_security_id (FwupdClient *self);
void fwupd_client_get_remotes_async (FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_remotes_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
void fwupd_client_get_remote_by_id_async (FwupdClient *self,
const gchar *remote_id,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
FwupdRemote *fwupd_client_get_remote_by_id_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gchar **fwupd_client_get_approved_firmware (FwupdClient *client,
void fwupd_client_get_approved_firmware_async(FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_approved_firmware_finish(FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_set_approved_firmware (FwupdClient *client,
gchar **checksums,
void fwupd_client_set_approved_firmware_async (FwupdClient *self,
GPtrArray *checksums,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_set_approved_firmware_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gchar **fwupd_client_get_blocked_firmware (FwupdClient *client,
void fwupd_client_get_blocked_firmware_async(FwupdClient *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GPtrArray *fwupd_client_get_blocked_firmware_finish(FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_set_blocked_firmware (FwupdClient *client,
gchar **checksums,
void fwupd_client_set_blocked_firmware_async (FwupdClient *self,
GPtrArray *checksums,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_set_blocked_firmware_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gchar *fwupd_client_self_sign (FwupdClient *client,
void fwupd_client_self_sign_async (FwupdClient *self,
const gchar *value,
FwupdSelfSignFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gchar *fwupd_client_self_sign_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_set_feature_flags (FwupdClient *client,
void fwupd_client_set_feature_flags_async (FwupdClient *self,
FwupdFeatureFlags feature_flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
gboolean fwupd_client_set_feature_flags_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
void fwupd_client_set_user_agent (FwupdClient *client,
void fwupd_client_set_user_agent (FwupdClient *self,
const gchar *user_agent);
void fwupd_client_set_user_agent_for_package(FwupdClient *client,
void fwupd_client_set_user_agent_for_package(FwupdClient *self,
const gchar *package_name,
const gchar *package_version);
GBytes *fwupd_client_download_bytes (FwupdClient *client,
void fwupd_client_download_bytes_async (FwupdClient *self,
const gchar *url,
FwupdClientDownloadFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GBytes *fwupd_client_download_bytes_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
GBytes *fwupd_client_upload_bytes (FwupdClient *client,
void fwupd_client_upload_bytes_async (FwupdClient *self,
const gchar *url,
const gchar *payload,
const gchar *signature,
FwupdClientUploadFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GBytes *fwupd_client_upload_bytes_finish (FwupdClient *self,
GAsyncResult *res,
GError **error);
gboolean fwupd_client_ensure_networking (FwupdClient *client,
gboolean fwupd_client_ensure_networking (FwupdClient *self,
GError **error);
G_END_DECLS

View File

@ -6,7 +6,7 @@
#pragma once
#include <glib.h>
#include <gio/gio.h>
#ifdef HAVE_GIO_UNIX
#include <gio/gunixinputstream.h>
@ -21,6 +21,14 @@ GVariant *fwupd_hash_kv_to_variant (GHashTable *hash);
GHashTable *fwupd_variant_to_hash_kv (GVariant *dict);
gchar *fwupd_build_user_agent_system (void);
void fwupd_input_stream_read_bytes_async (GInputStream *stream,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data);
GBytes *fwupd_input_stream_read_bytes_finish (GInputStream *stream,
GAsyncResult *res,
GError **error);
#ifdef HAVE_GIO_UNIX
GUnixInputStream *fwupd_unix_input_stream_from_bytes (GBytes *bytes,
GError **error);

View File

@ -169,7 +169,6 @@ fwupd_get_os_release (GError **error)
/* find the correct file */
for (guint i = 0; paths[i] != NULL; i++) {
g_debug ("looking for os-release at %s", paths[i]);
if (g_file_test (paths[i], G_FILE_TEST_EXISTS)) {
filename = paths[i];
break;
@ -941,6 +940,96 @@ fwupd_variant_to_hash_kv (GVariant *dict)
return hash;
}
static void
fwupd_input_stream_read_bytes_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
GByteArray *bufarr;
GInputStream *stream = G_INPUT_STREAM (source);
g_autoptr(GBytes) bytes = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GTask) task = G_TASK (user_data);
#if GLIB_CHECK_VERSION(2, 64, 0)
guint8 *buf;
gsize bufsz = 0;
#endif
/* read buf */
bytes = g_input_stream_read_bytes_finish (stream, res, &error);
if (bytes == NULL) {
g_task_return_error (task, g_steal_pointer (&error));
return;
}
/* add bytes to buffer */
bufarr = g_task_get_task_data (task);
if (g_bytes_get_size (bytes) > 0) {
GCancellable *cancellable = g_task_get_cancellable (task);
g_debug ("add %u", (guint) g_bytes_get_size (bytes));
g_byte_array_append (bufarr,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes));
g_input_stream_read_bytes_async (g_steal_pointer (&stream),
256 * 1024, /* bigger chunk */
G_PRIORITY_DEFAULT,
cancellable,
fwupd_input_stream_read_bytes_cb,
g_steal_pointer (&task));
return;
}
/* success */
#if GLIB_CHECK_VERSION(2, 64, 0)
buf = g_byte_array_steal (bufarr, &bufsz);
g_task_return_pointer (task,
g_bytes_new_take (buf, bufsz),
(GDestroyNotify) g_bytes_unref);
#else
g_task_return_pointer (task,
g_bytes_new (bufarr->data, bufarr->len),
(GDestroyNotify) g_bytes_unref);
#endif
}
/**
* fwupd_input_stream_read_bytes_async: (skip):
**/
void
fwupd_input_stream_read_bytes_async (GInputStream *stream,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer callback_data)
{
g_autoptr(GTask) task = NULL;
g_return_if_fail (G_IS_INPUT_STREAM (stream));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
task = g_task_new (stream, cancellable, callback, callback_data);
g_task_set_task_data (task, g_byte_array_new (), (GDestroyNotify) g_byte_array_unref);
g_input_stream_read_bytes_async (stream,
64 * 1024, /* small */
G_PRIORITY_DEFAULT,
cancellable,
fwupd_input_stream_read_bytes_cb,
g_steal_pointer (&task));
}
/**
* fwupd_input_stream_read_bytes_finish: (skip):
**/
GBytes *
fwupd_input_stream_read_bytes_finish (GInputStream *stream,
GAsyncResult *res,
GError **error)
{
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
g_return_val_if_fail (g_task_is_valid (res, stream), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
return g_task_propagate_pointer (G_TASK(res), error);
}
#ifdef HAVE_GIO_UNIX
/**
* fwupd_unix_input_stream_from_bytes: (skip):

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2017 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2015-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@ -39,6 +39,7 @@ typedef struct {
gchar *name;
gchar *serial;
gchar *summary;
gchar *branch;
gchar *description;
gchar *vendor;
gchar *vendor_id;
@ -62,7 +63,7 @@ typedef struct {
gchar *update_image;
FwupdStatus status;
GPtrArray *releases;
FwupdDevice *parent;
FwupdDevice *parent; /* noref */
} FwupdDevicePrivate;
enum {
@ -71,6 +72,7 @@ enum {
PROP_FLAGS,
PROP_PROTOCOL,
PROP_STATUS,
PROP_PARENT,
PROP_LAST
};
@ -172,6 +174,42 @@ fwupd_device_set_summary (FwupdDevice *device, const gchar *summary)
priv->summary = g_strdup (summary);
}
/**
* fwupd_device_get_branch:
* @device: A #FwupdDevice
*
* Gets the current device branch.
*
* Returns: the device branch, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_device_get_branch (FwupdDevice *device)
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_val_if_fail (FWUPD_IS_DEVICE (device), NULL);
return priv->branch;
}
/**
* fwupd_device_set_branch:
* @device: A #FwupdDevice
* @branch: the device one line branch
*
* Sets the current device branch.
*
* Since: 1.5.0
**/
void
fwupd_device_set_branch (FwupdDevice *device, const gchar *branch)
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
g_free (priv->branch);
priv->branch = g_strdup (branch);
}
/**
* fwupd_device_get_serial:
* @device: A #FwupdDevice
@ -311,10 +349,40 @@ void
fwupd_device_set_parent (FwupdDevice *device, FwupdDevice *parent)
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
FwupdDevicePrivate *priv_parent = GET_PRIVATE (parent);
g_return_if_fail (FWUPD_IS_DEVICE (device));
g_set_object (&priv->parent, parent);
g_ptr_array_add (priv_parent->children, g_object_ref (device));
if (priv->parent != NULL)
g_object_remove_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
if (parent != NULL)
g_object_add_weak_pointer (G_OBJECT (parent), (gpointer *) &priv->parent);
priv->parent = parent;
/* this is what goes over D-Bus */
fwupd_device_set_parent_id (device, parent != NULL ? fwupd_device_get_id (parent) : NULL);
}
/**
* fwupd_device_add_child:
* @self: A #FwupdDevice
* @child: Another #FwupdDevice
*
* Adds a child device. An child device is logically linked to the primary
* device in some way.
*
* Since: 1.5.1
**/
void
fwupd_device_add_child (FwupdDevice *device, FwupdDevice *child)
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
/* add if the child does not already exist */
for (guint i = 0; i < priv->children->len; i++) {
FwupdDevice *devtmp = g_ptr_array_index (priv->children, i);
if (devtmp == child)
return;
}
g_ptr_array_add (priv->children, g_object_ref (child));
}
/**
@ -1098,7 +1166,6 @@ fwupd_device_get_created (FwupdDevice *device)
return priv->created;
}
/**
* fwupd_device_set_created:
* @device: A #FwupdDevice
@ -1190,6 +1257,8 @@ fwupd_device_incorporate (FwupdDevice *self, FwupdDevice *donor)
fwupd_device_set_serial (self, priv_donor->serial);
if (priv->summary == NULL)
fwupd_device_set_summary (self, priv_donor->summary);
if (priv->branch == NULL)
fwupd_device_set_branch (self, priv_donor->branch);
if (priv->vendor == NULL)
fwupd_device_set_vendor (self, priv_donor->vendor);
if (priv->vendor_id == NULL)
@ -1325,6 +1394,11 @@ fwupd_device_to_variant_full (FwupdDevice *device, FwupdDeviceFlags flags)
FWUPD_RESULT_KEY_SUMMARY,
g_variant_new_string (priv->summary));
}
if (priv->branch != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_BRANCH,
g_variant_new_string (priv->branch));
}
if (priv->checksums->len > 0) {
g_autoptr(GString) str = g_string_new ("");
for (guint i = 0; i < priv->checksums->len; i++) {
@ -1537,6 +1611,10 @@ fwupd_device_from_key_value (FwupdDevice *device, const gchar *key, GVariant *va
fwupd_device_set_summary (device, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_BRANCH) == 0) {
fwupd_device_set_branch (device, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_DESCRIPTION) == 0) {
fwupd_device_set_description (device, g_variant_get_string (value, NULL));
return;
@ -2037,6 +2115,7 @@ fwupd_device_to_json (FwupdDevice *device, JsonBuilder *builder)
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_SERIAL, priv->serial);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_BRANCH, priv->branch);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_PROTOCOL, priv->protocol);
if (priv->flags != FWUPD_DEVICE_FLAG_NONE) {
@ -2173,6 +2252,7 @@ fwupd_device_to_string (FwupdDevice *device)
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_SERIAL, priv->serial);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_BRANCH, priv->branch);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_PROTOCOL, priv->protocol);
fwupd_pad_kv_dfl (str, FWUPD_RESULT_KEY_FLAGS, priv->flags);
@ -2248,6 +2328,9 @@ fwupd_device_get_property (GObject *object, guint prop_id,
case PROP_STATUS:
g_value_set_uint (value, priv->status);
break;
case PROP_PARENT:
g_value_set_object (value, priv->parent);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -2272,6 +2355,9 @@ fwupd_device_set_property (GObject *object, guint prop_id,
case PROP_STATUS:
fwupd_device_set_status (self, g_value_get_uint (value));
break;
case PROP_PARENT:
fwupd_device_set_parent (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -2316,6 +2402,13 @@ fwupd_device_class_init (FwupdDeviceClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_STATUS, pspec);
pspec = g_param_spec_object ("parent", NULL, NULL,
FWUPD_TYPE_DEVICE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_PARENT, pspec);
}
static void
@ -2337,13 +2430,14 @@ fwupd_device_finalize (GObject *object)
FwupdDevicePrivate *priv = GET_PRIVATE (device);
if (priv->parent != NULL)
g_object_unref (priv->parent);
g_object_remove_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
g_free (priv->description);
g_free (priv->id);
g_free (priv->parent_id);
g_free (priv->name);
g_free (priv->serial);
g_free (priv->summary);
g_free (priv->branch);
g_free (priv->vendor);
g_free (priv->vendor_id);
g_free (priv->plugin);
@ -2439,8 +2533,10 @@ fwupd_device_array_ensure_parents (GPtrArray *devices)
if (parent_id != NULL) {
FwupdDevice *dev_tmp;
dev_tmp = g_hash_table_lookup (devices_by_id, parent_id);
if (dev_tmp != NULL)
if (dev_tmp != NULL) {
fwupd_device_add_child (dev_tmp, dev);
fwupd_device_set_parent (dev, dev_tmp);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2017 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2015-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@ -41,6 +41,8 @@ void fwupd_device_set_parent_id (FwupdDevice *device,
FwupdDevice *fwupd_device_get_parent (FwupdDevice *device);
void fwupd_device_set_parent (FwupdDevice *device,
FwupdDevice *parent);
void fwupd_device_add_child (FwupdDevice *device,
FwupdDevice *child);
GPtrArray *fwupd_device_get_children (FwupdDevice *device);
const gchar *fwupd_device_get_name (FwupdDevice *device);
void fwupd_device_set_name (FwupdDevice *device,
@ -51,6 +53,9 @@ void fwupd_device_set_serial (FwupdDevice *device,
const gchar *fwupd_device_get_summary (FwupdDevice *device);
void fwupd_device_set_summary (FwupdDevice *device,
const gchar *summary);
const gchar *fwupd_device_get_branch (FwupdDevice *device);
void fwupd_device_set_branch (FwupdDevice *device,
const gchar *branch);
const gchar *fwupd_device_get_description (FwupdDevice *device);
void fwupd_device_set_description (FwupdDevice *device,
const gchar *description);

View File

@ -1,11 +1,13 @@
/*
* Copyright (C) 2016-2018 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2016-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <glib.h>
G_BEGIN_DECLS
#define FWUPD_RESULT_KEY_APPSTREAM_ID "AppstreamId" /* s */
@ -23,6 +25,8 @@ G_BEGIN_DECLS
#define FWUPD_RESULT_KEY_FLAGS "Flags" /* t */
#define FWUPD_RESULT_KEY_FLASHES_LEFT "FlashesLeft" /* u */
#define FWUPD_RESULT_KEY_URGENCY "Urgency" /* u */
#define FWUPD_RESULT_KEY_HSI_LEVEL "HsiLevel" /* u */
#define FWUPD_RESULT_KEY_HSI_RESULT "HsiResult" /* u */
#define FWUPD_RESULT_KEY_INSTALL_DURATION "InstallDuration" /* u */
#define FWUPD_RESULT_KEY_GUID "Guid" /* as */
#define FWUPD_RESULT_KEY_INSTANCE_IDS "InstanceIds" /* as */
@ -43,6 +47,7 @@ G_BEGIN_DECLS
#define FWUPD_RESULT_KEY_SIZE "Size" /* t */
#define FWUPD_RESULT_KEY_STATUS "Status" /* u */
#define FWUPD_RESULT_KEY_SUMMARY "Summary" /* s */
#define FWUPD_RESULT_KEY_BRANCH "Branch" /* s */
#define FWUPD_RESULT_KEY_TRUST_FLAGS "TrustFlags" /* t */
#define FWUPD_RESULT_KEY_UPDATE_MESSAGE "UpdateMessage" /* s */
#define FWUPD_RESULT_KEY_UPDATE_IMAGE "UpdateImage" /* s */

View File

@ -197,6 +197,10 @@ fwupd_device_flag_to_string (FwupdDeviceFlags device_flag)
return "updatable-hidden";
if (device_flag == FWUPD_DEVICE_FLAG_SKIPS_RESTART)
return "skips-restart";
if (device_flag == FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES)
return "has-multiple-branches";
if (device_flag == FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL)
return "backup-before-install";
if (device_flag == FWUPD_DEVICE_FLAG_UNKNOWN)
return "unknown";
return NULL;
@ -295,6 +299,88 @@ fwupd_device_flag_from_string (const gchar *device_flag)
return FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN;
if (g_strcmp0 (device_flag, "skips-restart") == 0)
return FWUPD_DEVICE_FLAG_SKIPS_RESTART;
if (g_strcmp0 (device_flag, "has-multiple-branches") == 0)
return FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES;
if (g_strcmp0 (device_flag, "backup-before-install") == 0)
return FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL;
return FWUPD_DEVICE_FLAG_UNKNOWN;
}
/**
* fwupd_plugin_flag_to_string:
* @plugin_flag: A #FwupdPluginFlags, e.g. %FWUPD_DEVICE_FLAG_REQUIRE_AC
*
* Converts a #FwupdDeviceFlags to a string.
*
* Return value: identifier string
*
* Since: 1.5.0
**/
const gchar *
fwupd_plugin_flag_to_string (FwupdPluginFlags plugin_flag)
{
if (plugin_flag == FWUPD_DEVICE_FLAG_NONE)
return "none";
if (plugin_flag == FWUPD_PLUGIN_FLAG_DISABLED)
return "disabled";
if (plugin_flag == FWUPD_PLUGIN_FLAG_USER_WARNING)
return "user-warning";
if (plugin_flag == FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE)
return "clear-updatable";
if (plugin_flag == FWUPD_PLUGIN_FLAG_NO_HARDWARE)
return "no-hardware";
if (plugin_flag == FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED)
return "capsules-unsupported";
if (plugin_flag == FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED)
return "unlock-required";
if (plugin_flag == FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED)
return "efivar-not-mounted";
if (plugin_flag == FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND)
return "esp-not-found";
if (plugin_flag == FWUPD_PLUGIN_FLAG_LEGACY_BIOS)
return "legacy-bios";
if (plugin_flag == FWUPD_PLUGIN_FLAG_FAILED_OPEN)
return "failed-open";
if (plugin_flag == FWUPD_DEVICE_FLAG_UNKNOWN)
return "unknown";
return NULL;
}
/**
* fwupd_plugin_flag_from_string:
* @plugin_flag: A string, e.g. `require-ac`
*
* Converts a string to a #FwupdPluginFlags.
*
* Return value: enumerated value
*
* Since: 1.5.0
**/
FwupdPluginFlags
fwupd_plugin_flag_from_string (const gchar *plugin_flag)
{
if (g_strcmp0 (plugin_flag, "none") == 0)
return FWUPD_DEVICE_FLAG_NONE;
if (g_strcmp0 (plugin_flag, "disabled") == 0)
return FWUPD_PLUGIN_FLAG_DISABLED;
if (g_strcmp0 (plugin_flag, "user-warning") == 0)
return FWUPD_PLUGIN_FLAG_USER_WARNING;
if (g_strcmp0 (plugin_flag, "clear-updatable") == 0)
return FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE;
if (g_strcmp0 (plugin_flag, "no-hardware") == 0)
return FWUPD_PLUGIN_FLAG_NO_HARDWARE;
if (g_strcmp0 (plugin_flag, "capsules-unsupported") == 0)
return FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED;
if (g_strcmp0 (plugin_flag, "unlock-required") == 0)
return FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED;
if (g_strcmp0 (plugin_flag, "efivar-not-mounted") == 0)
return FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED;
if (g_strcmp0 (plugin_flag, "esp-not-found") == 0)
return FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND;
if (g_strcmp0 (plugin_flag, "legacy-bios") == 0)
return FWUPD_PLUGIN_FLAG_LEGACY_BIOS;
if (g_strcmp0 (plugin_flag, "failed-open") == 0)
return FWUPD_PLUGIN_FLAG_FAILED_OPEN;
return FWUPD_DEVICE_FLAG_UNKNOWN;
}
@ -419,6 +505,8 @@ fwupd_feature_flag_to_string (FwupdFeatureFlags feature_flag)
return "detach-action";
if (feature_flag == FWUPD_FEATURE_FLAG_UPDATE_ACTION)
return "update-action";
if (feature_flag == FWUPD_FEATURE_FLAG_SWITCH_BRANCH)
return "switch-branch";
return NULL;
}
@ -443,6 +531,8 @@ fwupd_feature_flag_from_string (const gchar *feature_flag)
return FWUPD_FEATURE_FLAG_DETACH_ACTION;
if (g_strcmp0 (feature_flag, "update-action") == 0)
return FWUPD_FEATURE_FLAG_UPDATE_ACTION;
if (g_strcmp0 (feature_flag, "switch-branch") == 0)
return FWUPD_FEATURE_FLAG_SWITCH_BRANCH;
return FWUPD_FEATURE_FLAG_LAST;
}
@ -521,6 +611,8 @@ fwupd_release_flag_to_string (FwupdReleaseFlags release_flag)
return "blocked-version";
if (release_flag == FWUPD_RELEASE_FLAG_BLOCKED_APPROVAL)
return "blocked-approval";
if (release_flag == FWUPD_RELEASE_FLAG_IS_ALTERNATE_BRANCH)
return "is-alternate-branch";
return NULL;
}
@ -549,6 +641,8 @@ fwupd_release_flag_from_string (const gchar *release_flag)
return FWUPD_RELEASE_FLAG_BLOCKED_VERSION;
if (g_strcmp0 (release_flag, "blocked-approval") == 0)
return FWUPD_RELEASE_FLAG_BLOCKED_APPROVAL;
if (g_strcmp0 (release_flag, "is-alternate-branch") == 0)
return FWUPD_RELEASE_FLAG_IS_ALTERNATE_BRANCH;
return FWUPD_RELEASE_FLAG_NONE;
}
@ -578,7 +672,7 @@ fwupd_release_urgency_to_string (FwupdReleaseUrgency release_urgency)
/**
* fwupd_release_urgency_from_string:
* @release_urgency: A string, e.g. `trusted-payload`
* @release_urgency: A string, e.g. `low`
*
* Converts a string to an enumerated value.
*

View File

@ -70,6 +70,7 @@ typedef enum {
* @FWUPD_FEATURE_FLAG_CAN_REPORT: Can upload a report of the update back to the server
* @FWUPD_FEATURE_FLAG_DETACH_ACTION: Can perform detach action, typically showing text
* @FWUPD_FEATURE_FLAG_UPDATE_ACTION: Can perform update action, typically showing text
* @FWUPD_FEATURE_FLAG_SWITCH_BRANCH: Can switch the firmware branch
*
* The flags to the feature capabilities of the front-end client.
**/
@ -78,6 +79,7 @@ typedef enum {
FWUPD_FEATURE_FLAG_CAN_REPORT = 1 << 0, /* Since: 1.4.5 */
FWUPD_FEATURE_FLAG_DETACH_ACTION = 1 << 1, /* Since: 1.4.5 */
FWUPD_FEATURE_FLAG_UPDATE_ACTION = 1 << 2, /* Since: 1.4.5 */
FWUPD_FEATURE_FLAG_SWITCH_BRANCH = 1 << 3, /* Since: 1.5.0 */
/*< private >*/
FWUPD_FEATURE_FLAG_LAST
} FwupdFeatureFlags;
@ -88,7 +90,7 @@ typedef enum {
* @FWUPD_DEVICE_FLAG_INTERNAL: Device cannot be removed easily
* @FWUPD_DEVICE_FLAG_UPDATABLE: Device is updatable in this or any other mode
* @FWUPD_DEVICE_FLAG_ONLY_OFFLINE: Update can only be done from offline mode
* @FWUPD_DEVICE_FLAG_REQUIRE_AC: Requires AC power
* @FWUPD_DEVICE_FLAG_REQUIRE_AC: System requires external power source
* @FWUPD_DEVICE_FLAG_LOCKED: Is locked and can be unlocked
* @FWUPD_DEVICE_FLAG_SUPPORTED: Is found in current metadata
* @FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER: Requires a bootloader mode to be manually enabled by the user
@ -124,6 +126,8 @@ typedef enum {
* @FWUPD_DEVICE_FLAG_NO_GUID_MATCHING: Force an explicit ID match when adding devices to the device list
* @FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN: Device is updatable but should not be called by the client
* @FWUPD_DEVICE_FLAG_SKIPS_RESTART: Device relies upon activation or power cycle to load firmware
* @FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES: Device supports switching to a different stream of firmware
* @FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL: Device firmware should be saved before installing firmware
*
* The device flags.
**/
@ -166,7 +170,9 @@ typedef enum {
#define FWUPD_DEVICE_FLAG_ADD_COUNTERPART_GUIDS (1llu << 35) /* Since: 1.4.0 */
#define FWUPD_DEVICE_FLAG_NO_GUID_MATCHING (1llu << 36) /* Since: 1.4.1 */
#define FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN (1llu << 37) /* Since: 1.4.1 */
#define FWUPD_DEVICE_FLAG_SKIPS_RESTART (1llu << 38) /* Since: 1.4.5 */
#define FWUPD_DEVICE_FLAG_SKIPS_RESTART (1llu << 38) /* Since: 1.5.0 */
#define FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES (1llu << 39) /* Since: 1.5.0 */
#define FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL (1llu << 40) /* Since: 1.5.0 */
#define FWUPD_DEVICE_FLAG_UNKNOWN G_MAXUINT64 /* Since: 0.7.3 */
typedef guint64 FwupdDeviceFlags;
@ -179,6 +185,7 @@ typedef guint64 FwupdDeviceFlags;
* @FWUPD_RELEASE_FLAG_IS_DOWNGRADE: Is older than the device version
* @FWUPD_RELEASE_FLAG_BLOCKED_VERSION: Blocked as below device version-lowest
* @FWUPD_RELEASE_FLAG_BLOCKED_APPROVAL: Blocked as release not approved
* @FWUPD_RELEASE_FLAG_IS_ALTERNATE_BRANCH: Is an alternate branch of firmware
*
* The release flags.
**/
@ -189,6 +196,7 @@ typedef guint64 FwupdDeviceFlags;
#define FWUPD_RELEASE_FLAG_IS_DOWNGRADE (1u << 3) /* Since: 1.2.6 */
#define FWUPD_RELEASE_FLAG_BLOCKED_VERSION (1u << 4) /* Since: 1.2.6 */
#define FWUPD_RELEASE_FLAG_BLOCKED_APPROVAL (1u << 5) /* Since: 1.2.6 */
#define FWUPD_RELEASE_FLAG_IS_ALTERNATE_BRANCH (1u << 6) /* Since: 1.5.0 */
#define FWUPD_RELEASE_FLAG_UNKNOWN G_MAXUINT64 /* Since: 1.2.6 */
typedef guint64 FwupdReleaseFlags;
@ -212,6 +220,36 @@ typedef enum {
FWUPD_RELEASE_URGENCY_LAST
} FwupdReleaseUrgency;
/**
* FwupdPluginFlags:
* @FWUPD_PLUGIN_FLAG_NONE: No flags set
* @FWUPD_PLUGIN_FLAG_DISABLED: Disabled
* @FWUPD_PLUGIN_FLAG_USER_WARNING: Show the user a warning
* @FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE: Clear the UPDATABLE flag from devices
* @FWUPD_PLUGIN_FLAG_NO_HARDWARE: No hardware is found
* @FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED: UEFI UpdateCapsule are unsupported
* @FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED: Hardware unlock is required
* @FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED: The efivar filesystem is not found
* @FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND: The EFI ESP not found
* @FWUPD_PLUGIN_FLAG_LEGACY_BIOS: System running in legacy CSM mode
* @FWUPD_PLUGIN_FLAG_FAILED_OPEN: Failed to open plugin (missing dependency)
*
* The plugin flags.
**/
#define FWUPD_PLUGIN_FLAG_NONE (0u) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_DISABLED (1u << 0) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_USER_WARNING (1u << 1) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE (1u << 2) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_NO_HARDWARE (1u << 3) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED (1u << 4) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED (1u << 5) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED (1u << 6) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND (1u << 7) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_LEGACY_BIOS (1u << 8) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_FAILED_OPEN (1u << 9) /* Since: 1.5.0 */
#define FWUPD_PLUGIN_FLAG_UNKNOWN G_MAXUINT64 /* Since: 1.5.0 */
typedef guint64 FwupdPluginFlags;
/**
* FwupdInstallFlags:
* @FWUPD_INSTALL_FLAG_NONE: No flags set
@ -220,8 +258,12 @@ typedef enum {
* @FWUPD_INSTALL_FLAG_ALLOW_OLDER: Allow downgrading firmware
* @FWUPD_INSTALL_FLAG_FORCE: Force the update even if not a good idea
* @FWUPD_INSTALL_FLAG_NO_HISTORY: Do not write to the history database
* @FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH: Allow firmware branch switching
* @FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM: Ignore firmware CRCs and checksums
* @FWUPD_INSTALL_FLAG_IGNORE_VID_PID: Ignore firmware vendor and project checks
* @FWUPD_INSTALL_FLAG_IGNORE_POWER: Ignore requirement of external power source
*
* Flags to set when performing the firwmare update or install.
* Flags to set when performing the firmware update or install.
**/
typedef enum {
FWUPD_INSTALL_FLAG_NONE = 0, /* Since: 0.7.0 */
@ -230,6 +272,10 @@ typedef enum {
FWUPD_INSTALL_FLAG_ALLOW_OLDER = 1 << 2, /* Since: 0.7.0 */
FWUPD_INSTALL_FLAG_FORCE = 1 << 3, /* Since: 0.7.1 */
FWUPD_INSTALL_FLAG_NO_HISTORY = 1 << 4, /* Since: 1.0.8 */
FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH = 1 << 5, /* Since: 1.5.0 */
FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM = 1 << 6, /* Since: 1.5.0 */
FWUPD_INSTALL_FLAG_IGNORE_VID_PID = 1 << 7, /* Since: 1.5.0 */
FWUPD_INSTALL_FLAG_IGNORE_POWER = 1 << 8, /* Since: 1.5.0 */
/*< private >*/
FWUPD_INSTALL_FLAG_LAST
} FwupdInstallFlags;
@ -240,7 +286,7 @@ typedef enum {
* @FWUPD_SELF_SIGN_FLAG_ADD_TIMESTAMP: Add the timestamp to the detached signature
* @FWUPD_SELF_SIGN_FLAG_ADD_CERT: Add the certificate to the detached signature
*
* Flags to set when performing the firwmare update or install.
* Flags to set when performing the firmware update or install.
**/
typedef enum {
FWUPD_SELF_SIGN_FLAG_NONE = 0, /* Since: 1.2.6 */
@ -335,6 +381,8 @@ const gchar *fwupd_status_to_string (FwupdStatus status);
FwupdStatus fwupd_status_from_string (const gchar *status);
const gchar *fwupd_device_flag_to_string (FwupdDeviceFlags device_flag);
FwupdDeviceFlags fwupd_device_flag_from_string (const gchar *device_flag);
const gchar *fwupd_plugin_flag_to_string (FwupdPluginFlags plugin_flag);
FwupdPluginFlags fwupd_plugin_flag_from_string (const gchar *plugin_flag);
const gchar *fwupd_release_flag_to_string (FwupdReleaseFlags release_flag);
FwupdReleaseFlags fwupd_release_flag_from_string (const gchar *release_flag);
const gchar *fwupd_release_urgency_to_string (FwupdReleaseUrgency release_urgency);

View File

@ -0,0 +1,20 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <json-glib/json-glib.h>
#include "fwupd-plugin.h"
G_BEGIN_DECLS
GVariant *fwupd_plugin_to_variant (FwupdPlugin *plugin);
void fwupd_plugin_to_json (FwupdPlugin *plugin,
JsonBuilder *builder);
G_END_DECLS

484
libfwupd/fwupd-plugin.c Normal file
View File

@ -0,0 +1,484 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fwupd-enums-private.h"
#include "fwupd-plugin-private.h"
/**
* SECTION:fwupd-plugin
* @short_description: a hardware plugin
*
* An object that represents a fwupd plugin.
*
* See also: #FwupdRelease
*/
static void fwupd_plugin_finalize (GObject *object);
typedef struct {
gchar *name;
guint64 flags;
} FwupdPluginPrivate;
enum {
PROP_0,
PROP_NAME,
PROP_FLAGS,
PROP_LAST
};
G_DEFINE_TYPE_WITH_PRIVATE (FwupdPlugin, fwupd_plugin, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fwupd_plugin_get_instance_private (o))
/**
* fwupd_plugin_get_name:
* @plugin: A #FwupdPlugin
*
* Gets the plugin name.
*
* Returns: the plugin name, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_plugin_get_name (FwupdPlugin *plugin)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_val_if_fail (FWUPD_IS_PLUGIN (plugin), NULL);
return priv->name;
}
/**
* fwupd_plugin_set_name:
* @plugin: A #FwupdPlugin
* @name: the plugin name, e.g. `bios`
*
* Sets the plugin name.
*
* Since: 1.5.0
**/
void
fwupd_plugin_set_name (FwupdPlugin *plugin, const gchar *name)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_if_fail (FWUPD_IS_PLUGIN (plugin));
g_return_if_fail (name != NULL);
g_free (priv->name);
priv->name = g_strdup (name);
g_object_notify (G_OBJECT (plugin), "name");
}
/**
* fwupd_plugin_get_flags:
* @plugin: A #FwupdPlugin
*
* Gets the plugin flags.
*
* Returns: the plugin flags, or 0 if unset
*
* Since: 1.5.0
**/
guint64
fwupd_plugin_get_flags (FwupdPlugin *plugin)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_val_if_fail (FWUPD_IS_PLUGIN (plugin), 0);
return priv->flags;
}
/**
* fwupd_plugin_set_flags:
* @plugin: A #FwupdPlugin
* @flags: the plugin flags, e.g. %FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED
*
* Sets the plugin flags.
*
* Since: 1.5.0
**/
void
fwupd_plugin_set_flags (FwupdPlugin *plugin, guint64 flags)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_if_fail (FWUPD_IS_PLUGIN (plugin));
if (priv->flags == flags)
return;
priv->flags = flags;
g_object_notify (G_OBJECT (plugin), "flags");
}
/**
* fwupd_plugin_add_flag:
* @plugin: A #FwupdPlugin
* @flag: the #FwupdPluginFlags
*
* Adds a specific plugin flag to the plugin.
*
* Since: 1.5.0
**/
void
fwupd_plugin_add_flag (FwupdPlugin *plugin, FwupdPluginFlags flag)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_if_fail (FWUPD_IS_PLUGIN (plugin));
if (flag == 0)
return;
if ((priv->flags & flag) > 0)
return;
priv->flags |= flag;
g_object_notify (G_OBJECT (plugin), "flags");
}
/**
* fwupd_plugin_remove_flag:
* @plugin: A #FwupdPlugin
* @flag: the #FwupdPluginFlags
*
* Removes a specific plugin flag from the plugin.
*
* Since: 1.5.0
**/
void
fwupd_plugin_remove_flag (FwupdPlugin *plugin, FwupdPluginFlags flag)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_if_fail (FWUPD_IS_PLUGIN (plugin));
if (flag == 0)
return;
if ((priv->flags & flag) == 0)
return;
priv->flags &= ~flag;
g_object_notify (G_OBJECT (plugin), "flags");
}
/**
* fwupd_plugin_has_flag:
* @plugin: A #FwupdPlugin
* @flag: the #FwupdPluginFlags
*
* Finds if the plugin has a specific plugin flag.
*
* Returns: %TRUE if the flag is set
*
* Since: 1.5.0
**/
gboolean
fwupd_plugin_has_flag (FwupdPlugin *plugin, FwupdPluginFlags flag)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_val_if_fail (FWUPD_IS_PLUGIN (plugin), FALSE);
return (priv->flags & flag) > 0;
}
/**
* fwupd_plugin_to_variant:
* @plugin: A #FwupdPlugin
*
* Creates a GVariant from the plugin data omitting sensitive fields
*
* Returns: the GVariant, or %NULL for error
*
* Since: 1.5.0
**/
GVariant *
fwupd_plugin_to_variant (FwupdPlugin *plugin)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
GVariantBuilder builder;
g_return_val_if_fail (FWUPD_IS_PLUGIN (plugin), NULL);
/* create an array with all the metadata in */
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
if (priv->name != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_NAME,
g_variant_new_string (priv->name));
}
if (priv->flags > 0) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_FLAGS,
g_variant_new_uint64 (priv->flags));
}
return g_variant_new ("a{sv}", &builder);
}
static void
fwupd_plugin_from_key_value (FwupdPlugin *plugin, const gchar *key, GVariant *value)
{
if (g_strcmp0 (key, FWUPD_RESULT_KEY_NAME) == 0) {
fwupd_plugin_set_name (plugin, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_FLAGS) == 0) {
fwupd_plugin_set_flags (plugin, g_variant_get_uint64 (value));
return;
}
}
static void
fwupd_pad_kv_str (GString *str, const gchar *key, const gchar *value)
{
/* ignore */
if (key == NULL || value == NULL)
return;
g_string_append_printf (str, " %s: ", key);
for (gsize i = strlen (key); i < 20; i++)
g_string_append (str, " ");
g_string_append_printf (str, "%s\n", value);
}
static void
fwupd_pad_kv_dfl (GString *str, const gchar *key, guint64 plugin_flags)
{
g_autoptr(GString) tmp = g_string_new ("");
for (guint i = 0; i < 64; i++) {
if ((plugin_flags & ((guint64) 1 << i)) == 0)
continue;
g_string_append_printf (tmp, "%s|",
fwupd_plugin_flag_to_string ((guint64) 1 << i));
}
if (tmp->len == 0) {
g_string_append (tmp, fwupd_plugin_flag_to_string (0));
} else {
g_string_truncate (tmp, tmp->len - 1);
}
fwupd_pad_kv_str (str, key, tmp->str);
}
static void
fwupd_plugin_json_add_string (JsonBuilder *builder, const gchar *key, const gchar *str)
{
if (str == NULL)
return;
json_builder_set_member_name (builder, key);
json_builder_add_string_value (builder, str);
}
/**
* fwupd_plugin_to_json:
* @plugin: A #FwupdPlugin
* @builder: A #JsonBuilder
*
* Adds a fwupd plugin to a JSON builder
*
* Since: 1.5.0
**/
void
fwupd_plugin_to_json (FwupdPlugin *plugin, JsonBuilder *builder)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_return_if_fail (FWUPD_IS_PLUGIN (plugin));
g_return_if_fail (builder != NULL);
fwupd_plugin_json_add_string (builder, FWUPD_RESULT_KEY_NAME, priv->name);
if (priv->flags != FWUPD_PLUGIN_FLAG_NONE) {
json_builder_set_member_name (builder, FWUPD_RESULT_KEY_FLAGS);
json_builder_begin_array (builder);
for (guint i = 0; i < 64; i++) {
const gchar *tmp;
if ((priv->flags & ((guint64) 1 << i)) == 0)
continue;
tmp = fwupd_plugin_flag_to_string ((guint64) 1 << i);
json_builder_add_string_value (builder, tmp);
}
json_builder_end_array (builder);
}
}
/**
* fwupd_plugin_to_string:
* @plugin: A #FwupdPlugin
*
* Builds a text representation of the object.
*
* Returns: text, or %NULL for invalid
*
* Since: 1.5.0
**/
gchar *
fwupd_plugin_to_string (FwupdPlugin *plugin)
{
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
GString *str;
g_return_val_if_fail (FWUPD_IS_PLUGIN (plugin), NULL);
str = g_string_new (NULL);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_NAME, priv->name);
fwupd_pad_kv_dfl (str, FWUPD_RESULT_KEY_FLAGS, priv->flags);
return g_string_free (str, FALSE);
}
static void
fwupd_plugin_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
FwupdPlugin *self = FWUPD_PLUGIN (object);
FwupdPluginPrivate *priv = GET_PRIVATE (self);
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
case PROP_FLAGS:
g_value_set_uint64 (value, priv->flags);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
fwupd_plugin_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
FwupdPlugin *self = FWUPD_PLUGIN (object);
switch (prop_id) {
case PROP_NAME:
fwupd_plugin_set_name (self, g_value_get_string (value));
break;
case PROP_FLAGS:
fwupd_plugin_set_flags (self, g_value_get_uint64 (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
fwupd_plugin_class_init (FwupdPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->finalize = fwupd_plugin_finalize;
object_class->get_property = fwupd_plugin_get_property;
object_class->set_property = fwupd_plugin_set_property;
pspec = g_param_spec_string ("name", NULL, NULL, NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_NAME, pspec);
pspec = g_param_spec_uint64 ("flags", NULL, NULL,
FWUPD_PLUGIN_FLAG_NONE,
FWUPD_PLUGIN_FLAG_UNKNOWN,
FWUPD_PLUGIN_FLAG_NONE,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_FLAGS, pspec);
}
static void
fwupd_plugin_init (FwupdPlugin *plugin)
{
}
static void
fwupd_plugin_finalize (GObject *object)
{
FwupdPlugin *plugin = FWUPD_PLUGIN (object);
FwupdPluginPrivate *priv = GET_PRIVATE (plugin);
g_free (priv->name);
G_OBJECT_CLASS (fwupd_plugin_parent_class)->finalize (object);
}
static void
fwupd_plugin_set_from_variant_iter (FwupdPlugin *plugin, GVariantIter *iter)
{
GVariant *value;
const gchar *key;
while (g_variant_iter_next (iter, "{&sv}", &key, &value)) {
fwupd_plugin_from_key_value (plugin, key, value);
g_variant_unref (value);
}
}
/**
* fwupd_plugin_from_variant:
* @value: a #GVariant
*
* Creates a new plugin using packed data.
*
* Returns: (transfer full): a new #FwupdPlugin, or %NULL if @value was invalid
*
* Since: 1.5.0
**/
FwupdPlugin *
fwupd_plugin_from_variant (GVariant *value)
{
FwupdPlugin *plugin = NULL;
const gchar *type_string;
g_autoptr(GVariantIter) iter = NULL;
/* format from GetDetails */
type_string = g_variant_get_type_string (value);
if (g_strcmp0 (type_string, "(a{sv})") == 0) {
plugin = fwupd_plugin_new ();
g_variant_get (value, "(a{sv})", &iter);
fwupd_plugin_set_from_variant_iter (plugin, iter);
} else if (g_strcmp0 (type_string, "a{sv}") == 0) {
plugin = fwupd_plugin_new ();
g_variant_get (value, "a{sv}", &iter);
fwupd_plugin_set_from_variant_iter (plugin, iter);
} else {
g_warning ("type %s not known", type_string);
}
return plugin;
}
/**
* fwupd_plugin_array_from_variant:
* @value: a #GVariant
*
* Creates an array of new plugins using packed data.
*
* Returns: (transfer container) (element-type FwupdPlugin): plugins, or %NULL if @value was invalid
*
* Since: 1.5.0
**/
GPtrArray *
fwupd_plugin_array_from_variant (GVariant *value)
{
GPtrArray *array = NULL;
gsize sz;
g_autoptr(GVariant) untuple = NULL;
array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
untuple = g_variant_get_child_value (value, 0);
sz = g_variant_n_children (untuple);
for (guint i = 0; i < sz; i++) {
FwupdPlugin *plugin;
g_autoptr(GVariant) data = NULL;
data = g_variant_get_child_value (untuple, i);
plugin = fwupd_plugin_from_variant (data);
if (plugin == NULL)
continue;
g_ptr_array_add (array, plugin);
}
return array;
}
/**
* fwupd_plugin_new:
*
* Creates a new plugin.
*
* Returns: a new #FwupdPlugin
*
* Since: 1.5.0
**/
FwupdPlugin *
fwupd_plugin_new (void)
{
FwupdPlugin *plugin;
plugin = g_object_new (FWUPD_TYPE_PLUGIN, NULL);
return FWUPD_PLUGIN (plugin);
}

50
libfwupd/fwupd-plugin.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <glib-object.h>
#include "fwupd-enums.h"
G_BEGIN_DECLS
#define FWUPD_TYPE_PLUGIN (fwupd_plugin_get_type ())
G_DECLARE_DERIVABLE_TYPE (FwupdPlugin, fwupd_plugin, FWUPD, PLUGIN, GObject)
struct _FwupdPluginClass
{
GObjectClass parent_class;
/*< private >*/
void (*_fwupd_reserved1) (void);
void (*_fwupd_reserved2) (void);
void (*_fwupd_reserved3) (void);
void (*_fwupd_reserved4) (void);
void (*_fwupd_reserved5) (void);
void (*_fwupd_reserved6) (void);
void (*_fwupd_reserved7) (void);
};
FwupdPlugin *fwupd_plugin_new (void);
gchar *fwupd_plugin_to_string (FwupdPlugin *plugin);
const gchar *fwupd_plugin_get_name (FwupdPlugin *plugin);
void fwupd_plugin_set_name (FwupdPlugin *plugin,
const gchar *name);
guint64 fwupd_plugin_get_flags (FwupdPlugin *plugin);
void fwupd_plugin_set_flags (FwupdPlugin *plugin,
guint64 flags);
void fwupd_plugin_add_flag (FwupdPlugin *plugin,
FwupdPluginFlags flag);
void fwupd_plugin_remove_flag (FwupdPlugin *plugin,
FwupdPluginFlags flag);
gboolean fwupd_plugin_has_flag (FwupdPlugin *plugin,
FwupdPluginFlags flag);
FwupdPlugin *fwupd_plugin_from_variant (GVariant *value);
GPtrArray *fwupd_plugin_array_from_variant (GVariant *value);
G_END_DECLS

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2018 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2015-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@ -46,6 +46,7 @@ typedef struct {
gchar *name;
gchar *name_variant_suffix;
gchar *summary;
gchar *branch;
gchar *uri;
gchar *vendor;
gchar *version;
@ -934,6 +935,42 @@ fwupd_release_set_summary (FwupdRelease *release, const gchar *summary)
priv->summary = g_strdup (summary);
}
/**
* fwupd_release_get_branch:
* @release: A #FwupdRelease
*
* Gets the update branch.
*
* Returns: the alternate branch, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_release_get_branch (FwupdRelease *release)
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_val_if_fail (FWUPD_IS_RELEASE (release), NULL);
return priv->branch;
}
/**
* fwupd_release_set_branch:
* @release: A #FwupdRelease
* @branch: the update one line branch
*
* Sets the alternate branch.
*
* Since: 1.5.0
**/
void
fwupd_release_set_branch (FwupdRelease *release, const gchar *branch)
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
g_free (priv->branch);
priv->branch = g_strdup (branch);
}
/**
* fwupd_release_get_vendor:
* @release: A #FwupdRelease
@ -1354,6 +1391,11 @@ fwupd_release_to_variant (FwupdRelease *release)
FWUPD_RESULT_KEY_SUMMARY,
g_variant_new_string (priv->summary));
}
if (priv->branch != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_BRANCH,
g_variant_new_string (priv->branch));
}
if (priv->description != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_DESCRIPTION,
@ -1492,6 +1534,10 @@ fwupd_release_from_key_value (FwupdRelease *release, const gchar *key, GVariant
fwupd_release_set_summary (release, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_BRANCH) == 0) {
fwupd_release_set_branch (release, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_DESCRIPTION) == 0) {
fwupd_release_set_description (release, g_variant_get_string (value, NULL));
return;
@ -1675,6 +1721,7 @@ fwupd_release_to_json (FwupdRelease *release, JsonBuilder *builder)
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_REMOTE_ID, priv->remote_id);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_BRANCH, priv->branch);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_VERSION, priv->version);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_FILENAME, priv->filename);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_PROTOCOL, priv->protocol);
@ -1764,6 +1811,7 @@ fwupd_release_to_string (FwupdRelease *release)
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_REMOTE_ID, priv->remote_id);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_BRANCH, priv->branch);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VERSION, priv->version);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_FILENAME, priv->filename);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_PROTOCOL, priv->protocol);
@ -1844,6 +1892,7 @@ fwupd_release_finalize (GObject *object)
g_free (priv->name);
g_free (priv->name_variant_suffix);
g_free (priv->summary);
g_free (priv->branch);
g_free (priv->uri);
g_free (priv->homepage);
g_free (priv->details_url);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2018 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2015-2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@ -90,6 +90,9 @@ void fwupd_release_set_name_variant_suffix (FwupdRelease *release,
const gchar *fwupd_release_get_summary (FwupdRelease *release);
void fwupd_release_set_summary (FwupdRelease *release,
const gchar *summary);
const gchar *fwupd_release_get_branch (FwupdRelease *release);
void fwupd_release_set_branch (FwupdRelease *release,
const gchar *branch);
const gchar *fwupd_release_get_description (FwupdRelease *release);
void fwupd_release_set_description (FwupdRelease *release,
const gchar *description);

View File

@ -32,6 +32,7 @@ typedef struct {
gchar *id;
gchar *firmware_base_uri;
gchar *report_uri;
gchar *security_report_uri;
gchar *metadata_uri;
gchar *metadata_uri_sig;
gchar *username;
@ -50,6 +51,7 @@ typedef struct {
gchar **order_before;
gchar *remotes_dir;
gboolean automatic_reports;
gboolean automatic_security_reports;
} FwupdRemotePrivate;
enum {
@ -58,6 +60,7 @@ enum {
PROP_ENABLED,
PROP_APPROVAL_REQUIRED,
PROP_AUTOMATIC_REPORTS,
PROP_AUTOMATIC_SECURITY_REPORTS,
PROP_LAST
};
@ -252,6 +255,13 @@ fwupd_remote_set_report_uri (FwupdRemote *self, const gchar *report_uri)
priv->report_uri = g_strdup (report_uri);
}
static void
fwupd_remote_set_security_report_uri (FwupdRemote *self, const gchar *security_report_uri)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
priv->security_report_uri = g_strdup (security_report_uri);
}
/**
* fwupd_remote_kind_from_string:
* @kind: a string, e.g. `download`
@ -343,6 +353,7 @@ fwupd_remote_load_from_filename (FwupdRemote *self,
g_autofree gchar *order_after = NULL;
g_autofree gchar *order_before = NULL;
g_autofree gchar *report_uri = NULL;
g_autofree gchar *security_report_uri = NULL;
g_autoptr(GKeyFile) kf = NULL;
g_return_val_if_fail (FWUPD_IS_REMOTE (self), FALSE);
@ -415,8 +426,14 @@ fwupd_remote_load_from_filename (FwupdRemote *self,
if (report_uri != NULL && report_uri[0] != '\0')
fwupd_remote_set_report_uri (self, report_uri);
/* security reporting is optional */
security_report_uri = g_key_file_get_string (kf, group, "SecurityReportURI", NULL);
if (security_report_uri != NULL && security_report_uri[0] != '\0')
fwupd_remote_set_security_report_uri (self, security_report_uri);
/* automatic report uploading */
priv->automatic_reports = g_key_file_get_boolean (kf, group, "AutomaticReports", NULL);
priv->automatic_security_reports = g_key_file_get_boolean (kf, group, "AutomaticSecurityReports", NULL);
/* DOWNLOAD-type remotes */
if (priv->kind == FWUPD_REMOTE_KIND_DOWNLOAD) {
@ -879,6 +896,24 @@ fwupd_remote_get_report_uri (FwupdRemote *self)
return priv->report_uri;
}
/**
* fwupd_remote_get_security_report_uri:
* @self: A #FwupdRemote
*
* Gets the URI for the security report.
*
* Returns: (transfer none): a URI, or %NULL for invalid.
*
* Since: 1.5.0
**/
const gchar *
fwupd_remote_get_security_report_uri (FwupdRemote *self)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
return priv->security_report_uri;
}
/**
* fwupd_remote_get_metadata_uri:
* @self: A #FwupdRemote
@ -1069,6 +1104,24 @@ fwupd_remote_get_automatic_reports (FwupdRemote *self)
return priv->automatic_reports;
}
/**
* fwupd_remote_get_automatic_security_reports:
* @self: A #FwupdRemote
*
* Gets if security reports should be automatically uploaded to this remote
*
* Returns: a #TRUE if the remote should have reports uploaded automatically
*
* Since: 1.5.0
**/
gboolean
fwupd_remote_get_automatic_security_reports (FwupdRemote *self)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_REMOTE (self), FALSE);
return priv->automatic_security_reports;
}
/**
* fwupd_remote_get_approval_required:
* @self: A #FwupdRemote
@ -1133,6 +1186,8 @@ fwupd_remote_set_from_variant_iter (FwupdRemote *self, GVariantIter *iter)
fwupd_remote_set_filename_source (self, g_variant_get_string (value, NULL));
if (g_strcmp0 (key, "ReportUri") == 0)
fwupd_remote_set_report_uri (self, g_variant_get_string (value, NULL));
if (g_strcmp0 (key, "SecurityReportUri") == 0)
fwupd_remote_set_security_report_uri (self, g_variant_get_string (value, NULL));
}
while (g_variant_iter_loop (iter3, "{sv}", &key, &value)) {
if (g_strcmp0 (key, "Username") == 0) {
@ -1157,6 +1212,8 @@ fwupd_remote_set_from_variant_iter (FwupdRemote *self, GVariantIter *iter)
fwupd_remote_set_firmware_base_uri (self, g_variant_get_string (value, NULL));
} else if (g_strcmp0 (key, "AutomaticReports") == 0) {
priv->automatic_reports = g_variant_get_boolean (value);
} else if (g_strcmp0 (key, "AutomaticSecurityReports") == 0) {
priv->automatic_security_reports = g_variant_get_boolean (value);
}
}
}
@ -1213,6 +1270,10 @@ fwupd_remote_to_variant (FwupdRemote *self)
g_variant_builder_add (&builder, "{sv}", "ReportUri",
g_variant_new_string (priv->report_uri));
}
if (priv->security_report_uri != NULL) {
g_variant_builder_add (&builder, "{sv}", "SecurityReportUri",
g_variant_new_string (priv->security_report_uri));
}
if (priv->firmware_base_uri != NULL) {
g_variant_builder_add (&builder, "{sv}", "FirmwareBaseUri",
g_variant_new_string (priv->firmware_base_uri));
@ -1251,6 +1312,8 @@ fwupd_remote_to_variant (FwupdRemote *self)
g_variant_new_boolean (priv->approval_required));
g_variant_builder_add (&builder, "{sv}", "AutomaticReports",
g_variant_new_boolean (priv->automatic_reports));
g_variant_builder_add (&builder, "{sv}", "AutomaticSecurityReports",
g_variant_new_boolean (priv->automatic_security_reports));
return g_variant_new ("a{sv}", &builder);
}
@ -1274,6 +1337,9 @@ fwupd_remote_get_property (GObject *obj, guint prop_id,
case PROP_AUTOMATIC_REPORTS:
g_value_set_boolean (value, priv->automatic_reports);
break;
case PROP_AUTOMATIC_SECURITY_REPORTS:
g_value_set_boolean (value, priv->automatic_security_reports);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@ -1300,6 +1366,9 @@ fwupd_remote_set_property (GObject *obj, guint prop_id,
case PROP_AUTOMATIC_REPORTS:
priv->automatic_reports = g_value_get_boolean (value);
break;
case PROP_AUTOMATIC_SECURITY_REPORTS:
priv->automatic_security_reports = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@ -1360,6 +1429,17 @@ fwupd_remote_class_init (FwupdRemoteClass *klass)
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_AUTOMATIC_REPORTS, pspec);
/**
* FwupdRemote:automatic-security-reports:
*
* The behavior for auto-uploading security reports.
*
* Since: 1.5.0
*/
pspec = g_param_spec_boolean ("automatic-security-reports", NULL, NULL,
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_AUTOMATIC_SECURITY_REPORTS, pspec);
}
static void
@ -1378,6 +1458,7 @@ fwupd_remote_finalize (GObject *obj)
g_free (priv->metadata_uri_sig);
g_free (priv->firmware_base_uri);
g_free (priv->report_uri);
g_free (priv->security_report_uri);
g_free (priv->username);
g_free (priv->password);
g_free (priv->title);

View File

@ -60,11 +60,13 @@ const gchar *fwupd_remote_get_filename_cache_sig (FwupdRemote *self);
const gchar *fwupd_remote_get_filename_source (FwupdRemote *self);
const gchar *fwupd_remote_get_firmware_base_uri (FwupdRemote *self);
const gchar *fwupd_remote_get_report_uri (FwupdRemote *self);
const gchar *fwupd_remote_get_security_report_uri (FwupdRemote *self);
const gchar *fwupd_remote_get_metadata_uri (FwupdRemote *self);
const gchar *fwupd_remote_get_metadata_uri_sig (FwupdRemote *self);
gboolean fwupd_remote_get_enabled (FwupdRemote *self);
gboolean fwupd_remote_get_approval_required (FwupdRemote *self);
gboolean fwupd_remote_get_automatic_reports (FwupdRemote *self);
gboolean fwupd_remote_get_automatic_security_reports (FwupdRemote *self);
gint fwupd_remote_get_priority (FwupdRemote *self);
guint64 fwupd_remote_get_age (FwupdRemote *self);
FwupdRemoteKind fwupd_remote_get_kind (FwupdRemote *self);

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <glib-object.h>
#include <json-glib/json-glib.h>
#include "fwupd-security-attr.h"
G_BEGIN_DECLS
#define FWUPD_SECURITY_ATTR_ID_ACPI_DMAR "org.fwupd.hsi.AcpiDmar" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_ENCRYPTED_RAM "org.fwupd.hsi.EncryptedRam" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_FWUPD_ATTESTATION "org.fwupd.hsi.Fwupd.Attestation" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_FWUPD_PLUGINS "org.fwupd.hsi.Fwupd.Plugins" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_FWUPD_UPDATES "org.fwupd.hsi.Fwupd.Updates" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_ENABLED "org.fwupd.hsi.IntelBootguard.Enabled" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_VERIFIED "org.fwupd.hsi.IntelBootguard.Verified" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_ACM "org.fwupd.hsi.IntelBootguard.Acm" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_POLICY "org.fwupd.hsi.IntelBootguard.Policy" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_OTP "org.fwupd.hsi.IntelBootguard.Otp" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_CET_ENABLED "org.fwupd.hsi.IntelCet.Enabled" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_CET_ACTIVE "org.fwupd.hsi.IntelCet.Active" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_SMAP "org.fwupd.hsi.IntelSmap" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_IOMMU "org.fwupd.hsi.Iommu" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_KERNEL_LOCKDOWN "org.fwupd.hsi.Kernel.Lockdown" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_KERNEL_SWAP "org.fwupd.hsi.Kernel.Swap" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_KERNEL_TAINTED "org.fwupd.hsi.Kernel.Tainted" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_MEI_MANUFACTURING_MODE "org.fwupd.hsi.Mei.ManufacturingMode" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_MEI_OVERRIDE_STRAP "org.fwupd.hsi.Mei.OverrideStrap" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_MEI_VERSION "org.fwupd.hsi.Mei.Version" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_SPI_BIOSWE "org.fwupd.hsi.Spi.Bioswe" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_SPI_BLE "org.fwupd.hsi.Spi.Ble" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_SPI_SMM_BWP "org.fwupd.hsi.Spi.SmmBwp" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_SUSPEND_TO_IDLE "org.fwupd.hsi.SuspendToIdle" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_SUSPEND_TO_RAM "org.fwupd.hsi.SuspendToRam" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_TPM_RECONSTRUCTION_PCR0 "org.fwupd.hsi.Tpm.ReconstructionPcr0" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_TPM_VERSION_20 "org.fwupd.hsi.Tpm.Version20" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT "org.fwupd.hsi.Uefi.SecureBoot" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_DCI_ENABLED "org.fwupd.hsi.IntelDci.Enabled" /* Since: 1.5.0 */
#define FWUPD_SECURITY_ATTR_ID_INTEL_DCI_LOCKED "org.fwupd.hsi.IntelDci.Locked" /* Since: 1.5.0 */
GVariant *fwupd_security_attr_to_variant (FwupdSecurityAttr *self);
void fwupd_security_attr_to_json (FwupdSecurityAttr *self,
JsonBuilder *builder);
G_END_DECLS

View File

@ -0,0 +1,916 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <gio/gio.h>
#include "fwupd-common-private.h"
#include "fwupd-enums-private.h"
#include "fwupd-security-attr-private.h"
/**
* SECTION:fwupd-security-attr
*
* An object that represents an Host Security ID attribute.
*/
static void fwupd_security_attr_finalize (GObject *object);
typedef struct {
gchar *appstream_id;
GPtrArray *obsoletes;
GHashTable *metadata; /* (nullable) */
gchar *name;
gchar *plugin;
gchar *url;
FwupdSecurityAttrLevel level;
FwupdSecurityAttrResult result;
FwupdSecurityAttrFlags flags;
} FwupdSecurityAttrPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FwupdSecurityAttr, fwupd_security_attr, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fwupd_security_attr_get_instance_private (o))
/**
* fwupd_security_attr_flag_to_string:
* @flag: A #FwupdSecurityAttrFlags, e.g. %FWUPD_SECURITY_ATTR_FLAG_SUCCESS
*
* Returns the printable string for the flag.
*
* Returns: string, or %NULL
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_flag_to_string (FwupdSecurityAttrFlags flag)
{
if (flag == FWUPD_SECURITY_ATTR_FLAG_NONE)
return "none";
if (flag == FWUPD_SECURITY_ATTR_FLAG_SUCCESS)
return "success";
if (flag == FWUPD_SECURITY_ATTR_FLAG_OBSOLETED)
return "obsoleted";
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES)
return "runtime-updates";
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION)
return "runtime-attestation";
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE)
return "runtime-issue";
return NULL;
}
/**
* fwupd_security_attr_result_to_string:
* @result: A #FwupdSecurityAttrResult, e.g. %FWUPD_SECURITY_ATTR_RESULT_ENABLED
*
* Returns the printable string for the result enum.
*
* Returns: string, or %NULL
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_result_to_string (FwupdSecurityAttrResult result)
{
if (result == FWUPD_SECURITY_ATTR_RESULT_VALID)
return "valid";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_VALID)
return "not-valid";
if (result == FWUPD_SECURITY_ATTR_RESULT_ENABLED)
return "enabled";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED)
return "not-enabled";
if (result == FWUPD_SECURITY_ATTR_RESULT_LOCKED)
return "locked";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_LOCKED)
return "not-locked";
if (result == FWUPD_SECURITY_ATTR_RESULT_ENCRYPTED)
return "encrypted";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_ENCRYPTED)
return "not-encrypted";
if (result == FWUPD_SECURITY_ATTR_RESULT_TAINTED)
return "tainted";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_TAINTED)
return "not-tainted";
if (result == FWUPD_SECURITY_ATTR_RESULT_FOUND)
return "found";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND)
return "not-found";
if (result == FWUPD_SECURITY_ATTR_RESULT_SUPPORTED)
return "supported";
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED)
return "not-supported";
return NULL;
}
/**
* fwupd_security_attr_flag_to_suffix:
* @flag: A #FwupdSecurityAttrFlags, e.g. %FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES
*
* Returns the string suffix for the flag.
*
* Returns: string, or %NULL
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_flag_to_suffix (FwupdSecurityAttrFlags flag)
{
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES)
return "U";
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION)
return "A";
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE)
return "!";
return NULL;
}
/**
* fwupd_security_attr_get_obsoletes:
* @self: A #FwupdSecurityAttr
*
* Gets the list of attribute obsoletes. The obsoleted attributes will not
* contribute to the calculated HSI value or be visible in command line tools.
*
* Returns: (element-type utf8) (transfer none): the obsoletes, which may be empty
*
* Since: 1.5.0
**/
GPtrArray *
fwupd_security_attr_get_obsoletes (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
return priv->obsoletes;
}
/**
* fwupd_security_attr_add_obsolete:
* @self: A #FwupdSecurityAttr
* @appstream_id: the appstream_id or plugin name
*
* Adds an attribute appstream_id to obsolete. The obsoleted attribute will not
* contribute to the calculated HSI value or be visible in command line tools.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_add_obsolete (FwupdSecurityAttr *self, const gchar *appstream_id)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
g_return_if_fail (appstream_id != NULL);
if (fwupd_security_attr_has_obsolete (self, appstream_id))
return;
g_ptr_array_add (priv->obsoletes, g_strdup (appstream_id));
}
/**
* fwupd_security_attr_has_obsolete:
* @self: A #FwupdSecurityAttr
* @appstream_id: the attribute appstream_id
*
* Finds out if the attribute obsoletes a specific appstream_id.
*
* Returns: %TRUE if the self matches
*
* Since: 1.5.0
**/
gboolean
fwupd_security_attr_has_obsolete (FwupdSecurityAttr *self, const gchar *appstream_id)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), FALSE);
g_return_val_if_fail (appstream_id != NULL, FALSE);
for (guint i = 0; i < priv->obsoletes->len; i++) {
const gchar *obsolete_tmp = g_ptr_array_index (priv->obsoletes, i);
if (g_strcmp0 (obsolete_tmp, appstream_id) == 0)
return TRUE;
}
return FALSE;
}
/**
* fwupd_security_attr_get_appstream_id:
* @self: A #FwupdSecurityAttr
*
* Gets the AppStream ID.
*
* Returns: the AppStream ID, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_get_appstream_id (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
return priv->appstream_id;
}
/**
* fwupd_security_attr_set_appstream_id:
* @self: A #FwupdSecurityAttr
* @appstream_id: the AppStream component ID, e.g. `com.intel.BiosGuard`
*
* Sets the AppStream ID.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_appstream_id (FwupdSecurityAttr *self, const gchar *appstream_id)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
/* sanity check */
if (!g_str_has_prefix (appstream_id, "org.fwupd.hsi."))
g_critical ("HSI attributes need to have a 'org.fwupd.hsi.' prefix");
g_free (priv->appstream_id);
priv->appstream_id = g_strdup (appstream_id);
}
/**
* fwupd_security_attr_get_url:
* @self: A #FwupdSecurityAttr
*
* Gets the attribute URL.
*
* Returns: the attribute result, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_get_url (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
return priv->url;
}
/**
* fwupd_security_attr_set_name:
* @self: A #FwupdSecurityAttr
* @name: the attribute name
*
* Sets the attribute name.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_name (FwupdSecurityAttr *self, const gchar *name)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
g_free (priv->name);
priv->name = g_strdup (name);
}
/**
* fwupd_security_attr_set_plugin:
* @self: A #FwupdSecurityAttr
* @plugin: the plugin name
*
* Sets the plugin that created the attribute.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_plugin (FwupdSecurityAttr *self, const gchar *plugin)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
g_free (priv->plugin);
priv->plugin = g_strdup (plugin);
}
/**
* fwupd_security_attr_set_url:
* @self: A #FwupdSecurityAttr
* @url: the attribute URL
*
* Sets the attribute result.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_url (FwupdSecurityAttr *self, const gchar *url)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
g_free (priv->url);
priv->url = g_strdup (url);
}
/**
* fwupd_security_attr_get_name:
* @self: A #FwupdSecurityAttr
*
* Gets the attribute name.
*
* Returns: the attribute name, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_get_name (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
return priv->name;
}
/**
* fwupd_security_attr_get_plugin:
* @self: A #FwupdSecurityAttr
*
* Gets the plugin that created the attribute.
*
* Returns: the plugin name, or %NULL if unset
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_get_plugin (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
return priv->plugin;
}
/**
* fwupd_security_attr_get_flags:
* @self: A #FwupdSecurityAttr
*
* Gets the self flags.
*
* Returns: the self flags, or 0 if unset
*
* Since: 1.5.0
**/
FwupdSecurityAttrFlags
fwupd_security_attr_get_flags (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), 0);
return priv->flags;
}
/**
* fwupd_security_attr_set_flags:
* @self: A #FwupdSecurityAttr
* @flags: the self flags, e.g. %FWUPD_SECURITY_ATTR_FLAG_OBSOLETED
*
* Sets the self flags.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_flags (FwupdSecurityAttr *self, FwupdSecurityAttrFlags flags)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
priv->flags = flags;
}
/**
* fwupd_security_attr_add_flag:
* @self: A #FwupdSecurityAttr
* @flag: the #FwupdSecurityAttrFlags
*
* Adds a specific self flag to the self.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_add_flag (FwupdSecurityAttr *self, FwupdSecurityAttrFlags flag)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
priv->flags |= flag;
}
/**
* fwupd_security_attr_has_flag:
* @self: A #FwupdSecurityAttr
* @flag: the #FwupdSecurityAttrFlags
*
* Finds if the self has a specific self flag.
*
* Returns: %TRUE if the flag is set
*
* Since: 1.5.0
**/
gboolean
fwupd_security_attr_has_flag (FwupdSecurityAttr *self, FwupdSecurityAttrFlags flag)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), FALSE);
return (priv->flags & flag) > 0;
}
/**
* fwupd_security_attr_get_level:
* @self: A #FwupdSecurityAttr
*
* Gets the HSI level.
*
* Returns: the #FwupdSecurityAttrLevel, or %FWUPD_SECURITY_ATTR_LEVEL_NONE if unset
*
* Since: 1.5.0
**/
FwupdSecurityAttrLevel
fwupd_security_attr_get_level (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), 0);
return priv->level;
}
/**
* fwupd_security_attr_set_level:
* @self: A #FwupdSecurityAttr
* @level: A #FwupdSecurityAttrLevel, e.g. %FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT
*
* Sets the HSI level. A @level of %FWUPD_SECURITY_ATTR_LEVEL_NONE is not used
* for the HSI calculation.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_level (FwupdSecurityAttr *self, FwupdSecurityAttrLevel level)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
priv->level = level;
}
/**
* fwupd_security_attr_set_result:
* @self: A #FwupdSecurityAttr
* @result: A #FwupdSecurityAttrResult, e.g. %FWUPD_SECURITY_ATTR_LEVEL_LOCKED
*
* Sets the optional HSI result. This is required because some attributes may
* be a "success" when something is `locked` or may be "failed" if `found`.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_set_result (FwupdSecurityAttr *self, FwupdSecurityAttrResult result)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
priv->result = result;
}
/**
* fwupd_security_attr_get_result:
* @self: A #FwupdSecurityAttr
*
* Gets the optional HSI result.
*
* Returns: the #FwupdSecurityAttrResult, e.g %FWUPD_SECURITY_ATTR_LEVEL_LOCKED
*
* Since: 1.5.0
**/
FwupdSecurityAttrResult
fwupd_security_attr_get_result (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), 0);
return priv->result;
}
/**
* fwupd_security_attr_to_variant:
* @self: A #FwupdSecurityAttr
*
* Creates a GVariant from the self data.
*
* Returns: the GVariant, or %NULL for error
*
* Since: 1.5.0
**/
GVariant *
fwupd_security_attr_to_variant (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
GVariantBuilder builder;
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
if (priv->appstream_id != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_APPSTREAM_ID,
g_variant_new_string (priv->appstream_id));
}
if (priv->name != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_NAME,
g_variant_new_string (priv->name));
}
if (priv->url != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_URI,
g_variant_new_string (priv->url));
}
if (priv->obsoletes->len > 0) {
g_autofree const gchar **strv = g_new0 (const gchar *, priv->obsoletes->len + 1);
for (guint i = 0; i < priv->obsoletes->len; i++)
strv[i] = (const gchar *) g_ptr_array_index (priv->obsoletes, i);
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_CATEGORIES,
g_variant_new_strv (strv, -1));
}
if (priv->flags != 0) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_FLAGS,
g_variant_new_uint64 (priv->flags));
}
if (priv->level > 0) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_HSI_LEVEL,
g_variant_new_uint32 (priv->level));
}
if (priv->result != FWUPD_SECURITY_ATTR_RESULT_UNKNOWN) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_HSI_RESULT,
g_variant_new_uint32 (priv->result));
}
if (priv->metadata != NULL) {
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_METADATA,
fwupd_hash_kv_to_variant (priv->metadata));
}
return g_variant_new ("a{sv}", &builder);
}
/**
* fwupd_security_attr_get_metadata:
* @self: A #FwupdSecurityAttr
* @key: metadata key
*
* Gets private metadata from the attribute which may be used in the name.
*
* Returns: (nullable): the metadata value, or %NULL if unfound
*
* Since: 1.5.0
**/
const gchar *
fwupd_security_attr_get_metadata (FwupdSecurityAttr *self, const gchar *key)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
g_return_val_if_fail (key != NULL, NULL);
if (priv->metadata == NULL)
return NULL;
return g_hash_table_lookup (priv->metadata, key);
}
/**
* fwupd_security_attr_add_metadata:
* @self: A #FwupdSecurityAttr
* @key: metadata key
* @value: (nullable): metadata value
*
* Adds metadata to the attribute which may be used in the name.
*
* Since: 1.5.0
**/
void
fwupd_security_attr_add_metadata (FwupdSecurityAttr *self,
const gchar *key,
const gchar *value)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
g_return_if_fail (key != NULL);
if (priv->metadata == NULL) {
priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
}
g_hash_table_insert (priv->metadata, g_strdup (key), g_strdup (value));
}
static void
fwupd_security_attr_from_key_value (FwupdSecurityAttr *self, const gchar *key, GVariant *value)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
if (g_strcmp0 (key, FWUPD_RESULT_KEY_APPSTREAM_ID) == 0) {
fwupd_security_attr_set_appstream_id (self, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_NAME) == 0) {
fwupd_security_attr_set_name (self, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_URI) == 0) {
fwupd_security_attr_set_url (self, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_FLAGS) == 0) {
fwupd_security_attr_set_flags (self, g_variant_get_uint64 (value));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_HSI_LEVEL) == 0) {
fwupd_security_attr_set_level (self, g_variant_get_uint32 (value));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_HSI_RESULT) == 0) {
fwupd_security_attr_set_result (self, g_variant_get_uint32 (value));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_METADATA) == 0) {
if (priv->metadata != NULL)
g_hash_table_unref (priv->metadata);
priv->metadata = fwupd_variant_to_hash_kv (value);
return;
}
}
static void
fwupd_pad_kv_str (GString *str, const gchar *key, const gchar *value)
{
/* ignore */
if (key == NULL || value == NULL)
return;
g_string_append_printf (str, " %s: ", key);
for (gsize i = strlen (key); i < 20; i++)
g_string_append (str, " ");
g_string_append_printf (str, "%s\n", value);
}
static void
fwupd_pad_kv_tfl (GString *str, const gchar *key, FwupdSecurityAttrFlags security_attr_flags)
{
g_autoptr(GString) tmp = g_string_new ("");
for (guint i = 0; i < 64; i++) {
if ((security_attr_flags & ((guint64) 1 << i)) == 0)
continue;
g_string_append_printf (tmp, "%s|",
fwupd_security_attr_flag_to_string ((guint64) 1 << i));
}
if (tmp->len == 0) {
g_string_append (tmp, fwupd_security_attr_flag_to_string (0));
} else {
g_string_truncate (tmp, tmp->len - 1);
}
fwupd_pad_kv_str (str, key, tmp->str);
}
static void
fwupd_pad_kv_int (GString *str, const gchar *key, guint32 value)
{
g_autofree gchar *tmp = NULL;
/* ignore */
if (value == 0)
return;
tmp = g_strdup_printf("%" G_GUINT32_FORMAT, value);
fwupd_pad_kv_str (str, key, tmp);
}
static void
fwupd_security_attr_json_add_string (JsonBuilder *builder, const gchar *key, const gchar *str)
{
if (str == NULL)
return;
json_builder_set_member_name (builder, key);
json_builder_add_string_value (builder, str);
}
static void
fwupd_security_attr_json_add_int (JsonBuilder *builder, const gchar *key, guint64 num)
{
if (num == 0)
return;
json_builder_set_member_name (builder, key);
json_builder_add_int_value (builder, num);
}
/**
* fwupd_security_attr_to_json:
* @self: A #FwupdSecurityAttr
* @builder: A #JsonBuilder
*
* Adds a fwupd self to a JSON builder
*
* Since: 1.5.0
**/
void
fwupd_security_attr_to_json (FwupdSecurityAttr *self, JsonBuilder *builder)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_SECURITY_ATTR (self));
g_return_if_fail (builder != NULL);
fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_APPSTREAM_ID, priv->appstream_id);
fwupd_security_attr_json_add_int (builder, FWUPD_RESULT_KEY_HSI_LEVEL, priv->level);
fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_HSI_RESULT,
fwupd_security_attr_result_to_string (priv->result));
fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_NAME, priv->name);
fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_URI, priv->url);
if (priv->flags != FWUPD_SECURITY_ATTR_FLAG_NONE) {
json_builder_set_member_name (builder, FWUPD_RESULT_KEY_FLAGS);
json_builder_begin_array (builder);
for (guint i = 0; i < 64; i++) {
const gchar *tmp;
if ((priv->flags & ((guint64) 1 << i)) == 0)
continue;
tmp = fwupd_security_attr_flag_to_string ((guint64) 1 << i);
json_builder_add_string_value (builder, tmp);
}
json_builder_end_array (builder);
}
if (priv->metadata != NULL) {
g_autoptr(GList) keys = g_hash_table_get_keys (priv->metadata);
for (GList *l = keys; l != NULL; l = l->next) {
const gchar *key = l->data;
const gchar *value = g_hash_table_lookup (priv->metadata, key);
fwupd_security_attr_json_add_string (builder, key, value);
}
}
}
/**
* fwupd_security_attr_to_string:
* @self: A #FwupdSecurityAttr
*
* Builds a text representation of the object.
*
* Returns: text, or %NULL for invalid
*
* Since: 1.5.0
**/
gchar *
fwupd_security_attr_to_string (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
GString *str;
g_return_val_if_fail (FWUPD_IS_SECURITY_ATTR (self), NULL);
str = g_string_new ("");
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_APPSTREAM_ID, priv->appstream_id);
fwupd_pad_kv_int (str, FWUPD_RESULT_KEY_HSI_LEVEL, priv->level);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_HSI_RESULT,
fwupd_security_attr_result_to_string (priv->result));
if (priv->flags != FWUPD_SECURITY_ATTR_FLAG_NONE)
fwupd_pad_kv_tfl (str, FWUPD_RESULT_KEY_FLAGS, priv->flags);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_NAME, priv->name);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_URI, priv->url);
for (guint i = 0; i < priv->obsoletes->len; i++) {
const gchar *appstream_id = g_ptr_array_index (priv->obsoletes, i);
fwupd_pad_kv_str (str, "Obsolete", appstream_id);
}
if (priv->metadata != NULL) {
g_autoptr(GList) keys = g_hash_table_get_keys (priv->metadata);
for (GList *l = keys; l != NULL; l = l->next) {
const gchar *key = l->data;
const gchar *value = g_hash_table_lookup (priv->metadata, key);
fwupd_pad_kv_str (str, key, value);
}
}
return g_string_free (str, FALSE);
}
static void
fwupd_security_attr_class_init (FwupdSecurityAttrClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = fwupd_security_attr_finalize;
}
static void
fwupd_security_attr_init (FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
priv->obsoletes = g_ptr_array_new_with_free_func (g_free);
}
static void
fwupd_security_attr_finalize (GObject *object)
{
FwupdSecurityAttr *self = FWUPD_SECURITY_ATTR (object);
FwupdSecurityAttrPrivate *priv = GET_PRIVATE (self);
if (priv->metadata != NULL)
g_hash_table_unref (priv->metadata);
g_free (priv->appstream_id);
g_free (priv->name);
g_free (priv->plugin);
g_free (priv->url);
g_ptr_array_unref (priv->obsoletes);
G_OBJECT_CLASS (fwupd_security_attr_parent_class)->finalize (object);
}
static void
fwupd_security_attr_set_from_variant_iter (FwupdSecurityAttr *self, GVariantIter *iter)
{
GVariant *value;
const gchar *key;
while (g_variant_iter_next (iter, "{&sv}", &key, &value)) {
fwupd_security_attr_from_key_value (self, key, value);
g_variant_unref (value);
}
}
/**
* fwupd_security_attr_from_variant:
* @value: a #GVariant
*
* Creates a new self using packed data.
*
* Returns: (transfer full): a new #FwupdSecurityAttr, or %NULL if @value was invalid
*
* Since: 1.5.0
**/
FwupdSecurityAttr *
fwupd_security_attr_from_variant (GVariant *value)
{
FwupdSecurityAttr *rel = NULL;
const gchar *type_string;
g_autoptr(GVariantIter) iter = NULL;
type_string = g_variant_get_type_string (value);
if (g_strcmp0 (type_string, "(a{sv})") == 0) {
rel = fwupd_security_attr_new (NULL);
g_variant_get (value, "(a{sv})", &iter);
fwupd_security_attr_set_from_variant_iter (rel, iter);
} else if (g_strcmp0 (type_string, "a{sv}") == 0) {
rel = fwupd_security_attr_new (NULL);
g_variant_get (value, "a{sv}", &iter);
fwupd_security_attr_set_from_variant_iter (rel, iter);
} else {
g_warning ("type %s not known", type_string);
}
return rel;
}
/**
* fwupd_security_attr_array_from_variant:
* @value: a #GVariant
*
* Creates an array of new security_attrs using packed data.
*
* Returns: (transfer container) (element-type FwupdSecurityAttr): attributes, or %NULL if @value was invalid
*
* Since: 1.5.0
**/
GPtrArray *
fwupd_security_attr_array_from_variant (GVariant *value)
{
GPtrArray *array = NULL;
gsize sz;
g_autoptr(GVariant) untuple = NULL;
array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
untuple = g_variant_get_child_value (value, 0);
sz = g_variant_n_children (untuple);
for (guint i = 0; i < sz; i++) {
FwupdSecurityAttr *rel;
g_autoptr(GVariant) data = NULL;
data = g_variant_get_child_value (untuple, i);
rel = fwupd_security_attr_from_variant (data);
if (rel == NULL)
continue;
g_ptr_array_add (array, rel);
}
return array;
}
/**
* fwupd_security_attr_new:
* @appstream_id: (allow-none): the AppStream component ID, e.g. `com.intel.BiosGuard`
*
* Creates a new self.
*
* Returns: a new #FwupdSecurityAttr
*
* Since: 1.5.0
**/
FwupdSecurityAttr *
fwupd_security_attr_new (const gchar *appstream_id)
{
FwupdSecurityAttr *self;
self = g_object_new (FWUPD_TYPE_SECURITY_ATTR, NULL);
if (appstream_id != NULL)
fwupd_security_attr_set_appstream_id (self, appstream_id);
return FWUPD_SECURITY_ATTR (self);
}

View File

@ -0,0 +1,159 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <glib-object.h>
#include "fwupd-enums.h"
G_BEGIN_DECLS
#define FWUPD_TYPE_SECURITY_ATTR (fwupd_security_attr_get_type ())
G_DECLARE_DERIVABLE_TYPE (FwupdSecurityAttr, fwupd_security_attr, FWUPD, SECURITY_ATTR, GObject)
struct _FwupdSecurityAttrClass
{
GObjectClass parent_class;
/*< private >*/
void (*_fwupd_reserved1) (void);
void (*_fwupd_reserved2) (void);
void (*_fwupd_reserved3) (void);
void (*_fwupd_reserved4) (void);
void (*_fwupd_reserved5) (void);
void (*_fwupd_reserved6) (void);
void (*_fwupd_reserved7) (void);
};
/**
* FwupdSecurityAttrFlags:
* @FWUPD_SECURITY_ATTR_FLAG_NONE: No flags set
* @FWUPD_SECURITY_ATTR_FLAG_SUCCESS: Success
* @FWUPD_SECURITY_ATTR_FLAG_OBSOLETED: Obsoleted by another attribute
* @FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES: Suffix `U`
* @FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION: Suffix `A`
* @FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE: Suffix `!`
*
* The flags available for HSI attributes.
**/
typedef enum {
FWUPD_SECURITY_ATTR_FLAG_NONE = 0,
FWUPD_SECURITY_ATTR_FLAG_SUCCESS = 1 << 0,
FWUPD_SECURITY_ATTR_FLAG_OBSOLETED = 1 << 1,
FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES = 1 << 8,
FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION = 1 << 9,
FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE = 1 << 10,
} FwupdSecurityAttrFlags;
/**
* FwupdSecurityAttrLevel:
* @FWUPD_SECURITY_ATTR_LEVEL_NONE: Very few detected firmware protections
* @FWUPD_SECURITY_ATTR_LEVEL_CRITICAL: The most basic of security protections
* @FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT: Firmware security issues considered important
* @FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL: Firmware security issues that pose a theoretical concern
* @FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_PROTECTION: Out-of-band protection of the system firmware
* @FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_ATTESTATION: Out-of-band attestation of the system firmware
*
* The HSI level.
**/
typedef enum {
FWUPD_SECURITY_ATTR_LEVEL_NONE = 0, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_LEVEL_CRITICAL = 1, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT = 2, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL = 3, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_PROTECTION = 4, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_ATTESTATION = 5, /* Since: 1.5.0 */
/*< private >*/
FWUPD_SECURITY_ATTR_LEVEL_LAST = 6 /* perhaps increased in the future */
} FwupdSecurityAttrLevel;
/**
* FwupdSecurityAttrResult:
* @FWUPD_SECURITY_ATTR_RESULT_UNKNOWN: Not known
* @FWUPD_SECURITY_ATTR_RESULT_ENABLED: Enabled
* @FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED: Not enabled
* @FWUPD_SECURITY_ATTR_RESULT_VALID: Valid
* @FWUPD_SECURITY_ATTR_RESULT_NOT_VALID: Not valid
* @FWUPD_SECURITY_ATTR_RESULT_LOCKED: Locked
* @FWUPD_SECURITY_ATTR_RESULT_NOT_LOCKED: Not locked
* @FWUPD_SECURITY_ATTR_RESULT_ENCRYPTED: Encrypted
* @FWUPD_SECURITY_ATTR_RESULT_NOT_ENCRYPTED: Not encrypted
* @FWUPD_SECURITY_ATTR_RESULT_TAINTED: Tainted
* @FWUPD_SECURITY_ATTR_RESULT_NOT_TAINTED: Not tainted
* @FWUPD_SECURITY_ATTR_RESULT_FOUND: Found
* @FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND: NOt found
* @FWUPD_SECURITY_ATTR_RESULT_SUPPORTED: Supported
* @FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED: Not supported
*
* The HSI result.
**/
typedef enum {
FWUPD_SECURITY_ATTR_RESULT_UNKNOWN, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_ENABLED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_VALID, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_VALID, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_LOCKED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_LOCKED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_ENCRYPTED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_ENCRYPTED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_TAINTED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_TAINTED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_FOUND, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_SUPPORTED, /* Since: 1.5.0 */
FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED, /* Since: 1.5.0 */
/*< private >*/
FWUPD_SECURITY_ATTR_RESULT_LAST
} FwupdSecurityAttrResult;
FwupdSecurityAttr *fwupd_security_attr_new (const gchar *appstream_id);
gchar *fwupd_security_attr_to_string (FwupdSecurityAttr *self);
const gchar *fwupd_security_attr_get_appstream_id (FwupdSecurityAttr *self);
void fwupd_security_attr_set_appstream_id (FwupdSecurityAttr *self,
const gchar *appstream_id);
FwupdSecurityAttrLevel fwupd_security_attr_get_level (FwupdSecurityAttr *self);
void fwupd_security_attr_set_level (FwupdSecurityAttr *self,
FwupdSecurityAttrLevel level);
FwupdSecurityAttrResult fwupd_security_attr_get_result (FwupdSecurityAttr *self);
void fwupd_security_attr_set_result (FwupdSecurityAttr *self,
FwupdSecurityAttrResult result);
const gchar *fwupd_security_attr_get_name (FwupdSecurityAttr *self);
void fwupd_security_attr_set_name (FwupdSecurityAttr *self,
const gchar *name);
const gchar *fwupd_security_attr_get_plugin (FwupdSecurityAttr *self);
void fwupd_security_attr_set_plugin (FwupdSecurityAttr *self,
const gchar *plugin);
const gchar *fwupd_security_attr_get_url (FwupdSecurityAttr *self);
void fwupd_security_attr_set_url (FwupdSecurityAttr *self,
const gchar *url);
GPtrArray *fwupd_security_attr_get_obsoletes (FwupdSecurityAttr *self);
void fwupd_security_attr_add_obsolete (FwupdSecurityAttr *self,
const gchar *appstream_id);
gboolean fwupd_security_attr_has_obsolete (FwupdSecurityAttr *self,
const gchar *appstream_id);
const gchar *fwupd_security_attr_get_metadata (FwupdSecurityAttr *self,
const gchar *key);
void fwupd_security_attr_add_metadata (FwupdSecurityAttr *self,
const gchar *key,
const gchar *value);
FwupdSecurityAttrFlags fwupd_security_attr_get_flags (FwupdSecurityAttr *self);
void fwupd_security_attr_set_flags (FwupdSecurityAttr *self,
FwupdSecurityAttrFlags flags);
void fwupd_security_attr_add_flag (FwupdSecurityAttr *self,
FwupdSecurityAttrFlags flag);
gboolean fwupd_security_attr_has_flag (FwupdSecurityAttr *self,
FwupdSecurityAttrFlags flag);
const gchar *fwupd_security_attr_flag_to_string (FwupdSecurityAttrFlags flag);
const gchar *fwupd_security_attr_flag_to_suffix (FwupdSecurityAttrFlags flag);
const gchar *fwupd_security_attr_result_to_string (FwupdSecurityAttrResult result);
FwupdSecurityAttr *fwupd_security_attr_from_variant (GVariant *value);
GPtrArray *fwupd_security_attr_array_from_variant (GVariant *value);
G_END_DECLS

View File

@ -12,6 +12,7 @@
#endif
#include "fwupd-client.h"
#include "fwupd-client-sync.h"
#include "fwupd-common.h"
#include "fwupd-enums.h"
#include "fwupd-error.h"
@ -147,6 +148,12 @@ fwupd_enums_func (void)
break;
g_assert_cmpint (fwupd_device_flag_from_string (tmp), ==, i);
}
for (guint64 i = 1; i < FWUPD_PLUGIN_FLAG_UNKNOWN; i *= 2) {
const gchar *tmp = fwupd_plugin_flag_to_string (i);
if (tmp == NULL)
break;
g_assert_cmpint (fwupd_plugin_flag_from_string (tmp), ==, i);
}
}
static void

View File

@ -14,10 +14,13 @@
#define __FWUPD_H_INSIDE__
#include <libfwupd/fwupd-client.h>
#include <libfwupd/fwupd-client-sync.h>
#include <libfwupd/fwupd-common.h>
#include <libfwupd/fwupd-device.h>
#include <libfwupd/fwupd-plugin.h>
#include <libfwupd/fwupd-enums.h>
#include <libfwupd/fwupd-error.h>
#include <libfwupd/fwupd-security-attr.h>
#include <libfwupd/fwupd-release.h>
#include <libfwupd/fwupd-remote.h>
#include <libfwupd/fwupd-version.h>

View File

@ -475,3 +475,144 @@ LIBFWUPD_1.4.6 {
fwupd_client_set_blocked_firmware;
local: *;
} LIBFWUPD_1.4.5;
LIBFWUPD_1.5.0 {
global:
fwupd_client_activate_async;
fwupd_client_activate_finish;
fwupd_client_clear_results_async;
fwupd_client_clear_results_finish;
fwupd_client_connect_async;
fwupd_client_connect_finish;
fwupd_client_download_bytes_async;
fwupd_client_download_bytes_finish;
fwupd_client_get_approved_firmware_async;
fwupd_client_get_approved_firmware_finish;
fwupd_client_get_blocked_firmware_async;
fwupd_client_get_blocked_firmware_finish;
fwupd_client_get_details_bytes;
fwupd_client_get_details_bytes_async;
fwupd_client_get_details_bytes_finish;
fwupd_client_get_device_by_id_async;
fwupd_client_get_device_by_id_finish;
fwupd_client_get_devices_async;
fwupd_client_get_devices_by_guid_async;
fwupd_client_get_devices_by_guid_finish;
fwupd_client_get_devices_finish;
fwupd_client_get_downgrades_async;
fwupd_client_get_downgrades_finish;
fwupd_client_get_history_async;
fwupd_client_get_history_finish;
fwupd_client_get_host_security_attrs;
fwupd_client_get_host_security_attrs_async;
fwupd_client_get_host_security_attrs_finish;
fwupd_client_get_host_security_id;
fwupd_client_get_plugins;
fwupd_client_get_plugins_async;
fwupd_client_get_plugins_finish;
fwupd_client_get_releases_async;
fwupd_client_get_releases_finish;
fwupd_client_get_remote_by_id_async;
fwupd_client_get_remote_by_id_finish;
fwupd_client_get_remotes_async;
fwupd_client_get_remotes_finish;
fwupd_client_get_report_metadata;
fwupd_client_get_report_metadata_async;
fwupd_client_get_report_metadata_finish;
fwupd_client_get_results_async;
fwupd_client_get_results_finish;
fwupd_client_get_upgrades_async;
fwupd_client_get_upgrades_finish;
fwupd_client_install_async;
fwupd_client_install_bytes_async;
fwupd_client_install_bytes_finish;
fwupd_client_install_finish;
fwupd_client_install_release_async;
fwupd_client_install_release_finish;
fwupd_client_modify_config_async;
fwupd_client_modify_config_finish;
fwupd_client_modify_device_async;
fwupd_client_modify_device_finish;
fwupd_client_modify_remote_async;
fwupd_client_modify_remote_finish;
fwupd_client_refresh_remote_async;
fwupd_client_refresh_remote_finish;
fwupd_client_self_sign_async;
fwupd_client_self_sign_finish;
fwupd_client_set_approved_firmware_async;
fwupd_client_set_approved_firmware_finish;
fwupd_client_set_blocked_firmware_async;
fwupd_client_set_blocked_firmware_finish;
fwupd_client_set_feature_flags_async;
fwupd_client_set_feature_flags_finish;
fwupd_client_unlock_async;
fwupd_client_unlock_finish;
fwupd_client_update_metadata_bytes_async;
fwupd_client_update_metadata_bytes_finish;
fwupd_client_upload_bytes_async;
fwupd_client_upload_bytes_finish;
fwupd_client_verify_async;
fwupd_client_verify_finish;
fwupd_client_verify_update_async;
fwupd_client_verify_update_finish;
fwupd_device_get_branch;
fwupd_device_set_branch;
fwupd_plugin_add_flag;
fwupd_plugin_array_from_variant;
fwupd_plugin_flag_from_string;
fwupd_plugin_flag_to_string;
fwupd_plugin_from_variant;
fwupd_plugin_get_flags;
fwupd_plugin_get_name;
fwupd_plugin_get_type;
fwupd_plugin_has_flag;
fwupd_plugin_new;
fwupd_plugin_remove_flag;
fwupd_plugin_set_flags;
fwupd_plugin_set_name;
fwupd_plugin_to_json;
fwupd_plugin_to_string;
fwupd_plugin_to_variant;
fwupd_release_get_branch;
fwupd_release_set_branch;
fwupd_remote_get_automatic_security_reports;
fwupd_remote_get_security_report_uri;
fwupd_security_attr_add_flag;
fwupd_security_attr_add_metadata;
fwupd_security_attr_add_obsolete;
fwupd_security_attr_array_from_variant;
fwupd_security_attr_flag_to_string;
fwupd_security_attr_flag_to_suffix;
fwupd_security_attr_from_variant;
fwupd_security_attr_get_appstream_id;
fwupd_security_attr_get_flags;
fwupd_security_attr_get_level;
fwupd_security_attr_get_metadata;
fwupd_security_attr_get_name;
fwupd_security_attr_get_obsoletes;
fwupd_security_attr_get_plugin;
fwupd_security_attr_get_result;
fwupd_security_attr_get_type;
fwupd_security_attr_get_url;
fwupd_security_attr_has_flag;
fwupd_security_attr_has_obsolete;
fwupd_security_attr_new;
fwupd_security_attr_result_to_string;
fwupd_security_attr_set_appstream_id;
fwupd_security_attr_set_flags;
fwupd_security_attr_set_level;
fwupd_security_attr_set_name;
fwupd_security_attr_set_plugin;
fwupd_security_attr_set_result;
fwupd_security_attr_set_url;
fwupd_security_attr_to_json;
fwupd_security_attr_to_string;
fwupd_security_attr_to_variant;
local: *;
} LIBFWUPD_1.4.6;
LIBFWUPD_1.5.1 {
global:
fwupd_device_add_child;
local: *;
} LIBFWUPD_1.5.0;

View File

@ -15,13 +15,16 @@ install_headers(
install_headers([
'fwupd-client.h',
'fwupd-client-sync.h',
'fwupd-common.h',
'fwupd-deprecated.h',
'fwupd-device.h',
'fwupd-enums.h',
'fwupd-error.h',
'fwupd-remote.h',
'fwupd-security-attr.h',
'fwupd-release.h',
'fwupd-plugin.h',
fwupd_version_h,
],
subdir : 'fwupd-1/libfwupd',
@ -33,11 +36,14 @@ fwupd = shared_library(
'fwupd',
sources : [
'fwupd-client.c',
'fwupd-client-sync.c',
'fwupd-common.c',
'fwupd-device.c',
'fwupd-enums.c',
'fwupd-error.c',
'fwupd-security-attr.c',
'fwupd-release.c',
'fwupd-plugin.c',
'fwupd-remote.c',
],
soversion : libfwupd_lt_current,
@ -74,6 +80,8 @@ if get_option('introspection')
sources : [
'fwupd-client.c',
'fwupd-client.h',
'fwupd-client-sync.c',
'fwupd-client-sync.h',
'fwupd-common.c',
'fwupd-common.h',
'fwupd-common-private.h',
@ -85,9 +93,15 @@ if get_option('introspection')
'fwupd-enums-private.h',
'fwupd-error.c',
'fwupd-error.h',
'fwupd-security-attr.c',
'fwupd-security-attr.h',
'fwupd-security-attr-private.h',
'fwupd-release.c',
'fwupd-release.h',
'fwupd-release-private.h',
'fwupd-plugin.c',
'fwupd-plugin.h',
'fwupd-plugin-private.h',
'fwupd-remote.c',
'fwupd-remote.h',
'fwupd-remote-private.h',

View File

@ -341,8 +341,11 @@ fu_cabinet_set_container_checksum_cb (XbBuilderFixup *builder_fixup,
/* verify it is correct */
if (g_strcmp0 (xb_builder_node_get_text (csum), self->container_checksum) != 0) {
g_debug ("invalid container checksum %s, fixing up to %s",
xb_builder_node_get_text (csum), self->container_checksum);
if (xb_builder_node_get_text (csum) != NULL) {
g_warning ("invalid container checksum %s, fixing up to %s",
xb_builder_node_get_text (csum),
self->container_checksum);
}
xb_builder_node_set_text (csum, self->container_checksum, -1);
}
return TRUE;
@ -485,7 +488,7 @@ fu_cabinet_build_silo (FuCabinet *self, GBytes *data, GError **error)
g_autoptr(XbBuilderFixup) fixup2 = NULL;
/* verbose profiling */
if (g_getenv ("FWUPD_VERBOSE") != NULL) {
if (g_getenv ("FWUPD_XMLB_VERBOSE") != NULL) {
xb_builder_set_profile_flags (self->builder,
XB_SILO_PROFILE_FLAG_XPATH |
XB_SILO_PROFILE_FLAG_DEBUG);
@ -504,7 +507,6 @@ fu_cabinet_build_silo (FuCabinet *self, GBytes *data, GError **error)
/* adds each metainfo file to the silo */
for (guint i = 0; i < folders->len; i++) {
GCabFolder *cabfolder = GCAB_FOLDER (g_ptr_array_index (folders, i));
g_debug ("processing folder: %u/%u", i + 1, folders->len);
if (!fu_cabinet_build_silo_folder (self, cabfolder, error))
return FALSE;
}

View File

@ -444,10 +444,8 @@ fu_common_version_verify_format (const gchar *version,
return TRUE;
/* nothing we can check for */
if (fmt == FWUPD_VERSION_FORMAT_UNKNOWN) {
g_debug ("not checking %s as no version format set", version);
if (fmt == FWUPD_VERSION_FORMAT_UNKNOWN)
return TRUE;
}
/* check the base format */
fmt_guess = fu_common_version_guess_format (version);
@ -484,6 +482,13 @@ fu_common_vercmp_full (const gchar *version_a,
{
if (fmt == FWUPD_VERSION_FORMAT_PLAIN)
return g_strcmp0 (version_a, version_b);
if (fmt == FWUPD_VERSION_FORMAT_HEX) {
g_autofree gchar *hex_a = NULL;
g_autofree gchar *hex_b = NULL;
hex_a = fu_common_version_parse_from_format (version_a, fmt);
hex_b = fu_common_version_parse_from_format (version_b, fmt);
return fu_common_vercmp (hex_a, hex_b);
}
return fu_common_vercmp (version_a, version_b);
}

View File

@ -19,6 +19,10 @@
#include <shlwapi.h>
#endif
#ifdef HAVE_CPUID_H
#include <cpuid.h>
#endif
#include <archive_entry.h>
#include <archive.h>
#include <errno.h>
@ -31,11 +35,12 @@
#include "fu-common.h"
#include "fu-volume-private.h"
#define UDISKS_DBUS_SERVICE "org.freedesktop.UDisks2"
#define UDISKS_DBUS_PATH "/org/freedesktop/UDisks2/Manager"
#define UDISKS_DBUS_MANAGER_INTERFACE "org.freedesktop.UDisks2.Manager"
#define UDISKS_DBUS_PART_INTERFACE "org.freedesktop.UDisks2.Partition"
#define UDISKS_DBUS_FILE_INTERFACE "org.freedesktop.UDisks2.Filesystem"
#define UDISKS_DBUS_SERVICE "org.freedesktop.UDisks2"
#define UDISKS_DBUS_PATH "/org/freedesktop/UDisks2/Manager"
#define UDISKS_DBUS_MANAGER_INTERFACE "org.freedesktop.UDisks2.Manager"
#define UDISKS_DBUS_INTERFACE_PARTITION "org.freedesktop.UDisks2.Partition"
#define UDISKS_DBUS_INTERFACE_FILESYSTEM "org.freedesktop.UDisks2.Filesystem"
#define UDISKS_DBUS_INTERFACE_BLOCK "org.freedesktop.UDisks2.Block"
/**
* SECTION:fu-common
@ -159,7 +164,8 @@ fu_common_mkdir_parent (const gchar *filename, GError **error)
g_autofree gchar *parent = NULL;
parent = g_path_get_dirname (filename);
g_debug ("creating path %s", parent);
if (!g_file_test (parent, G_FILE_TEST_IS_DIR))
g_debug ("creating path %s", parent);
if (g_mkdir_with_parents (parent, 0755) == -1) {
g_set_error (error,
FWUPD_ERROR,
@ -1033,6 +1039,12 @@ fu_common_get_path (FuPathKind path_kind)
if (tmp != NULL)
return g_build_filename (tmp, FWUPD_LOCALSTATEDIR, NULL);
return g_build_filename (FWUPD_LOCALSTATEDIR, NULL);
/* /proc */
case FU_PATH_KIND_PROCFS:
tmp = g_getenv ("FWUPD_PROCFS");
if (tmp != NULL)
return g_strdup (tmp);
return g_strdup ("/proc");
/* /sys/firmware */
case FU_PATH_KIND_SYSFSDIR_FW:
tmp = g_getenv ("FWUPD_SYSFSFWDIR");
@ -1057,6 +1069,12 @@ fu_common_get_path (FuPathKind path_kind)
if (tmp != NULL)
return g_strdup (tmp);
return g_strdup ("/sys/kernel/security");
/* /sys/firmware/acpi/tables */
case FU_PATH_KIND_ACPI_TABLES:
tmp = g_getenv ("FWUPD_ACPITABLESDIR");
if (tmp != NULL)
return g_strdup (tmp);
return g_strdup ("/sys/firmware/acpi/tables");
/* /etc */
case FU_PATH_KIND_SYSCONFDIR:
tmp = g_getenv ("FWUPD_SYSCONFDIR");
@ -1217,6 +1235,9 @@ fu_common_strwidth (const gchar *text)
{
const gchar *p = text;
gsize width = 0;
g_return_val_if_fail (text != NULL, 0);
while (*p) {
gunichar c = g_utf8_get_char (p);
if (g_unichar_iswide (c))
@ -1679,6 +1700,49 @@ fu_common_fnmatch (const gchar *pattern, const gchar *str)
#endif
}
static gint
fu_common_filename_glob_sort_cb (gconstpointer a, gconstpointer b)
{
return g_strcmp0 (*(const gchar **)a, *(const gchar **)b);
}
/**
* fu_common_filename_glob:
* @directory: a directory path
* @pattern: a glob pattern, e.g. `*foo*`
* @error: A #GError or %NULL
*
* Returns all the filenames that match a specific glob pattern.
* Any results are sorted. No matching files will set @error.
*
* Return value: (element-type utf8) (transfer container): matching files, or %NULL
*
* Since: 1.5.0
**/
GPtrArray *
fu_common_filename_glob (const gchar *directory, const gchar *pattern, GError **error)
{
const gchar *basename;
g_autoptr(GDir) dir = g_dir_open (directory, 0, error);
g_autoptr(GPtrArray) files = g_ptr_array_new_with_free_func (g_free);
if (dir == NULL)
return NULL;
while ((basename = g_dir_read_name (dir)) != NULL) {
if (!fu_common_fnmatch (pattern, basename))
continue;
g_ptr_array_add (files, g_build_filename (directory, basename, NULL));
}
if (files->len == 0) {
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"no files matched pattern");
return NULL;
}
g_ptr_array_sort (files, fu_common_filename_glob_sort_cb);
return g_steal_pointer (&files);
}
/**
* fu_common_strnsplit:
* @str: a string to split
@ -1937,6 +2001,24 @@ fu_byte_array_append_uint32 (GByteArray *array, guint32 data, FuEndianType endia
g_byte_array_append (array, buf, sizeof(buf));
}
/**
* fu_byte_array_set_size:
* @array: a #GByteArray
* @length: the new size of the GByteArray
*
* Sets the size of the GByteArray, expanding it with NULs if necessary.
*
* Since: 1.5.0
**/
void
fu_byte_array_set_size (GByteArray *array, guint length)
{
guint oldlength = array->len;
g_byte_array_set_size (array, length);
if (length > oldlength)
memset (array->data + oldlength, 0x0, length - oldlength);
}
/**
* fu_common_kernel_locked_down:
*
@ -1971,6 +2053,83 @@ fu_common_kernel_locked_down (void)
#endif
}
/**
* fu_common_cpuid:
* @leaf: The CPUID level, now called the 'leaf' by Intel
* @eax: (out) (nullable): EAX register
* @ebx: (out) (nullable): EBX register
* @ecx: (out) (nullable): ECX register
* @edx: (out) (nullable): EDX register
* @error: A #GError or NULL
*
* Calls CPUID and returns the registers for the given leaf.
*
* Return value: %TRUE if the registers are set.
*
* Since: 1.5.0
**/
gboolean
fu_common_cpuid (guint32 leaf,
guint32 *eax,
guint32 *ebx,
guint32 *ecx,
guint32 *edx,
GError **error)
{
#ifdef HAVE_CPUID_H
guint eax_tmp = 0;
guint ebx_tmp = 0;
guint ecx_tmp = 0;
guint edx_tmp = 0;
/* get vendor */
__get_cpuid_count (leaf, 0x0, &eax_tmp, &ebx_tmp, &ecx_tmp, &edx_tmp);
if (eax != NULL)
*eax = eax_tmp;
if (ebx != NULL)
*ebx = ebx_tmp;
if (ecx != NULL)
*ecx = ecx_tmp;
if (edx != NULL)
*edx = edx_tmp;
return TRUE;
#else
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"no <cpuid.h> support");
return FALSE;
#endif
}
/**
* fu_common_is_cpu_intel:
*
* Uses CPUID to discover the CPU vendor and check if it is Intel.
*
* Return value: %TRUE if the vendor was Intel.
*
* Since: 1.5.0
**/
gboolean
fu_common_is_cpu_intel (void)
{
guint ebx = 0;
guint ecx = 0;
guint edx = 0;
if (!fu_common_cpuid (0x0, NULL, &ebx, &ecx, &edx, NULL))
return FALSE;
#ifdef HAVE_CPUID_H
if (ebx == signature_INTEL_ebx &&
edx == signature_INTEL_edx &&
ecx == signature_INTEL_ecx) {
return TRUE;
}
#endif
return FALSE;
}
/**
* fu_common_is_live_media:
*
@ -2006,16 +2165,21 @@ fu_common_is_live_media (void)
}
static GPtrArray *
fu_common_get_block_devices (GDBusConnection *connection, GError **error)
fu_common_get_block_devices (GError **error)
{
GVariantBuilder builder;
GVariant *input;
const gchar *obj;
g_autoptr(GVariant) output = NULL;
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GPtrArray) devices = NULL;
g_autoptr(GVariantIter) iter = NULL;
g_autoptr(GDBusConnection) connection = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
if (connection == NULL) {
g_prefix_error (error, "failed to get system bus: ");
return NULL;
}
proxy = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE, NULL,
UDISKS_DBUS_SERVICE,
@ -2027,17 +2191,36 @@ fu_common_get_block_devices (GDBusConnection *connection, GError **error)
return NULL;
}
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
input = g_variant_new ("(a{sv})", &builder);
output = g_dbus_proxy_call_sync (proxy,
"GetBlockDevices", g_variant_ref (input),
"GetBlockDevices",
g_variant_new ("(a{sv})", &builder),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, error);
if (output == NULL)
if (output == NULL) {
if (error != NULL)
g_dbus_error_strip_remote_error (*error);
g_prefix_error (error, "failed to call %s.%s(): ",
UDISKS_DBUS_SERVICE,
"GetBlockDevices");
return NULL;
devices = g_ptr_array_new_with_free_func (g_free);
}
devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
g_variant_get (output, "(ao)", &iter);
while (g_variant_iter_next (iter, "o", &obj))
g_ptr_array_add (devices, g_strdup (obj));
while (g_variant_iter_next (iter, "&o", &obj)) {
g_autoptr(GDBusProxy) proxy_blk = NULL;
proxy_blk = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE, NULL,
UDISKS_DBUS_SERVICE,
obj,
UDISKS_DBUS_INTERFACE_BLOCK,
NULL, error);
if (proxy_blk == NULL) {
g_prefix_error (error, "failed to initialize d-bus proxy for %s: ", obj);
return NULL;
}
g_ptr_array_add (devices, g_steal_pointer (&proxy_blk));
}
return g_steal_pointer (&devices);
}
@ -2047,9 +2230,7 @@ fu_common_get_block_devices (GDBusConnection *connection, GError **error)
* @kind: A volume kind, typically a GUID
* @error: A #GError or NULL
*
* Call into the plugin's get results routine
*
* Finds all volumes of a specific type
* Finds all volumes of a specific partition type
*
* Returns: (transfer container) (element-type FuVolume): a #GPtrArray, or %NULL if the kind was not found
*
@ -2058,56 +2239,56 @@ fu_common_get_block_devices (GDBusConnection *connection, GError **error)
GPtrArray *
fu_common_get_volumes_by_kind (const gchar *kind, GError **error)
{
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GPtrArray) devices = NULL;
g_autoptr(GPtrArray) volumes = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
if (connection == NULL) {
g_prefix_error (error, "failed to get system bus: ");
return NULL;
}
devices = fu_common_get_block_devices (connection, error);
devices = fu_common_get_block_devices (error);
if (devices == NULL)
return NULL;
volumes = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
for (guint i = 0; i < devices->len; i++) {
const gchar *obj = g_ptr_array_index (devices, i);
GDBusProxy *proxy_blk = g_ptr_array_index (devices, i);
const gchar *type_str;
g_autoptr(GDBusProxy) proxy_part = NULL;
g_autoptr(GDBusProxy) proxy_file = NULL;
g_autoptr(GError) error_local = NULL;
g_autoptr(GDBusProxy) proxy_fs = NULL;
g_autoptr(GVariant) val = NULL;
proxy_part = g_dbus_proxy_new_sync (connection,
proxy_part = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy_blk),
G_DBUS_PROXY_FLAGS_NONE, NULL,
UDISKS_DBUS_SERVICE,
obj,
UDISKS_DBUS_PART_INTERFACE,
g_dbus_proxy_get_object_path (proxy_blk),
UDISKS_DBUS_INTERFACE_PARTITION,
NULL, error);
if (proxy_part == NULL) {
g_prefix_error (error, "failed to initialize d-bus proxy %s: ", obj);
g_prefix_error (error, "failed to initialize d-bus proxy %s: ",
g_dbus_proxy_get_object_path (proxy_blk));
return NULL;
}
val = g_dbus_proxy_get_cached_property (proxy_part, "Type");
if (val == NULL)
continue;
g_variant_get (val, "s", &type_str);
g_debug ("device %s, type: %s", obj, type_str);
g_variant_get (val, "&s", &type_str);
g_debug ("device %s, type: %s",
g_dbus_proxy_get_object_path (proxy_blk), type_str);
if (g_strcmp0 (type_str, kind) != 0)
continue;
proxy_file = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE, NULL,
UDISKS_DBUS_SERVICE,
obj,
UDISKS_DBUS_FILE_INTERFACE,
NULL, error);
if (proxy_file == NULL) {
g_prefix_error (error, "failed to initialize d-bus proxy %s: ", obj);
proxy_fs = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy_blk),
G_DBUS_PROXY_FLAGS_NONE, NULL,
UDISKS_DBUS_SERVICE,
g_dbus_proxy_get_object_path (proxy_blk),
UDISKS_DBUS_INTERFACE_FILESYSTEM,
NULL, error);
if (proxy_fs == NULL) {
g_prefix_error (error, "failed to initialize d-bus proxy %s: ",
g_dbus_proxy_get_object_path (proxy_blk));
return NULL;
}
g_ptr_array_add (volumes, fu_volume_new_from_proxy (proxy_file));
g_ptr_array_add (volumes,
g_object_new (FU_TYPE_VOLUME,
"proxy-block", proxy_blk,
"proxy-filesystem", proxy_fs,
NULL));
}
if (volumes->len == 0) {
g_set_error (error,
@ -2119,6 +2300,90 @@ fu_common_get_volumes_by_kind (const gchar *kind, GError **error)
return g_steal_pointer (&volumes);
}
/**
* fu_common_get_volume_by_device:
* @device: A device string, typcically starting with `/dev/`
* @error: A #GError or NULL
*
* Finds the first volume from the specified device.
*
* Returns: (transfer full): a #GPtrArray, or %NULL if the kind was not found
*
* Since: 1.5.1
**/
FuVolume *
fu_common_get_volume_by_device (const gchar *device, GError **error)
{
g_autoptr(GPtrArray) devices = NULL;
/* find matching block device */
devices = fu_common_get_block_devices (error);
if (devices == NULL)
return NULL;
for (guint i = 0; i < devices->len; i++) {
GDBusProxy *proxy_blk = g_ptr_array_index (devices, i);
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy_blk, "Device");
if (val == NULL)
continue;
if (g_strcmp0 (g_variant_get_bytestring (val), device) == 0) {
return g_object_new (FU_TYPE_VOLUME,
"proxy-block", proxy_blk,
NULL);
}
}
/* failed */
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"no volumes for device %s",
device);
return NULL;
}
/**
* fu_common_get_volume_by_devnum:
* @devicenum: A device number
* @error: A #GError or NULL
*
* Finds the first volume from the specified device.
*
* Returns: (transfer full): a #GPtrArray, or %NULL if the kind was not found
*
* Since: 1.5.1
**/
FuVolume *
fu_common_get_volume_by_devnum (guint32 devnum, GError **error)
{
g_autoptr(GPtrArray) devices = NULL;
/* find matching block device */
devices = fu_common_get_block_devices (error);
if (devices == NULL)
return NULL;
for (guint i = 0; i < devices->len; i++) {
GDBusProxy *proxy_blk = g_ptr_array_index (devices, i);
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy_blk, "DeviceNumber");
if (val == NULL)
continue;
if (devnum == g_variant_get_uint64 (val)) {
return g_object_new (FU_TYPE_VOLUME,
"proxy-block", proxy_blk,
NULL);
}
}
/* failed */
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"no volumes for devnum %u",
devnum);
return NULL;
}
/**
* fu_common_get_esp_default:
* @error: A #GError or NULL
@ -2186,7 +2451,7 @@ fu_common_get_esp_for_path (const gchar *esp_path, GError **error)
return NULL;
for (guint i = 0; i < volumes->len; i++) {
FuVolume *vol = g_ptr_array_index (volumes, i);
g_autofree gchar *vol_basename = g_path_get_basename (fu_volume_get_id (vol));
g_autofree gchar *vol_basename = g_path_get_basename (fu_volume_get_mount_point (vol));
if (g_strcmp0 (basename, vol_basename) == 0)
return g_object_ref (vol);
}
@ -2197,3 +2462,101 @@ fu_common_get_esp_for_path (const gchar *esp_path, GError **error)
esp_path);
return NULL;
}
/**
* fu_common_crc8:
* @buf: memory buffer
* @bufsz: sizeof buf
*
* Returns the cyclic redundancy check value for the given memory buffer.
*
* Returns: CRC value
*
* Since: 1.5.0
**/
guint8
fu_common_crc8 (const guint8 *buf, gsize bufsz)
{
guint32 crc = 0;
for (gsize j = bufsz; j > 0; j--) {
crc ^= (*(buf++) << 8);
for (guint32 i = 8; i; i--) {
if (crc & 0x8000)
crc ^= (0x1070 << 3);
crc <<= 1;
}
}
return ~((guint8) (crc >> 8));
}
/**
* fu_common_crc16:
* @buf: memory buffer
* @bufsz: sizeof buf
*
* Returns the cyclic redundancy check value for the given memory buffer.
*
* Returns: CRC value
*
* Since: 1.5.0
**/
guint16
fu_common_crc16 (const guint8 *buf, gsize bufsz)
{
guint16 crc = 0xffff;
for (gsize len = bufsz; len > 0; len--) {
crc = (guint16) (crc ^ (*buf++));
for (guint8 i = 0; i < 8; i++) {
if (crc & 0x1) {
crc = (crc >> 1) ^ 0xa001;
} else {
crc >>= 1;
}
}
}
return ~crc;
}
/**
* fu_common_crc32_full:
* @buf: memory buffer
* @bufsz: sizeof buf
* @crc: initial CRC value, typically 0xFFFFFFFF
* @polynomial: CRC polynomial, typically 0xEDB88320
*
* Returns the cyclic redundancy check value for the given memory buffer.
*
* Returns: CRC value
*
* Since: 1.5.0
**/
guint32
fu_common_crc32_full (const guint8 *buf, gsize bufsz, guint32 crc, guint32 polynomial)
{
for (guint32 idx = 0; idx < bufsz; idx++) {
guint8 data = *buf++;
crc = crc ^ data;
for (guint32 bit = 0; bit < 8; bit++) {
guint32 mask = -(crc & 1);
crc = (crc >> 1) ^ (polynomial & mask);
}
}
return ~crc;
}
/**
* fu_common_crc32:
* @buf: memory buffer
* @bufsz: sizeof buf
*
* Returns the cyclic redundancy check value for the given memory buffer.
*
* Returns: CRC value
*
* Since: 1.5.0
**/
guint32
fu_common_crc32 (const guint8 *buf, gsize bufsz)
{
return fu_common_crc32_full (buf, bufsz, 0xFFFFFFFF, 0xEDB88320);
}

View File

@ -55,9 +55,11 @@ typedef guint FuEndianType;
* @FU_PATH_KIND_SYSFSDIR_FW: The sysfs firmware location (IE /sys/firmware)
* @FU_PATH_KIND_SYSFSDIR_DRIVERS: The platform sysfs directory (IE /sys/bus/platform/drivers)
* @FU_PATH_KIND_SYSFSDIR_TPM: The TPM sysfs directory (IE /sys/class/tpm)
* @FU_PATH_KIND_PROCFS: The procfs location (IE /proc)
* @FU_PATH_KIND_POLKIT_ACTIONS: The directory for policy kit actions (IE /usr/share/polkit-1/actions/)
* @FU_PATH_KIND_OFFLINE_TRIGGER: The file for the offline trigger (IE /system-update)
* @FU_PATH_KIND_SYSFSDIR_SECURITY: The sysfs security location (IE /sys/kernel/security)
* @FU_PATH_KIND_ACPI_TABLES: The location of the ACPI tables
*
* Path types to use when dynamically determining a path at runtime
**/
@ -73,9 +75,11 @@ typedef enum {
FU_PATH_KIND_SYSFSDIR_FW,
FU_PATH_KIND_SYSFSDIR_DRIVERS,
FU_PATH_KIND_SYSFSDIR_TPM,
FU_PATH_KIND_PROCFS,
FU_PATH_KIND_POLKIT_ACTIONS,
FU_PATH_KIND_OFFLINE_TRIGGER,
FU_PATH_KIND_SYSFSDIR_SECURITY,
FU_PATH_KIND_ACPI_TABLES,
/*< private >*/
FU_PATH_KIND_LAST
} FuPathKind;
@ -93,6 +97,9 @@ gboolean fu_common_spawn_sync (const gchar * const *argv,
gchar *fu_common_get_path (FuPathKind path_kind);
gchar *fu_common_realpath (const gchar *filename,
GError **error);
GPtrArray *fu_common_filename_glob (const gchar *directory,
const gchar *pattern,
GError **error);
gboolean fu_common_fnmatch (const gchar *pattern,
const gchar *str);
gboolean fu_common_rmtree (const gchar *directory,
@ -175,6 +182,8 @@ gboolean fu_common_read_uint32_safe (const guint8 *buf,
FuEndianType endian,
GError **error);
void fu_byte_array_set_size (GByteArray *array,
guint length);
void fu_byte_array_append_uint8 (GByteArray *array,
guint8 data);
void fu_byte_array_append_uint16 (GByteArray *array,
@ -219,9 +228,31 @@ gchar **fu_common_strnsplit (const gchar *str,
const gchar *delimiter,
gint max_tokens);
gboolean fu_common_kernel_locked_down (void);
gboolean fu_common_cpuid (guint32 leaf,
guint32 *eax,
guint32 *ebx,
guint32 *ecx,
guint32 *edx,
GError **error);
gboolean fu_common_is_cpu_intel (void);
gboolean fu_common_is_live_media (void);
GPtrArray *fu_common_get_volumes_by_kind (const gchar *kind,
GError **error);
FuVolume *fu_common_get_volume_by_device (const gchar *device,
GError **error);
FuVolume *fu_common_get_volume_by_devnum (guint32 devnum,
GError **error);
FuVolume *fu_common_get_esp_for_path (const gchar *esp_path,
GError **error);
FuVolume *fu_common_get_esp_default (GError **error);
guint8 fu_common_crc8 (const guint8 *buf,
gsize bufsz);
guint16 fu_common_crc16 (const guint8 *buf,
gsize bufsz);
guint32 fu_common_crc32 (const guint8 *buf,
gsize bufsz);
guint32 fu_common_crc32_full (const guint8 *buf,
gsize bufsz,
guint32 crc,
guint32 polynomial);

View File

@ -16,12 +16,11 @@ gboolean fu_device_has_parent_guid (FuDevice *self,
const gchar *guid);
void fu_device_set_parent (FuDevice *self,
FuDevice *parent);
guint fu_device_get_order (FuDevice *self);
gint fu_device_get_order (FuDevice *self);
void fu_device_set_order (FuDevice *self,
guint order);
gint order);
void fu_device_set_alternate (FuDevice *self,
FuDevice *alternate);
GType fu_device_get_specialized_gtype (FuDevice *self);
gboolean fu_device_ensure_id (FuDevice *self,
GError **error);
void fu_device_incorporate_from_component (FuDevice *device,
@ -29,3 +28,5 @@ void fu_device_incorporate_from_component (FuDevice *device,
void fu_device_convert_instance_ids (FuDevice *self);
gchar *fu_device_get_guids_as_str (FuDevice *self);
GPtrArray *fu_device_get_possible_plugins (FuDevice *self);
void fu_device_add_possible_plugin (FuDevice *self,
const gchar *plugin);

Some files were not shown because too many files have changed in this diff Show More