diff -Nru fwupd-1.4.5/data/installed-tests/fakedevice124.bin fwupd-1.5.8/data/installed-tests/fakedevice124.bin
--- fwupd-1.4.5/data/installed-tests/fakedevice124.bin 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/fakedevice124.bin 2021-03-31 20:08:32.000000000 +0000
@@ -1 +1 @@
-fakedevice124 -n
+0x1020004
diff -Nru fwupd-1.4.5/data/installed-tests/fakedevice124.bin.asc fwupd-1.5.8/data/installed-tests/fakedevice124.bin.asc
--- fwupd-1.4.5/data/installed-tests/fakedevice124.bin.asc 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/fakedevice124.bin.asc 2021-03-31 20:08:32.000000000 +0000
@@ -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-----
diff -Nru fwupd-1.4.5/data/installed-tests/fakedevice124.metainfo.xml fwupd-1.5.8/data/installed-tests/fakedevice124.metainfo.xml
--- fwupd-1.4.5/data/installed-tests/fakedevice124.metainfo.xml 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/fakedevice124.metainfo.xml 2021-03-31 20:08:32.000000000 +0000
@@ -1,8 +1,8 @@
- fakedevice.firmware
- FakeDevice Firmware
+ org.fwupd.fakedevice.firmware
+ FakeDevice
Firmware for the ACME Corp Integrated Webcam
diff -Nru fwupd-1.4.5/data/installed-tests/fwupdmgr.sh fwupd-1.5.8/data/installed-tests/fwupdmgr.sh
--- fwupd-1.4.5/data/installed-tests/fwupdmgr.sh 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/fwupdmgr.sh 2021-03-31 20:08:32.000000000 +0000
@@ -1,7 +1,6 @@
#!/bin/bash
exec 2>&1
-dirname=`dirname $0`
device=08d460be0f1f9f128413f816022a6439e0078018
error()
@@ -43,7 +42,7 @@
# ---
echo "Installing test firmware..."
-fwupdmgr install ${dirname}/fakedevice124.cab
+fwupdmgr update $device -y
rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
# ---
@@ -56,9 +55,14 @@
fwupdmgr verify $device
rc=$?; if [[ $rc != 0 ]]; then error $rc; fi
+if [ -z "$CI_NETWORK" ]; then
+ echo "Skipping remaining tests due to CI_NETWORK not being set"
+ exit 0
+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 +72,7 @@
# ---
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
# ---
diff -Nru fwupd-1.4.5/data/installed-tests/fwupd.sh fwupd-1.5.8/data/installed-tests/fwupd.sh
--- fwupd-1.4.5/data/installed-tests/fwupd.sh 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/fwupd.sh 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+exec 2>&1
+dirname=`dirname $0`
+
+run_test()
+{
+ if [ -f $dirname/$1 ]; then
+ $dirname/$1
+ rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
+ 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
diff -Nru fwupd-1.4.5/data/installed-tests/fwupd.test.in fwupd-1.5.8/data/installed-tests/fwupd.test.in
--- fwupd-1.4.5/data/installed-tests/fwupd.test.in 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/fwupd.test.in 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,3 @@
+[Test]
+Type=session
+Exec=sh -c "@installedtestsbindir@/fwupd.sh"
diff -Nru fwupd-1.4.5/data/installed-tests/meson.build fwupd-1.5.8/data/installed-tests/meson.build
--- fwupd-1.4.5/data/installed-tests/meson.build 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/meson.build 2021-03-31 20:08:32.000000000 +0000
@@ -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 @@
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_dir : installed_test_datadir,
)
+install_data([
+ 'fwupd.sh',
+ ],
+ install_dir : installed_test_bindir,
+)
+
custom_target('installed-cab123',
input : [
'fakedevice123.bin',
diff -Nru fwupd-1.4.5/data/installed-tests/README.md fwupd-1.5.8/data/installed-tests/README.md
--- fwupd-1.4.5/data/installed-tests/README.md 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/installed-tests/README.md 2021-03-31 20:08:32.000000000 +0000
@@ -9,7 +9,7 @@
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
```
diff -Nru fwupd-1.4.5/data/meson.build fwupd-1.5.8/data/meson.build
--- fwupd-1.4.5/data/meson.build 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/meson.build 2021-03-31 20:08:32.000000000 +0000
@@ -49,7 +49,7 @@
con2.set('localstatedir', localstatedir)
con2.set('package_name', meson.project_name())
rw_directories = []
- if get_option('plugin_uefi')
+ if get_option('plugin_uefi_capsule')
rw_directories += ['-/boot/efi', '-/efi/EFI', '-/boot/EFI']
endif
diff -Nru fwupd-1.4.5/data/motd/fwupd-refresh.service.in fwupd-1.5.8/data/motd/fwupd-refresh.service.in
--- fwupd-1.4.5/data/motd/fwupd-refresh.service.in 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/motd/fwupd-refresh.service.in 2021-03-31 20:08:32.000000000 +0000
@@ -14,4 +14,4 @@
ProtectControlGroups=yes
RestrictRealtime=yes
SuccessExitStatus=2
-ExecStart=@bindir@/fwupdmgr refresh --no-metadata-check
+ExecStart=@bindir@/fwupdmgr refresh
diff -Nru fwupd-1.4.5/data/org.freedesktop.fwupd.metainfo.xml fwupd-1.5.8/data/org.freedesktop.fwupd.metainfo.xml
--- fwupd-1.4.5/data/org.freedesktop.fwupd.metainfo.xml 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/org.freedesktop.fwupd.metainfo.xml 2021-03-31 20:08:32.000000000 +0000
@@ -30,70 +30,263 @@
fwupdmgr
+ fwupdtool
+ fwupdtpmevlog
+ fwupdagent
-
+
This release adds the following features:
- - Add dual-image feature for VL103 backup firmware
- - Add more CCGX hybrid dock support
- - Add support for a delayed activation flow for Thunderbolt
- - Allow firmware to require specific features from front-end clients
- - Modernize the thunderbolt plugin for future hardware
- - Support LVFS::UpdateImage in GUI clients
+ - Add a new internal flag to opt-in to GUID matching
+ - Add D501 Baklava device support
+ - Add fu_device_set_battery_level()
+ - Add missing uint64 read and write helpers
+ - Add Qubes wrapper source and create packages
+ - Allow enabling plugins only matching a specific HwId
+ - Prompt for unlock keypress if reset command is blocked
+ - Remove obsolete dell-dock non-passive update flow support
+ - Remove the Hughski public key
+ - Show a warning when parsing invalid quirk files
+ - Support for GATT characteristic signals/notifications
+ - Support more than one protocol for a given device
This release fixes the following bugs:
- - Be more defensive when remotes are missing required keys
- - Check all AppStream components when verifying
- - Check for free space after cleaning up ESP
- - Fix TPM PCR0 calculation
- - Only show UpdateMessage when state is success
- - Read the modem vendor ID correctly
- - Set the runtime version to 0.0.0 for pre-1.0.0 Thelio Io firmware
- - Support compiling libqmi-glib 1.26.0 and later
- - Use the GPIOB reset for the MiniDock VL103
- - Wait for the root device to be replugged when updating the MSP430
+ - Align the CCGX DMC firmware to 64 byte chunks
+ - Be more strict for custom quirk keys
+ - Check pixart firmware compatibility with hardware before flashing
+ - Correct a thunderbolt assertion if kernel failed FW read
+ - Correctly erase STM32 devices when transfer size is less than sector size
+ - Detect SREC overflow to avoid adding ~4GB of 0xFF padding
+ - Do not show a critical error when flashing footer-less binary files
+ - Don't allow device updates while needing activation
+ - Fix a regression in the elantp defined IAP start address
+ - Fix a regression where activate stopped working
+ - Fix firmware update of pointing device on Lenovo ThinkPad Nano
+ - Fix the HSI plugin 'Disabled' state
+ - Fix the quirk key name for the Lenovo HDMI with power
+ - Fix writing to the GD32VF103 bootloader
+ - Only call elantp->detach() when writing a firmware blob
+ - Updated StarLabs GUIDs
+ - Wait a few ms for the Logitech hardware to settle after detach
-
+
- This release fixes the following regression:
+ This release adds the following features:
- - Fix refreshing when checking for downgraded metadata
+ - Add initial support for Bluez bluetooth devices
+ - Add more supported pixart devices
+ - Add support for the RTD21xx HDMI converter
+
+ This release fixes the following bugs:
+
+ - Convert MBR types to GPT GUIDs to help find the ESP
+ - Do not allow updating a synaptics-mst device with no customer ID
+ - Drop unused heap pages after startup has completed
+ - Ensure SBAT metadata is added correctly
+ - Move the plugin build logic to the plugins themselves
+ - Only allow verify-update for plugins that support CAN_VERIFY
-
+
This release adds the following features:
- - Add support for HP DMC dock devices
+ - Add SBAT metadata to the fwupd EFI binary
+ - Add support for GD32VF103 as found in the Longan Nano
+ - Add support for RMI PS2 devices
+ - Add support for the System76 Keyboard
+ - Allow downloading firmware from IPFS
+ - Install the UX data into a single .tar.xz file
This release fixes the following bugs:
- - Always enforce the metadata signature has a valid timestamp
- - Capture the dock SKU in metadata
- - Check the device requirements when returning from GetDetails
- - Force the prometheus minor version from 0x02 to 0x01
- - Prevent Dell dock updates to occur via synaptics-mst plugin
+ - Add support for the Starlabs LabTop L4
+ - Allow using an external ESP again
+ - Ask the user to reboot when required if downgrading
+ - Be more paranoid when parsing ASCII buffers and devices
+ - Check if the fwupd BootXXXX entry exists on failure
+ - Clear the pending flag if restarting the system
+ - Do not allow flashing using flashrom if BLE is enabled
+ - Do not allow Lenovo hardware to install multiple capsules
+ - Do not parse the OptionROM image
+ - Do not show Unknown [***] for every client connection
+ - Fix dnload wBlockNum wraparound for ST devices
+ - Fix OOM when using large ArchiveSizeMax values
+ - Fix several crashes spotted by AddressSanitizer
+ - Fix several places where the Goodix MOC plugin could crash
+ - Include the PCR0 to the report metadata
+ - Report the lockdown status from UEFI and SuperIO plugins
+ - Show a console warning if the system clock is not set
-
+
+ This release adds the following features:
+
+ - Add a plugin to update PixArt RF devices
+ - Add new hardware to use the elantp and rts54hid plugins
+ - Allow specifying more than one VendorID for a device
+ - Detect the AMD TSME encryption state for HSI-4
+ - Detect the AMI PK test key is not installed for HSI-1
+
This release fixes the following bugs:
- - Add several more ATA OUI quirks
- - Avoid communicating with DFU devices when bitManifestationTolerant is off
- - Correct the display of final calculated PCRs
- - Delay activation for Dell Thunderbolt updates
- - Do not use synaptics-rmi on the Dell K12A
- - Fix switching wacom-raw to bootloader mode
- - Switch the default of EnumerateAllDevices to false
- - Use GPIOB to reset the VL817 found in two Lenovo products
+ - Fix flashing a fingerprint reader that is in use
+ - Fix several critical warnings when parsing invalid firmware
+ - Fix updating DFU devices that use DNLOAD_BUSY
+ - Ignore the legacy UEFI OVMF dummy GUID
+ - Make libfwupd more thread safe to fix a crash in gnome-software
+ - Never show unprintable chars from invalid firmware in the logs
+
+
+
+
+
+ This release adds the following features:
+
+ - Add Maple Ridge Thunderbolt firmware parsing support
+ - Add --no-remote-check to ignore checking for download remotes
+ - Allow creating FMAP and Synaptics firmware using builder.xml
+ - Build a test harness that uses honggfuzz to fuzz firmware
+
+ This release fixes the following bugs:
+
+ - Allow using fwupdtool as non-root for firmware commands
+ - Do not trust the Block.HintSystem boolean for ESP filtering
+ - Fix a memory leak when parsing Synaptics firmware
+ - Fix a possible crash when reading the Goodix MOC USB request
+ - Fix crashes when parsing invalid FMAP, DMC, Solokey and Synaptics images
+
+
+
+
+
+ This release adds the following features:
+
+ - Allow setting the GMainContext when used for sync methods
+ - Export the driver name from FuUdevDevice
+
+ This release fixes the following bugs:
+
+ - Add a UEFI quirk for Star Labs Lite Mk III
+ - Add the device firmare ID for serio class hardware
+ - Allow the client to send legacy PKCS7 and GPG signatures
+ - Do not use accidentally depend on new meson versions
+ - Fix a possible critical warning due to missing retval
+ - Fix the endianness for the CRC check in bcm57xx
+ - Lower the CURL version required to fix RHEL
+ - Make sure the correct interface number is used for QMI
+ - Mark more user-visible strings as translatable
+ - Restrict loading component types of firmware
+ - Validate ModemManager firmware update method combinations
+
+
+
+
+
+ This release adds the following features:
+
+ - Add a flag to indicate if packages are supported
+ - Add a plugin for the Pinebook Pro laptop
+ - Allow components to set the icon from the metadata
+ - Switch from libsoup to libcurl for downloading data
+
+ This release fixes the following bugs:
+
+ - Fall back to FAT32 internal partitions for detecting ESP
+ - Fix detection of ColorHug version on older firmware versions
+ - Fix reading BCM57XX vendor and device ids from firmware
+ - Fix replugging the MSP430 device
+ - Fix sync method when called from threads without a context
+ - Ignore an invalid vendor-id when adding releases for display
+ - Improve synaptics-mst reliability when writing data
+ - Install modules-load configs in the correct directory
+ - Notify the service manager when idle-quitting
+ - Only download the remote metadata as required
+ - Remove HSI update and attestation suffixes
+ - Restore recognizing GPG and PKCS7 signature types in libfwupd
+ - Set the SMBIOS chassis type to portable if a DT battery exists
+
+
+
+
+
+ This release adds the following features:
+
+ - Include the amount of NVRAM size in use in the LVFS failure report
+
+ This release fixes the following bugs:
+
+ - Delete unused EFI variables when deploying firmware
+ - Fix probe warning for the Logitech Unifying device
+ - Make bcm57xx hotplug more reliable
+ - Recognize authorized thunderbolt value of 2
+ - Remove the duplicate parent-child data in FwupdDevice and FuDevice
+ - Show a less scary fwupdate output for devices without info
+ - Show a link to discover more information about a specific plugin failure
+ - Use a different Device ID for the OptionROM devices
+ - Use UDisks to find out if swap devices are encrypted
+
+
+
+
+
+ This release adds the following features:
+
+ - Add a compatible re-implementation of the rhboot dbxtool
+ - Add async versions of the library for GUI tools
+ - Add commands for interacting with the ESP to fwupdtool
+ - Add firmware-extract subcommand to fwupdtool
+ - Add FwupdPlugin so we can convey enumerated system errors to the end user
+ - Add plugin for Goodix fingerprint sensors
+ - Add plugin that can update the BCM5719 network adapter
+ - Add plugin to update Elan Touchpads using HID
+ - Add support for a delayed activation flow for Thunderbolt
+ - Add support for ChromeOS Quiche and Gingerbread
+ - Add support for Hyper hardware
+ - Add support for the Host Security ID
+ - Add support for ThunderBolt retimers
+ - Add switch-branch command to fwupdtool and fwupdmgr
+ - Allow blocking specific firmware releases by checksum
+ - Allow constructing a firmware with multiple images
+ - Allow firmware to require specific features from front-end clients
+ - Allow updating the dbx using the LVFS, validating it is safe to apply
+ - Include the HSI results and attributes in the uploaded report
+ - Support loading DMI data from DT systems
+ - Support LVFS::UpdateImage for GUI clients
+
+ This release fixes the following bugs:
+
+ - Allow compiling the daemon without polkit support
+ - Always look at all TPM eventlog supported algorithms
+ - Change all instances of master/slave to initiator/target
+ - Correctly order devices when using logical parents
+ - Do not dedupe NVMe or VLI PD devices
+ - Do not expose the VLI shared-SPI devices on the USB2 recovery device
+ - Do not fix up the version on post-update mismatch
+ - Download the metadata first when using 'fwupdtool refresh'
+ - Drop efivar dependency
+ - Drop support for ThunderBolt force power due to hardware issues
+ - Fix setting BootNext correctly when multiple updates are scheduled
+ - Fix the topology of the audio device on the Lenovo TR dock
+ - Make return code different for get-updates with no updates
+ - Make specific authorizations also imply others
+ - Make TPM support more optional
+ - Parse the HEX version before comparing for equality
+ - Prevent dell-dock updates to occur via synaptics-mst plugin
+ - Record the UEFI failure in more cases
+ - Retry the HID SetReport to fix flashing the TB3 dock
+ - Show an error when a plugin is missing dependencies
+ - Use libxmlb bound parameters to speed up the device verification
+ - Use pkttyagent to request user passwords if running without GUI
+ - Use the JCat file to select the metadata file
@@ -168,6 +361,32 @@
+
+
+ This release adds the following features:
+
+ - Added completion script for fish shell
+ - Inihbit all power management actions using logind when updating
+
+ This release fixes the following bugs:
+
+ - Always check for PLAIN when doing vercmp() operations
+ - Always return AppStream markup for remote agreements
+ - Apply UEFI capsule update even with single valid capsule
+ - Check the device protocol before de-duping devices
+ - Copy the version and format from donor device in get-details
+ - Correctly append the release to devices in `fwupdtool get-details`
+ - Decrease minimum battery requirement to 10%
+ - Discard the reason upgrades aren't available
+ - Do not fail loading in /etc/machine-id is not available
+ - Fix a critical warning when installing some firmware
+ - For the `get-details` command make sure to always show devices
+ - Set the MSP430 version format to pair
+ - Switch off the ATA verbose logging by default
+ - Use unknown for version format by default on get-details
+
+
+
This release adds the following features:
@@ -486,7 +705,7 @@
Do not fail to start the daemon if tpm2_pcrlist hangs
Do not fail when scheduling more than one update to be run offline
Do not let failing to find DBus prevent fwuptool from starting
- Do not schedule an update on battery power if it requires AC power
+ Do not schedule an update on battery power if it requires an external power source
Include all device checksums in the LVFS report
Rename the shimx64.efi binary for known broken firmware
Upload the UPDATE_INFO entry for the UEFI UX capsule
diff -Nru fwupd-1.4.5/data/pki/GPG-KEY-Hughski-Limited fwupd-1.5.8/data/pki/GPG-KEY-Hughski-Limited
--- fwupd-1.4.5/data/pki/GPG-KEY-Hughski-Limited 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/pki/GPG-KEY-Hughski-Limited 1970-01-01 00:00:00.000000000 +0000
@@ -1,30 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1
-
-mQENBFUr0UoBCACsdOLuTJ81dICrSvUhyznBsL4WgEa2RUbEjJuaXwrEyPMikHE1
-Clda2YI7VbpCgIVq8Zy63CGJ4Xqs2T6pyetaXnbX8J0C+7wg2IfPv7pUyCsP7/JR
-HRB2GNelCWrsGArN1cOPI0ESH4yHWKF9KCGlpsLfSHmvF7D8vcKlKQUlO4T6lxOP
-SNjMSXkMsxfDDhl1mzqrwxfU4V6nnPcuMwU7tvg+39PioP4Ny1tKP4SSpBfh7qwz
-XXRd505dqNLOubxmOPZ5rznVkKmW2cwahO6fr5zVA8/2TDZQ79mdbfvSJVlW06qs
-C5PYmLnBjyzE5uQ4oxSIuUEiMfqrn3Qs6PhhABEBAAG0Ikh1Z2hza2kgTGltaXRl
-ZCA8aW5mb0BodWdoc2tpLmNvbT6JATgEEwECACIFAlUr0UoCGwMGCwkIBwMCBhUI
-AgkKCwQWAgMBAh4BAheAAAoJEK2KUo/sRIge/fUH/Rblgzh5GeB0Zp2U9W+r26iJ
-t1AD5a/fKxQahz/pwMkevQCCMzI1vpX12P3HtACZOD3Zjh9RXY6Z3033YZjrRApe
-FkOVfcyUF1nP/z2Ox3jE3+B8v1u0UzH/MqtF/1095mqvR7gllE288KDqu7bvd5l3
-z4IETk5qqoeCe9LYc8aob973dbocyS/gou/FLCKxoXVEe8DPRwv8qmXlXOujxdxd
-FcslpYqtjj4fgUswQ/cY/a1UcAX5zCnVqFbU7oJH2uTNewKuaZ2wgPbnzvwx8JYl
-VfFdPN7GZ0NMrZDLeJ0SLXer/9+qAKNH4UpQS9axXQL+VKOzsZCXuv31VDCj5Jy5
-AQ0EVSvRSgEIAMgVrZP3LmA9bx7B8l+agVh5DNXrMixX9jhZ0Yfn8+UIMMNTZziD
-ZV3nXxswKPrcsqQ+KP9iUwq3V2oio46bvHiMMoZSGCaTv4yiKOliFOMYr9NAOSTZ
-8mOI24dNXI9XqQ7ZA8m4uKmgHZQUIUUlx693uRI2Wmk/Y5XEBoL2+XdA5KalO+36
-27YXpdyU3GiMCOtSBLWNfBxXw6oKdNUp+8o/fYrmQnBxuGgmVlcZEmjhrIGXaCH1
-iDeWIFqaM/S+DXMF3bgqvqRZq1U2RwT2oxapAuaG/0I5JaKKpb3HqMCXfOUxpFPk
-zgUYpHatUcePG/94K8N8CRjnJ+l83H5PewcAEQEAAYkBHwQYAQIACQUCVSvRSgIb
-DAAKCRCtilKP7ESIHrrcCACc6UTZzVGbVq9pXSz2Bw2xQpAEAhnnedPgfXwEJMM0
-24bMUNsyJcQZAW1d5KfJYNAihOfse3oDQ/hJAycTK3GAHsPfljEQjWGn27eC8Fxu
-mHpfNpxbTirChfepCNctZG818Hp2v+K4X/PjyQMQ6J5H9oinnlasVQ6wzdZifnWm
-7E5OL0NV/ni9xqq4fC5y5qxNBeYVmHUF4H0E3VOuCbESAOnUDpCo998Dc68eZEmV
-f3IMukvvnxM9VOZQSnp7J/kkhPB5fim2z2qrlJK9N+tBjAMugxtnAV2fIaZYTiba
-SnN2hheFd9Y0nMmWbwRqFtwMG1m/tS3JlD52Rpwzk59B
-=WFoi
------END PGP PUBLIC KEY BLOCK-----
diff -Nru fwupd-1.4.5/data/pki/meson.build fwupd-1.5.8/data/pki/meson.build
--- fwupd-1.4.5/data/pki/meson.build 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/pki/meson.build 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,4 @@
install_data([
- 'GPG-KEY-Hughski-Limited',
'GPG-KEY-Linux-Foundation-Firmware',
'GPG-KEY-Linux-Vendor-Firmware-Service',
],
diff -Nru fwupd-1.4.5/data/remotes.d/lvfs.conf fwupd-1.5.8/data/remotes.d/lvfs.conf
--- fwupd-1.4.5/data/remotes.d/lvfs.conf 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/remotes.d/lvfs.conf 2021-03-31 20:08:32.000000000 +0000
@@ -5,6 +5,8 @@
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
diff -Nru fwupd-1.4.5/data/tests/daemon.conf fwupd-1.5.8/data/tests/daemon.conf
--- fwupd-1.4.5/data/tests/daemon.conf 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/tests/daemon.conf 2021-03-31 20:08:32.000000000 +0000
@@ -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;test_ble;invalid
# Maximum archive size that can be loaded in Mb, with 0 for the default
ArchiveSizeMax=0
@@ -32,3 +32,13 @@
# A list of firmware checksums that has been approved by the site admin
# If unset, all firmware is approved
ApprovedFirmware=
+
+# Allow blocking specific devices by their checksum, either SHA1 or SHA256
+# Uses semicolons as delimiter
+BlockedFirmware=
+
+# Allowed URI schemes in the preference order; failed downloads from the first
+# scheme will be retried with the next in order until no choices remain.
+#
+# If unset or no schemes are listed, the default will be: file,https,http,ipfs
+UriSchemes=
diff -Nru fwupd-1.4.5/data/tests/devicetree/base/ibm,firmware-versions/version fwupd-1.5.8/data/tests/devicetree/base/ibm,firmware-versions/version
--- fwupd-1.4.5/data/tests/devicetree/base/ibm,firmware-versions/version 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/tests/devicetree/base/ibm,firmware-versions/version 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+1.2.3-4
\ No newline at end of file
diff -Nru fwupd-1.4.5/data/tests/devicetree/base/model fwupd-1.5.8/data/tests/devicetree/base/model
--- fwupd-1.4.5/data/tests/devicetree/base/model 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/tests/devicetree/base/model 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+ColorHug
\ No newline at end of file
diff -Nru fwupd-1.4.5/data/tests/devicetree/base/model-name fwupd-1.5.8/data/tests/devicetree/base/model-name
--- fwupd-1.4.5/data/tests/devicetree/base/model-name 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/tests/devicetree/base/model-name 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+To Be Filled By O.E.M.
\ No newline at end of file
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/devicetree/base/name and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/devicetree/base/name differ
diff -Nru fwupd-1.4.5/data/tests/devicetree/base/vendor fwupd-1.5.8/data/tests/devicetree/base/vendor
--- fwupd-1.4.5/data/tests/devicetree/base/vendor 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/tests/devicetree/base/vendor 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+Hughski Limited
\ No newline at end of file
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/devicetree/base/vpd/name and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/devicetree/base/vpd/name differ
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/name and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/name differ
diff -Nru fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/part-number fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/part-number
--- fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/part-number 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/part-number 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+PCB-CH001
\ No newline at end of file
diff -Nru fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/vendor fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/vendor
--- fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/vendor 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/vendor 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+Richard Hughes
\ No newline at end of file
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/name and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/enclosure@1e00/name differ
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/devicetree/base/vpd/root-node-vpd@a000/name and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/devicetree/base/vpd/root-node-vpd@a000/name differ
diff -Nru fwupd-1.4.5/data/tests/firmware-base-uri.conf fwupd-1.5.8/data/tests/firmware-base-uri.conf
--- fwupd-1.4.5/data/tests/firmware-base-uri.conf 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/tests/firmware-base-uri.conf 2021-03-31 20:08:32.000000000 +0000
@@ -1,6 +1,6 @@
[fwupd Remote]
Enabled=true
Type=download
-Keyring=gpg
+Keyring=jcat
MetadataURI=https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz
FirmwareBaseURI=https://my.fancy.cdn/
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/firmware.dfuse and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/firmware.dfuse differ
Binary files /tmp/tmpL43cVd/35odgmMgHT/fwupd-1.4.5/data/tests/firmware.fmap and /tmp/tmpL43cVd/PDLFbnBkMt/fwupd-1.5.8/data/tests/firmware.fmap differ
diff -Nru fwupd-1.4.5/data/tests/firmware-nopath.conf fwupd-1.5.8/data/tests/firmware-nopath.conf
--- fwupd-1.4.5/data/tests/firmware-nopath.conf 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/tests/firmware-nopath.conf 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
[fwupd Remote]
Enabled=true
Type=download
-Keyring=gpg
+Keyring=jcat
MetadataURI=https://s3.amazonaws.com/lvfsbucket/downloads/firmware.xml.gz
diff -Nru fwupd-1.4.5/data/tests/multiple-rels/firmware.metainfo.xml fwupd-1.5.8/data/tests/multiple-rels/firmware.metainfo.xml
--- fwupd-1.4.5/data/tests/multiple-rels/firmware.metainfo.xml 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/tests/multiple-rels/firmware.metainfo.xml 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
-
+
com.hughski.test.firmware
diff -Nru fwupd-1.4.5/data/tests/quirks.d/tests.quirk fwupd-1.5.8/data/tests/quirks.d/tests.quirk
--- fwupd-1.4.5/data/tests/quirks.d/tests.quirk 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/data/tests/quirks.d/tests.quirk 2021-03-31 20:08:32.000000000 +0000
@@ -2,16 +2,16 @@
Flags= ignore-runtime
[ACME Inc.=True]
-Test = awesome
+Name = awesome
[CORP*]
-Test = town
+Name = town
-[DeviceInstanceId=USB\VID_0BDA&PID_1100]
+[USB\VID_0BDA&PID_1100]
Flags = clever
Name = Hub
Children = FuDevice|USB\VID_0763&PID_2806&I2C_01
-[DeviceInstanceId=USB\VID_0763&PID_2806&I2C_01]
+[USB\VID_0763&PID_2806&I2C_01]
Name = HDMI
Flags = updatable,internal
diff -Nru fwupd-1.4.5/debian/changelog fwupd-1.5.8/debian/changelog
--- fwupd-1.4.5/debian/changelog 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/changelog 2021-03-31 20:08:32.000000000 +0000
@@ -1,6 +1,6 @@
-fwupd (1.4.5-1pop0~1611677200~21.04~aaada71~dev) hirsute; urgency=medium
+fwupd (1.5.8-0ubuntu1pop0~1617221312~21.04~a9de48d~dev) hirsute; urgency=medium
* Auto Build
- -- Pop OS (ISO Signing Key) Tue, 26 Jan 2021 09:06:40 -0700
+ -- Pop OS (ISO Signing Key) Wed, 31 Mar 2021 14:08:32 -0600
diff -Nru fwupd-1.4.5/debian/control fwupd-1.5.8/debian/control
--- fwupd-1.4.5/debian/control 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/control 2021-03-31 20:08:32.000000000 +0000
@@ -23,6 +23,7 @@
libarchive-dev,
libcairo-dev,
libcairo-gobject2,
+ libcurl4-gnutls-dev,
libefiboot-dev [amd64 arm64 armhf i386],
libefivar-dev [amd64 arm64 armhf i386],
libelf-dev,
@@ -32,15 +33,15 @@
libgirepository1.0-dev,
libglib2.0-dev (>= 2.45.8),
libgudev-1.0-dev,
- libgusb-dev (>= 0.2.9),
+ libgusb-dev (>= 0.3.4),
libjcat-dev,
libjson-glib-dev (>= 1.1.1),
libmm-glib-dev,
libpolkit-gobject-1-dev,
libqmi-glib-dev,
libsmbios-dev [i386 amd64],
- libsoup2.4-dev,
libsqlite3-dev,
+ libsystemd-dev,
libtool-bin,
libtss2-dev,
libxmlb-dev (>= 0.1.13),
@@ -102,7 +103,11 @@
shared-mime-info
Recommends: python3,
bolt,
+ dbus,
+ secureboot-db,
+ udisks2,
fwupd-signed
+Suggests: gir1.2-fwupd-2.0
Provides: fwupdate
Conflicts: fwupdate-amd64-signed,
fwupdate-i386-signed,
@@ -110,6 +115,7 @@
fwupdate-armhf-signed
Breaks: gir1.2-dfu-1.0 (<< 0.9.7-1),
libdfu1 (<< 0.9.7-1),
+ fwupdate (<< 12-7),
libdfu-dev (<< 0.9.7-1)
Replaces: gir1.2-dfu-1.0 (<< 0.9.7-1),
libdfu1 (<< 0.9.7-1),
@@ -168,6 +174,10 @@
Multi-Arch: same
Depends: libfwupd2 (= ${binary:Version}),
gir1.2-fwupd-2.0 (= ${binary:Version}),
+ libcurl4-gnutls-dev,
+ libglib2.0-dev (>= 2.45.8),
+ libjcat-dev,
+ libjson-glib-dev (>= 1.1.1),
${misc:Depends}
Breaks: fwupd-dev (<< 0.5.4-2~)
Replaces: fwupd-dev (<< 0.5.4-2~)
@@ -198,6 +208,17 @@
Multi-Arch: same
Depends: libfwupdplugin1 (= ${binary:Version}),
gir1.2-fwupdplugin-1.0 (= ${binary:Version}),
+ libarchive-dev,
+ libcurl4-gnutls-dev,
+ libfwupd-dev (= ${binary:Version}),
+ libgcab-dev,
+ libglib2.0-dev (>= 2.45.8),
+ libgudev-1.0-dev,
+ libgusb-dev (>= 0.3.5),
+ libjcat-dev,
+ libjson-glib-dev (>= 1.1.1),
+ libxmlb-dev (>= 0.1.13),
+ valgrind [!ia64 !riscv64 !x32 !mips !sparc64 !sh4 !ppc64 !powerpcspe !hppa !alpha !mips64el !armhf !armel !mipsel !m68k],
${misc:Depends}
Section: libdevel
Description: development files for libfwupdplugin
diff -Nru fwupd-1.4.5/debian/control.in fwupd-1.5.8/debian/control.in
--- fwupd-1.4.5/debian/control.in 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/control.in 2021-03-31 20:08:32.000000000 +0000
@@ -49,7 +49,11 @@
shared-mime-info
Recommends: python3,
bolt,
+ dbus,
+ secureboot-db,
+ udisks2,
fwupd-signed
+Suggests: gir1.2-fwupd-2.0
Provides: fwupdate
Conflicts: fwupdate-amd64-signed,
fwupdate-i386-signed,
@@ -57,6 +61,7 @@
fwupdate-armhf-signed
Breaks: gir1.2-dfu-1.0 (<< 0.9.7-1),
libdfu1 (<< 0.9.7-1),
+ fwupdate (<< 12-7),
libdfu-dev (<< 0.9.7-1)
Replaces: gir1.2-dfu-1.0 (<< 0.9.7-1),
libdfu1 (<< 0.9.7-1),
@@ -115,6 +120,10 @@
Multi-Arch: same
Depends: libfwupd2 (= ${binary:Version}),
gir1.2-fwupd-2.0 (= ${binary:Version}),
+ libcurl4-gnutls-dev,
+ libglib2.0-dev (>= 2.45.8),
+ libjcat-dev,
+ libjson-glib-dev (>= 1.1.1),
${misc:Depends}
Breaks: fwupd-dev (<< 0.5.4-2~)
Replaces: fwupd-dev (<< 0.5.4-2~)
@@ -145,6 +154,17 @@
Multi-Arch: same
Depends: libfwupdplugin1 (= ${binary:Version}),
gir1.2-fwupdplugin-1.0 (= ${binary:Version}),
+ libarchive-dev,
+ libcurl4-gnutls-dev,
+ libfwupd-dev (= ${binary:Version}),
+ libgcab-dev,
+ libglib2.0-dev (>= 2.45.8),
+ libgudev-1.0-dev,
+ libgusb-dev (>= 0.3.5),
+ libjcat-dev,
+ libjson-glib-dev (>= 1.1.1),
+ libxmlb-dev (>= 0.1.13),
+ valgrind [!ia64 !riscv64 !x32 !mips !sparc64 !sh4 !ppc64 !powerpcspe !hppa !alpha !mips64el !armhf !armel !mipsel !m68k],
${misc:Depends}
Section: libdevel
Description: development files for libfwupdplugin
diff -Nru fwupd-1.4.5/debian/copyright fwupd-1.5.8/debian/copyright
--- fwupd-1.4.5/debian/copyright 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/copyright 2021-03-31 20:08:32.000000000 +0000
@@ -3,32 +3,47 @@
Source: https://github.com/fwupd/fwupd
Files: *
-Copyright: 9elements Agency GmbH
+Copyright:
+ 9elements Agency GmbH
+ Aleix Pol
Aleksander Morgado
Andrew Duggan
+ Benson Leung
Christian J. Kellner
Cypress Semiconductor Corporation.
Dell Inc.
Dell, Inc.
+ Evan Lojewski
Fresco Logic
Google, Inc.
+ H.J. Lu
Intel Corporation.
Intel, Inc.
+ Javier Martinez Canillas
Jeremy Soller
+ Jimmy Yu
Kalev Lember
+ Lennart Poettering
Mario Limonciello
- Max Ehrlich max.ehr@gmail.com
+ Matthias Klumpp
+ Max Ehrlich maxehr@gmail.com
Peichen Huang
Peter Jones
+ Philip Withnall
+ Philip Withnall
+ Realtek Corporation
Realtek Semiconductor Corporation
Red Hat, Inc.
+ Ricardo Cañuelo
Richard Hughes
+ Ricky Wu
Ryan Chang
Synaptics
Synaptics Inc
Synaptics Inc.
Synaptics Incorporated
VIA Corporation
+ boger wang
License: LGPL-2.1+
Files: *.metainfo.xml
@@ -37,7 +52,7 @@
Files: debian/*
Copyright: 2015 Daniel Jared Dominguez
- 2015-2018 Mario Limonciello
+ 2015 Mario Limonciello
License: LGPL-2.1+
License: LGPL-2.1+
diff -Nru fwupd-1.4.5/debian/copyright.in fwupd-1.5.8/debian/copyright.in
--- fwupd-1.4.5/debian/copyright.in 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/copyright.in 2021-03-31 20:08:32.000000000 +0000
@@ -9,7 +9,7 @@
Files: debian/*
Copyright: 2015 Daniel Jared Dominguez
- 2015-2018 Mario Limonciello
+ 2015 Mario Limonciello
License: LGPL-2.1+
License: LGPL-2.1+
diff -Nru fwupd-1.4.5/debian/fwupd.install fwupd-1.5.8/debian/fwupd.install
--- fwupd-1.4.5/debian/fwupd.install 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd.install 2021-03-31 20:08:32.000000000 +0000
@@ -8,8 +8,7 @@
usr/share/polkit-1/*
usr/share/locale
usr/share/metainfo/*
-usr/libexec/fwupd/fwupd
-usr/libexec/fwupd/fwupdoffline
+usr/libexec/fwupd/*
usr/share/man/man1/*
lib/systemd/system/*
lib/systemd/system-preset/*
diff -Nru fwupd-1.4.5/debian/fwupd.maintscript fwupd-1.5.8/debian/fwupd.maintscript
--- fwupd-1.4.5/debian/fwupd.maintscript 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd.maintscript 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,6 @@
+
+rm_conffile /etc/fwupd.conf 1.0.0~
+rm_conffile /etc/fwupd/remotes.d/fwupd.conf 1.2.7~
+rm_conffile /etc/dbus-1/system.d/org.freedesktop.fwupd.conf 1.3.2~
+rm_conffile /etc/modules-load.d/fwupd-msr.conf 1.5.3~
+rm_conffile /etc/modules-load.d/fwupd-platform-integrity.conf 1.5.3~
diff -Nru fwupd-1.4.5/debian/fwupd.postinst fwupd-1.5.8/debian/fwupd.postinst
--- fwupd-1.4.5/debian/fwupd.postinst 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd.postinst 2021-03-31 20:08:32.000000000 +0000
@@ -8,13 +8,29 @@
/etc/fwupd.conf 1.0.0~ -- "$@"
dpkg-maintscript-helper rm_conffile \
/etc/fwupd/remotes.d/fwupd.conf 1.2.7~ -- "$@"
- dpkg-maintscript-helper rm_conffile \
- /etc/dbus-1/system.d/org.freedesktop.fwupd.conf 1.3.2~ -- "$@"
+ dpkg-maintscript-helper rm_conffile \
+ /etc/dbus-1/system.d/org.freedesktop.fwupd.conf 1.3.2~ -- "$@"
+ dpkg-maintscript-helper rm_conffile \
+ /etc/fwupd/ata.conf 1.5.5~ -- "$@"
+fi
+
+#Perform transition from /etc/fwupd/uefi.conf to /etc/fwupd/uefi_capsule.conf
+if dpkg-maintscript-helper supports mv_conffile 2>/dev/null; then
+ ORIGINAL=/etc/fwupd/uefi.conf
+ NEW=/etc/fwupd/uefi_capsule.conf
+ #If already upgraded this file won't exist
+ #If in the middle of an upgrade:
+ # -> If unmodified then preinst would have renamed to /etc/fwupd/uefi.conf.dpkg-remove
+ # -> If modified, we need to do an in-place upgrade with sed
+ if [ -f $ORIGINAL ]; then
+ sed "s,\[uefi\],\[uefi_capsule\]," -i $ORIGINAL
+ fi
+ dpkg-maintscript-helper mv_conffile $ORIGINAL $NEW 1.5.5~ -- "$@"
fi
# Clean up from fwupdate->fwupd transition
# This can be removed after bullseye and focal are released
-EFIDIR=$(dpkg-vendor --query vendor | awk '{ print tolower($$0) }')
+EFIDIR=$(awk '/^ID=/ {gsub(/"/,""); split($$0,a,"="); print tolower(a[2])}' /etc/os-release)
if [ "${DPKG_MAINTSCRIPT_ARCH}" = "amd64" ]; then
EFI_NAME=x64
elif [ "${DPKG_MAINTSCRIPT_ARCH}" = "i386" ]; then
diff -Nru fwupd-1.4.5/debian/fwupd.postrm fwupd-1.5.8/debian/fwupd.postrm
--- fwupd-1.4.5/debian/fwupd.postrm 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd.postrm 2021-03-31 20:08:32.000000000 +0000
@@ -15,4 +15,13 @@
/etc/fwupd/remotes.d/fwupd.conf 1.2.7~ -- "$@"
dpkg-maintscript-helper rm_conffile \
/etc/dbus-1/system.d/org.freedesktop.fwupd.conf 1.3.2~ -- "$@"
+ dpkg-maintscript-helper rm_conffile \
+ /etc/fwupd/ata.conf 1.5.5~ -- "$@"
+fi
+
+#Perform transition from /etc/fwupd/uefi.conf to /etc/fwupd/uefi_capsule.conf
+if dpkg-maintscript-helper supports mv_conffile 2>/dev/null; then
+ ORIGINAL=/etc/fwupd/uefi.conf
+ NEW=/etc/fwupd/uefi_capsule.conf
+ dpkg-maintscript-helper mv_conffile $ORIGINAL $NEW 1.5.5~ -- "$@"
fi
diff -Nru fwupd-1.4.5/debian/fwupd.preinst fwupd-1.5.8/debian/fwupd.preinst
--- fwupd-1.4.5/debian/fwupd.preinst 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd.preinst 2021-03-31 20:08:32.000000000 +0000
@@ -6,10 +6,19 @@
if dpkg-maintscript-helper supports rm_conffile 2>/dev/null; then
dpkg-maintscript-helper rm_conffile \
/etc/fwupd.conf 1.0.0~ -- "$@"
- dpkg-maintscript-helper rm_conffile \
- /etc/fwupd/remotes.d/fwupd.conf 1.2.7~ -- "$@"
- dpkg-maintscript-helper rm_conffile \
- /etc/dbus-1/system.d/org.freedesktop.fwupd.conf 1.3.2~ -- "$@"
+ dpkg-maintscript-helper rm_conffile \
+ /etc/fwupd/remotes.d/fwupd.conf 1.2.7~ -- "$@"
+ dpkg-maintscript-helper rm_conffile \
+ /etc/dbus-1/system.d/org.freedesktop.fwupd.conf 1.3.2~ -- "$@"
+ dpkg-maintscript-helper rm_conffile \
+ /etc/fwupd/ata.conf 1.5.5~ -- "$@"
+fi
+
+#Perform transition from /etc/fwupd/uefi.conf to /etc/fwupd/uefi_capsule.conf
+if dpkg-maintscript-helper supports mv_conffile 2>/dev/null; then
+ ORIGINAL=/etc/fwupd/uefi.conf
+ NEW=/etc/fwupd/uefi_capsule.conf
+ dpkg-maintscript-helper mv_conffile $ORIGINAL $NEW 1.5.5~ -- "$@"
fi
# 1.3.2 had fwupd-refresh.service and fwupd.service both claiming
diff -Nru fwupd-1.4.5/debian/fwupd-tests.install fwupd-1.5.8/debian/fwupd-tests.install
--- fwupd-1.4.5/debian/fwupd-tests.install 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd-tests.install 2021-03-31 20:08:32.000000000 +0000
@@ -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
diff -Nru fwupd-1.4.5/debian/fwupd-tests.postinst fwupd-1.5.8/debian/fwupd-tests.postinst
--- fwupd-1.4.5/debian/fwupd-tests.postinst 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd-tests.postinst 2021-03-31 20:08:32.000000000 +0000
@@ -7,7 +7,7 @@
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=.*,DisabledPlugins=," -i /etc/fwupd/daemon.conf
else
echo "To enable test suite, modify /etc/fwupd/daemon.conf"
fi
diff -Nru fwupd-1.4.5/debian/fwupd-tests.postrm fwupd-1.5.8/debian/fwupd-tests.postrm
--- fwupd-1.4.5/debian/fwupd-tests.postrm 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/fwupd-tests.postrm 2021-03-31 20:08:32.000000000 +0000
@@ -6,7 +6,7 @@
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
diff -Nru fwupd-1.4.5/debian/.gitignore fwupd-1.5.8/debian/.gitignore
--- fwupd-1.4.5/debian/.gitignore 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/debian/.gitignore 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,39 @@
+.debhelper/
+debhelper-build-stamp
+fwupd-amd64-signed-template.debhelper.log
+fwupd-amd64-signed-template/
+fwupd-doc.debhelper.log
+fwupd-doc/
+fwupd-tests.debhelper.log
+fwupd-tests/
+fwupd.debhelper.log
+fwupd.postrm.debhelper
+fwupd/
+gir1.2-fwupd-2.0.debhelper.log
+gir1.2-fwupd-2.0/
+gir1.2-fwupdplugin-1.0.debhelper.log
+gir1.2-fwupdplugin-1.0/
+libfwupd-dev.debhelper.log
+libfwupd-dev/
+libfwupd2.debhelper.log
+libfwupd2.substvars
+libfwupd2/
+libfwupdplugin-dev.debhelper.log
+libfwupdplugin-dev/
+libfwupdplugin1.debhelper.log
+libfwupdplugin1.substvars
+libfwupdplugin1/
+tmp/
+files
+fwupd-amd64-signed-template.substvars
+fwupd-doc.substvars
+fwupd-images/
+fwupd-tests.substvars
+fwupd.postinst.debhelper
+fwupd.preinst.debhelper
+fwupd.prerm.debhelper
+fwupd.substvars
+gir1.2-fwupd-2.0.substvars
+gir1.2-fwupdplugin-1.0.substvars
+libfwupd-dev.substvars
+libfwupdplugin-dev.substvars
diff -Nru fwupd-1.4.5/debian/libfwupd2.symbols fwupd-1.5.8/debian/libfwupd2.symbols
--- fwupd-1.4.5/debian/libfwupd2.symbols 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/libfwupd2.symbols 2021-03-31 20:08:32.000000000 +0000
@@ -39,6 +39,13 @@
LIBFWUPD_1.4.0@LIBFWUPD_1.4.0 1.4.0
LIBFWUPD_1.4.1@LIBFWUPD_1.4.1 1.4.1
LIBFWUPD_1.4.5@LIBFWUPD_1.4.5 1.4.5
+ LIBFWUPD_1.4.6@LIBFWUPD_1.4.6 1.4.6
+ LIBFWUPD_1.5.0@LIBFWUPD_1.5.0 1.5.0
+ LIBFWUPD_1.5.1@LIBFWUPD_1.5.1 1.5.1
+ LIBFWUPD_1.5.2@LIBFWUPD_1.5.2 1.5.2
+ LIBFWUPD_1.5.3@LIBFWUPD_1.5.3 1.5.3
+ LIBFWUPD_1.5.5@LIBFWUPD_1.5.5 1.5.5
+ LIBFWUPD_1.5.6@LIBFWUPD_1.5.6 1.5.6
fwupd_build_history_report_json@LIBFWUPD_1.0.4 1.0.4
fwupd_build_machine_id@LIBFWUPD_1.0.4 1.0.4
fwupd_build_user_agent@LIBFWUPD_1.0.3 1.0.3
@@ -47,61 +54,149 @@
fwupd_checksum_get_by_kind@LIBFWUPD_0.9.4 1.0.0
fwupd_checksum_guess_kind@LIBFWUPD_0.9.3 1.0.0
fwupd_client_activate@LIBFWUPD_1.2.6 1.2.6
+ fwupd_client_activate_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_activate_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_clear_results@LIBFWUPD_0.7.0 1.0.0
+ fwupd_client_clear_results_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_clear_results_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_connect@LIBFWUPD_0.7.1 1.0.0
+ fwupd_client_connect_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_connect_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_download_bytes@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_download_bytes_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_download_bytes_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_download_file@LIBFWUPD_1.5.2 1.5.2
fwupd_client_ensure_networking@LIBFWUPD_1.4.5 1.4.5
fwupd_client_get_approved_firmware@LIBFWUPD_1.2.6 1.2.6
+ fwupd_client_get_approved_firmware_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_approved_firmware_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_blocked_firmware@LIBFWUPD_1.4.6 1.4.6
+ fwupd_client_get_blocked_firmware_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_blocked_firmware_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_daemon_interactive@LIBFWUPD_1.3.4 1.3.4
fwupd_client_get_daemon_version@LIBFWUPD_0.9.6 1.0.0
fwupd_client_get_details@LIBFWUPD_1.0.0 1.0.0
+ fwupd_client_get_details_bytes@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_details_bytes_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_details_bytes_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_device_by_id@LIBFWUPD_0.9.3 1.0.0
+ fwupd_client_get_device_by_id_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_device_by_id_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_devices@LIBFWUPD_0.9.2 1.0.0
+ fwupd_client_get_devices_async@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_devices_by_guid@LIBFWUPD_1.4.1 1.4.1
+ fwupd_client_get_devices_by_guid_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_devices_by_guid_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_devices_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_downgrades@LIBFWUPD_0.9.8 1.0.0
+ fwupd_client_get_downgrades_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_downgrades_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_history@LIBFWUPD_1.0.4 1.0.4
+ fwupd_client_get_history_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_history_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_host_machine_id@LIBFWUPD_1.3.2 1.3.2
fwupd_client_get_host_product@LIBFWUPD_1.3.1 1.3.1
+ fwupd_client_get_host_security_attrs@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_host_security_attrs_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_host_security_attrs_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_host_security_id@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_main_context@LIBFWUPD_1.5.3 1.5.3
fwupd_client_get_percentage@LIBFWUPD_0.7.3 1.0.0
+ fwupd_client_get_plugins@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_plugins_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_plugins_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_releases@LIBFWUPD_0.9.3 1.0.0
+ fwupd_client_get_releases_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_releases_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_remote_by_id@LIBFWUPD_0.9.3 1.0.0
+ fwupd_client_get_remote_by_id_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_remote_by_id_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_remotes@LIBFWUPD_0.9.3 1.0.0
+ fwupd_client_get_remotes_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_remotes_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_report_metadata@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_report_metadata_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_report_metadata_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_results@LIBFWUPD_0.7.0 1.0.0
+ fwupd_client_get_results_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_results_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_get_status@LIBFWUPD_0.7.3 1.0.0
fwupd_client_get_tainted@LIBFWUPD_1.2.4 1.2.4
fwupd_client_get_type@LIBFWUPD_0.7.0 1.0.0
fwupd_client_get_upgrades@LIBFWUPD_0.9.8 1.0.0
+ fwupd_client_get_upgrades_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_upgrades_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_get_user_agent@LIBFWUPD_1.5.2 1.5.2
fwupd_client_install@LIBFWUPD_0.7.0 1.0.0
+ fwupd_client_install_async@LIBFWUPD_1.5.0 1.5.0
fwupd_client_install_bytes@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_install_bytes_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_install_bytes_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_install_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_install_release2@LIBFWUPD_1.5.6 1.5.6
+ fwupd_client_install_release2_async@LIBFWUPD_1.5.6 1.5.6
fwupd_client_install_release@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_install_release_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_install_release_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_modify_config@LIBFWUPD_1.2.8 1.2.8
+ fwupd_client_modify_config_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_modify_config_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_modify_device@LIBFWUPD_1.0.4 1.0.4
+ fwupd_client_modify_device_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_modify_device_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_modify_remote@LIBFWUPD_0.9.8 1.0.0
+ fwupd_client_modify_remote_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_modify_remote_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_new@LIBFWUPD_0.7.0 1.0.0
fwupd_client_refresh_remote@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_refresh_remote_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_refresh_remote_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_self_sign@LIBFWUPD_1.2.6 1.2.6
+ fwupd_client_self_sign_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_self_sign_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_set_approved_firmware@LIBFWUPD_1.2.6 1.2.6
+ fwupd_client_set_approved_firmware_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_set_approved_firmware_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_set_blocked_firmware@LIBFWUPD_1.4.6 1.4.6
+ fwupd_client_set_blocked_firmware_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_set_blocked_firmware_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_set_feature_flags@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_set_feature_flags_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_set_feature_flags_finish@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_set_main_context@LIBFWUPD_1.5.3 1.5.3
fwupd_client_set_user_agent@LIBFWUPD_1.4.5 1.4.5
fwupd_client_set_user_agent_for_package@LIBFWUPD_1.4.5 1.4.5
fwupd_client_unlock@LIBFWUPD_0.7.0 1.0.0
+ fwupd_client_unlock_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_unlock_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_update_metadata@LIBFWUPD_1.0.0 1.0.0
fwupd_client_update_metadata_bytes@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_update_metadata_bytes_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_update_metadata_bytes_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_upload_bytes@LIBFWUPD_1.4.5 1.4.5
+ fwupd_client_upload_bytes_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_upload_bytes_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_verify@LIBFWUPD_0.7.0 1.0.0
+ fwupd_client_verify_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_verify_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_client_verify_update@LIBFWUPD_0.8.0 1.0.0
+ fwupd_client_verify_update_async@LIBFWUPD_1.5.0 1.5.0
+ fwupd_client_verify_update_finish@LIBFWUPD_1.5.0 1.5.0
fwupd_device_add_checksum@LIBFWUPD_0.9.3 1.0.0
+ fwupd_device_add_child@LIBFWUPD_1.5.1 1.5.1
fwupd_device_add_flag@LIBFWUPD_0.9.3 1.0.0
fwupd_device_add_guid@LIBFWUPD_0.9.3 1.0.0
fwupd_device_add_icon@LIBFWUPD_0.9.8 1.0.0
fwupd_device_add_instance_id@LIBFWUPD_1.2.5 1.2.5
fwupd_device_add_release@LIBFWUPD_0.9.8 1.0.0
+ fwupd_device_add_vendor_id@LIBFWUPD_1.5.5 1.5.5
fwupd_device_array_ensure_parents@LIBFWUPD_1.3.7 1.3.7
fwupd_device_array_from_variant@LIBFWUPD_1.2.10 1.2.10
fwupd_device_compare@LIBFWUPD_1.1.1 1.1.1
fwupd_device_flag_from_string@LIBFWUPD_0.7.0 1.0.0
fwupd_device_flag_to_string@LIBFWUPD_0.7.0 1.0.0
fwupd_device_from_variant@LIBFWUPD_1.0.0 1.0.0
+ fwupd_device_get_branch@LIBFWUPD_1.5.0 1.5.0
fwupd_device_get_checksums@LIBFWUPD_0.9.3 1.0.0
fwupd_device_get_children@LIBFWUPD_1.3.7 1.3.7
fwupd_device_get_created@LIBFWUPD_0.9.3 1.0.0
@@ -132,6 +227,7 @@
fwupd_device_get_update_state@LIBFWUPD_0.9.8 1.0.0
fwupd_device_get_vendor@LIBFWUPD_0.9.3 1.0.0
fwupd_device_get_vendor_id@LIBFWUPD_0.9.4 1.0.0
+ fwupd_device_get_vendor_ids@LIBFWUPD_1.5.5 1.5.5
fwupd_device_get_version@LIBFWUPD_0.9.3 1.0.0
fwupd_device_get_version_bootloader@LIBFWUPD_0.9.3 1.0.0
fwupd_device_get_version_bootloader_raw@LIBFWUPD_1.4.0 1.4.0
@@ -142,10 +238,12 @@
fwupd_device_has_flag@LIBFWUPD_0.9.3 1.0.0
fwupd_device_has_guid@LIBFWUPD_0.9.3 1.0.0
fwupd_device_has_instance_id@LIBFWUPD_1.2.5 1.2.5
+ fwupd_device_has_vendor_id@LIBFWUPD_1.5.5 1.5.5
fwupd_device_id_is_valid@LIBFWUPD_1.4.1 1.4.1
fwupd_device_incorporate@LIBFWUPD_1.1.0 1.1.0
fwupd_device_new@LIBFWUPD_0.9.3 1.0.0
fwupd_device_remove_flag@LIBFWUPD_0.9.3 1.0.0
+ fwupd_device_set_branch@LIBFWUPD_1.5.0 1.5.0
fwupd_device_set_created@LIBFWUPD_0.9.3 1.0.0
fwupd_device_set_description@LIBFWUPD_0.9.3 1.0.0
fwupd_device_set_flags@LIBFWUPD_0.9.3 1.0.0
@@ -191,10 +289,27 @@
fwupd_guid_to_string@LIBFWUPD_1.2.5 1.2.5
fwupd_keyring_kind_from_string@LIBFWUPD_0.9.7 1.0.0
fwupd_keyring_kind_to_string@LIBFWUPD_0.9.7 1.0.0
+ fwupd_plugin_add_flag@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_array_from_variant@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_flag_from_string@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_flag_to_string@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_from_variant@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_get_flags@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_get_name@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_get_type@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_has_flag@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_new@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_remove_flag@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_set_flags@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_set_name@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_to_json@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_to_string@LIBFWUPD_1.5.0 1.5.0
+ fwupd_plugin_to_variant@LIBFWUPD_1.5.0 1.5.0
fwupd_release_add_category@LIBFWUPD_1.2.7 1.2.7
fwupd_release_add_checksum@LIBFWUPD_0.9.3 1.0.0
fwupd_release_add_flag@LIBFWUPD_1.2.6 1.2.6
fwupd_release_add_issue@LIBFWUPD_1.3.2 1.3.2
+ fwupd_release_add_location@LIBFWUPD_1.5.6 1.5.6
fwupd_release_add_metadata@LIBFWUPD_1.0.4 1.0.4
fwupd_release_add_metadata_item@LIBFWUPD_1.0.4 1.0.4
fwupd_release_array_from_variant@LIBFWUPD_1.2.10 1.2.10
@@ -202,6 +317,7 @@
fwupd_release_flag_to_string@LIBFWUPD_1.2.6 1.2.6
fwupd_release_from_variant@LIBFWUPD_1.0.0 1.0.0
fwupd_release_get_appstream_id@LIBFWUPD_0.9.3 1.0.0
+ fwupd_release_get_branch@LIBFWUPD_1.5.0 1.5.0
fwupd_release_get_categories@LIBFWUPD_1.2.7 1.2.7
fwupd_release_get_checksums@LIBFWUPD_0.9.3 1.0.0
fwupd_release_get_created@LIBFWUPD_1.4.0 1.4.0
@@ -215,6 +331,7 @@
fwupd_release_get_install_duration@LIBFWUPD_1.2.1 1.2.4
fwupd_release_get_issues@LIBFWUPD_1.3.2 1.3.2
fwupd_release_get_license@LIBFWUPD_0.9.3 1.0.0
+ fwupd_release_get_locations@LIBFWUPD_1.5.6 1.5.6
fwupd_release_get_metadata@LIBFWUPD_1.0.4 1.0.4
fwupd_release_get_metadata_item@LIBFWUPD_1.0.4 1.0.4
fwupd_release_get_name@LIBFWUPD_0.9.3 1.0.0
@@ -238,6 +355,7 @@
fwupd_release_new@LIBFWUPD_0.9.3 1.0.0
fwupd_release_remove_flag@LIBFWUPD_1.2.6 1.2.6
fwupd_release_set_appstream_id@LIBFWUPD_0.9.3 1.0.0
+ fwupd_release_set_branch@LIBFWUPD_1.5.0 1.5.0
fwupd_release_set_created@LIBFWUPD_1.4.0 1.4.0
fwupd_release_set_description@LIBFWUPD_0.9.3 1.0.0
fwupd_release_set_detach_caption@LIBFWUPD_1.3.3 1.3.3
@@ -274,6 +392,7 @@
fwupd_remote_get_agreement@LIBFWUPD_1.0.7 1.0.7
fwupd_remote_get_approval_required@LIBFWUPD_1.2.6 1.2.6
fwupd_remote_get_automatic_reports@LIBFWUPD_1.3.3 1.3.3
+ fwupd_remote_get_automatic_security_reports@LIBFWUPD_1.5.0 1.5.0
fwupd_remote_get_checksum@LIBFWUPD_1.0.0 1.0.0
fwupd_remote_get_enabled@LIBFWUPD_0.9.3 1.0.0
fwupd_remote_get_filename_cache@LIBFWUPD_0.9.6 1.0.0
@@ -291,6 +410,7 @@
fwupd_remote_get_priority@LIBFWUPD_0.9.5 1.0.0
fwupd_remote_get_remotes_dir@LIBFWUPD_1.3.1 1.3.1
fwupd_remote_get_report_uri@LIBFWUPD_1.0.4 1.0.4
+ fwupd_remote_get_security_report_uri@LIBFWUPD_1.5.0 1.5.0
fwupd_remote_get_title@LIBFWUPD_0.9.8 1.0.0
fwupd_remote_get_type@LIBFWUPD_0.9.3 1.0.0
fwupd_remote_get_username@LIBFWUPD_0.9.5 1.0.0
@@ -301,10 +421,42 @@
fwupd_remote_load_signature_bytes@LIBFWUPD_1.4.5 1.4.5
fwupd_remote_new@LIBFWUPD_0.9.3 1.0.0
fwupd_remote_set_agreement@LIBFWUPD_1.0.7 1.0.7
+ fwupd_remote_set_keyring_kind@LIBFWUPD_1.5.3 1.5.3
fwupd_remote_set_mtime@LIBFWUPD_0.9.5 1.0.0
fwupd_remote_set_priority@LIBFWUPD_0.9.5 1.0.0
fwupd_remote_set_remotes_dir@LIBFWUPD_1.3.1 1.3.1
fwupd_remote_to_variant@LIBFWUPD_1.0.0 1.0.0
+ fwupd_security_attr_add_flag@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_add_metadata@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_add_obsolete@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_array_from_variant@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_flag_to_string@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_flag_to_suffix@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_from_variant@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_appstream_id@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_flags@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_level@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_metadata@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_name@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_obsoletes@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_plugin@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_result@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_type@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_get_url@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_has_flag@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_has_obsolete@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_new@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_result_to_string@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_appstream_id@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_flags@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_level@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_name@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_plugin@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_result@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_set_url@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_to_json@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_to_string@LIBFWUPD_1.5.0 1.5.0
+ fwupd_security_attr_to_variant@LIBFWUPD_1.5.0 1.5.0
fwupd_status_from_string@LIBFWUPD_0.1.1 1.0.0
fwupd_status_to_string@LIBFWUPD_0.1.1 1.0.0
fwupd_trust_flag_from_string@LIBFWUPD_0.7.0 1.0.0
diff -Nru fwupd-1.4.5/debian/libfwupdplugin1.symbols fwupd-1.5.8/debian/libfwupdplugin1.symbols
--- fwupd-1.4.5/debian/libfwupdplugin1.symbols 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/libfwupdplugin1.symbols 2021-03-31 20:08:32.000000000 +0000
@@ -41,42 +41,88 @@
LIBFWUPDPLUGIN_1.4.0@LIBFWUPDPLUGIN_1.4.0 1.4.0
LIBFWUPDPLUGIN_1.4.1@LIBFWUPDPLUGIN_1.4.1 1.4.1
LIBFWUPDPLUGIN_1.4.5@LIBFWUPDPLUGIN_1.4.5 1.4.5
+ LIBFWUPDPLUGIN_1.4.6@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ LIBFWUPDPLUGIN_1.4.7@LIBFWUPDPLUGIN_1.4.7 1.4.7
+ LIBFWUPDPLUGIN_1.5.0@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ LIBFWUPDPLUGIN_1.5.1@LIBFWUPDPLUGIN_1.5.1 1.5.1
+ LIBFWUPDPLUGIN_1.5.2@LIBFWUPDPLUGIN_1.5.2 1.5.2
+ LIBFWUPDPLUGIN_1.5.3@LIBFWUPDPLUGIN_1.5.3 1.5.3
+ LIBFWUPDPLUGIN_1.5.4@LIBFWUPDPLUGIN_1.5.4 1.5.4
+ LIBFWUPDPLUGIN_1.5.5@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ LIBFWUPDPLUGIN_1.5.6@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ LIBFWUPDPLUGIN_1.5.7@LIBFWUPDPLUGIN_1.5.7 1.5.7
fu_archive_get_type@LIBFWUPDPLUGIN_1.2.2 1.2.2
fu_archive_iterate@LIBFWUPDPLUGIN_1.3.4 1.3.4
fu_archive_lookup_by_fn@LIBFWUPDPLUGIN_1.2.2 1.2.2
fu_archive_new@LIBFWUPDPLUGIN_1.2.2 1.2.2
+ fu_bluez_device_get_type@LIBFWUPDPLUGIN_1.5.7 1.5.7
+ fu_bluez_device_read@LIBFWUPDPLUGIN_1.5.7 1.5.7
+ fu_bluez_device_read_string@LIBFWUPDPLUGIN_1.5.7 1.5.7
+ fu_bluez_device_write@LIBFWUPDPLUGIN_1.5.7 1.5.7
fu_byte_array_append_uint16@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_byte_array_append_uint32@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_byte_array_append_uint8@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_byte_array_set_size@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_cabinet_get_silo@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_cabinet_get_type@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_cabinet_new@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_cabinet_parse@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_cabinet_set_jcat_context@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_cabinet_set_size_max@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_chunk_array_mutable_new@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_chunk_array_new@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_chunk_array_new_from_bytes@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_chunk_array_to_string@LIBFWUPDPLUGIN_1.0.1 1.0.1
+ fu_chunk_bytes_new@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_address@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_bytes@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_data@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_data_out@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_data_sz@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_idx@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_page@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_get_type@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_chunk_new@LIBFWUPDPLUGIN_1.1.2 1.1.2
+ fu_chunk_set_address@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_set_bytes@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_set_idx@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_set_page@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_chunk_to_string@LIBFWUPDPLUGIN_1.1.2 1.4.6
fu_common_bytes_align@LIBFWUPDPLUGIN_1.2.4 1.2.4
fu_common_bytes_compare@LIBFWUPDPLUGIN_1.2.6 1.2.6
fu_common_bytes_compare_raw@LIBFWUPDPLUGIN_1.3.2 1.3.2
fu_common_bytes_is_empty@LIBFWUPDPLUGIN_1.2.6 1.2.6
+ fu_common_bytes_new_offset@LIBFWUPDPLUGIN_1.5.4 1.5.4
fu_common_bytes_pad@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_common_cab_build_silo@LIBFWUPDPLUGIN_1.2.0 1.2.0
+ fu_common_cpuid@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_common_crc16@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_common_crc32@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_common_crc32_full@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_common_crc8@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_common_dump_bytes@LIBFWUPDPLUGIN_1.2.2 1.2.2
fu_common_dump_full@LIBFWUPDPLUGIN_1.2.4 1.2.4
fu_common_dump_raw@LIBFWUPDPLUGIN_1.2.2 1.2.2
fu_common_error_array_get_best@LIBFWUPDPLUGIN_1.0.8 1.0.8
fu_common_extract_archive@LIBFWUPDPLUGIN_0.9.7 0.9.7
+ fu_common_filename_glob@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_common_find_program_in_path@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_common_firmware_builder@LIBFWUPDPLUGIN_0.9.7 0.9.7
fu_common_fnmatch@LIBFWUPDPLUGIN_1.3.5 1.3.5
fu_common_get_contents_bytes@LIBFWUPDPLUGIN_0.9.7 0.9.7
fu_common_get_contents_fd@LIBFWUPDPLUGIN_0.9.5 0.9.5
+ fu_common_get_cpu_vendor@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_common_get_esp_default@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_common_get_esp_for_path@LIBFWUPDPLUGIN_1.4.6 1.4.6
fu_common_get_files_recursive@LIBFWUPDPLUGIN_1.0.6 1.0.6
+ fu_common_get_memory_size@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_common_get_path@LIBFWUPDPLUGIN_1.0.8 1.0.8
+ fu_common_get_volume_by_device@LIBFWUPDPLUGIN_1.5.1 1.5.1
+ fu_common_get_volume_by_devnum@LIBFWUPDPLUGIN_1.5.1 1.5.1
+ fu_common_get_volumes_by_kind@LIBFWUPDPLUGIN_1.4.6 1.4.6
fu_common_guid_is_plausible@LIBFWUPDPLUGIN_1.2.5 1.2.5
+ fu_common_is_cpu_intel@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_common_is_live_media@LIBFWUPDPLUGIN_1.4.6 1.4.6
fu_common_kernel_locked_down@LIBFWUPDPLUGIN_1.3.8 1.3.8
fu_common_mkdir_parent@LIBFWUPDPLUGIN_0.9.7 0.9.7
fu_common_read_uint16@LIBFWUPDPLUGIN_1.0.3 1.0.3
@@ -93,10 +139,13 @@
fu_common_string_append_kv@LIBFWUPDPLUGIN_1.2.4 1.2.4
fu_common_string_append_kx@LIBFWUPDPLUGIN_1.2.4 1.2.4
fu_common_string_replace@LIBFWUPDPLUGIN_1.2.0 1.2.0
+ fu_common_strjoin_array@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_common_strnsplit@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_common_strsafe@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_common_strstrip@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_common_strtoull@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_common_strwidth@LIBFWUPDPLUGIN_1.3.2 1.3.2
+ fu_common_uri_get_scheme@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_common_vercmp@LIBFWUPDPLUGIN_0.3.5 0.3.5
fu_common_vercmp_full@LIBFWUPDPLUGIN_1.3.9 1.3.9
fu_common_version_ensure_semver@LIBFWUPDPLUGIN_1.2.9 1.2.9
@@ -116,12 +165,16 @@
fu_device_add_guid@LIBFWUPDPLUGIN_0.7.2 0.7.2
fu_device_add_instance_id@LIBFWUPDPLUGIN_1.2.5 1.2.5
fu_device_add_instance_id_full@LIBFWUPDPLUGIN_1.2.9 1.2.9
+ fu_device_add_internal_flag@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_device_add_parent_guid@LIBFWUPDPLUGIN_1.0.8 1.0.8
+ fu_device_add_possible_plugin@LIBFWUPDPLUGIN_1.5.1 1.5.1
fu_device_attach@LIBFWUPDPLUGIN_1.0.8 1.0.8
+ fu_device_bind_driver@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_device_cleanup@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_device_close@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_device_convert_instance_ids@LIBFWUPDPLUGIN_1.2.5 1.2.5
fu_device_detach@LIBFWUPDPLUGIN_1.0.8 1.0.8
+ fu_device_dump_firmware@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_device_ensure_id@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_device_get_alternate@LIBFWUPDPLUGIN_0.7.2 0.7.2
fu_device_get_alternate_id@LIBFWUPDPLUGIN_1.1.0 1.1.0
@@ -154,10 +207,13 @@
fu_device_get_type@LIBFWUPDPLUGIN_0.1.0 0.1.0
fu_device_has_custom_flag@LIBFWUPDPLUGIN_1.1.0 1.1.0
fu_device_has_guid@LIBFWUPDPLUGIN_1.2.2 1.2.2
+ fu_device_has_internal_flag@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_device_has_parent_guid@LIBFWUPDPLUGIN_1.0.8 1.0.8
fu_device_incorporate@LIBFWUPDPLUGIN_1.1.0 1.1.0
fu_device_incorporate_flag@LIBFWUPDPLUGIN_1.3.5 1.3.5
fu_device_incorporate_from_component@LIBFWUPDPLUGIN_1.2.4 1.2.4
+ fu_device_internal_flag_from_string@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_device_internal_flag_to_string@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_device_locker_close@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_device_locker_get_type@LIBFWUPDPLUGIN_1.0.0 1.0.0
fu_device_locker_new@LIBFWUPDPLUGIN_1.0.0 1.0.0
@@ -171,10 +227,14 @@
fu_device_probe_invalidate@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_device_read_firmware@LIBFWUPDPLUGIN_1.0.8 1.0.8
fu_device_reload@LIBFWUPDPLUGIN_1.3.3 1.3.3
+ fu_device_remove_internal_flag@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_device_remove_metadata@LIBFWUPDPLUGIN_1.3.3 1.3.3
+ fu_device_report_metadata_post@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_device_report_metadata_pre@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_device_rescan@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_device_retry@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_device_retry_add_recovery@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_device_retry_full@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_device_retry_set_delay@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_device_set_alternate@LIBFWUPDPLUGIN_0.7.2 0.7.2
fu_device_set_alternate_id@LIBFWUPDPLUGIN_1.1.0 1.1.0
@@ -207,7 +267,9 @@
fu_device_set_version_format@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_device_set_version_lowest@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_device_setup@LIBFWUPDPLUGIN_1.1.2 1.1.2
+ fu_device_sleep_with_progress@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_device_to_string@LIBFWUPDPLUGIN_0.9.8 0.9.8
+ fu_device_unbind_driver@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_device_write_firmware@LIBFWUPDPLUGIN_1.0.8 1.0.8
fu_dfu_firmware_get_pid@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_dfu_firmware_get_release@LIBFWUPDPLUGIN_1.3.3 1.3.3
@@ -219,14 +281,33 @@
fu_dfu_firmware_set_release@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_dfu_firmware_set_version@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_dfu_firmware_set_vid@LIBFWUPDPLUGIN_1.3.3 1.3.3
+ fu_dfuse_firmware_get_type@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_dfuse_firmware_new@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_efi_signature_get_kind@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_efi_signature_get_owner@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_efi_signature_get_type@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_efi_signature_kind_to_string@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_efi_signature_list_get_type@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_efi_signature_list_new@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_efivar_delete@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_efivar_delete_with_glob@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_efivar_exists@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_efivar_get_data@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_efivar_get_data_bytes@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_efivar_get_monitor@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_efivar_get_names@LIBFWUPDPLUGIN_1.4.7 1.4.7
fu_efivar_secure_boot_enabled@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_efivar_secure_boot_enabled_full@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_efivar_set_data@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_efivar_set_data_bytes@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_efivar_space_used@LIBFWUPDPLUGIN_1.5.1 1.5.1
fu_efivar_supported@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_firmware_add_flag@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_add_image@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_build@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_flag_from_string@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_flag_to_string@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_get_image_by_checksum@LIBFWUPDPLUGIN_1.5.5 1.5.5
fu_firmware_get_image_by_id@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_get_image_by_id_bytes@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_get_image_by_idx@LIBFWUPDPLUGIN_1.3.1 1.3.1
@@ -236,43 +317,70 @@
fu_firmware_get_images@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_get_type@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_get_version@LIBFWUPDPLUGIN_1.3.3 1.3.3
+ fu_firmware_get_version_raw@LIBFWUPDPLUGIN_1.5.7 1.5.7
+ fu_firmware_has_flag@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_image_add_chunk@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_firmware_image_build@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_image_get_addr@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_image_get_bytes@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_image_get_checksum@LIBFWUPDPLUGIN_1.5.5 1.5.5
+ fu_firmware_image_get_chunks@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_firmware_image_get_filename@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_image_get_id@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_image_get_idx@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_image_get_offset@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_image_get_type@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_image_get_version@LIBFWUPDPLUGIN_1.3.4 1.3.4
fu_firmware_image_new@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_image_parse@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_image_set_addr@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_image_set_bytes@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_image_set_filename@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_image_set_id@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_image_set_idx@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_image_set_offset@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_image_set_version@LIBFWUPDPLUGIN_1.3.4 1.3.4
fu_firmware_image_to_string@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_image_write@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_firmware_image_write_chunk@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_new@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_new_from_bytes@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_new_from_gtypes@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_firmware_parse@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_parse_file@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_firmware_parse_full@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_remove_image@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_remove_image_by_id@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_firmware_remove_image_by_idx@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_firmware_set_version@LIBFWUPDPLUGIN_1.3.3 1.3.3
+ fu_firmware_set_version_raw@LIBFWUPDPLUGIN_1.5.7 1.5.7
fu_firmware_strparse_uint16@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_strparse_uint16_safe@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_firmware_strparse_uint24@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_strparse_uint24_safe@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_firmware_strparse_uint32@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_strparse_uint32_safe@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_firmware_strparse_uint4@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_strparse_uint4_safe@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_firmware_strparse_uint8@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_firmware_strparse_uint8_safe@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_firmware_to_string@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_tokenize@LIBFWUPDPLUGIN_1.3.2 1.3.2
fu_firmware_write@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_firmware_write_file@LIBFWUPDPLUGIN_1.3.3 1.3.3
+ fu_fmap_firmware_get_type@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_fmap_firmware_new@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_hid_device_add_flag@LIBFWUPDPLUGIN_1.5.2 1.5.2
fu_hid_device_get_interface@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_hid_device_get_report@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_hid_device_get_type@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_hid_device_new@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_hid_device_set_interface@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_hid_device_set_report@LIBFWUPDPLUGIN_1.4.0 1.4.0
+ fu_hwids_add_smbios_override@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_hwids_get_guid@LIBFWUPDPLUGIN_0.9.3 0.9.3
fu_hwids_get_guids@LIBFWUPDPLUGIN_0.9.3 0.9.3
+ fu_hwids_get_keys@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_hwids_get_replace_keys@LIBFWUPDPLUGIN_0.9.3 0.9.3
fu_hwids_get_replace_values@LIBFWUPDPLUGIN_0.9.3 0.9.3
fu_hwids_get_type@LIBFWUPDPLUGIN_0.9.3 0.9.3
@@ -295,6 +403,7 @@
fu_io_channel_write_bytes@LIBFWUPDPLUGIN_1.2.2 1.2.2
fu_io_channel_write_raw@LIBFWUPDPLUGIN_1.2.2 1.2.2
fu_memcpy_safe@LIBFWUPDPLUGIN_1.3.1 1.3.1
+ fu_memdup_safe@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_plugin_add_compile_version@LIBFWUPDPLUGIN_1.0.7 1.0.7
fu_plugin_add_firmware_gtype@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_plugin_add_report_metadata@LIBFWUPDPLUGIN_1.0.4 1.0.4
@@ -313,6 +422,7 @@
fu_plugin_get_config_value@LIBFWUPDPLUGIN_1.0.6 1.0.6
fu_plugin_get_config_value_boolean@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_plugin_get_data@LIBFWUPDPLUGIN_0.8.0 0.8.0
+ fu_plugin_get_devices@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_plugin_get_dmi_value@LIBFWUPDPLUGIN_0.9.7 0.9.7
fu_plugin_get_enabled@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_get_hwid_replace_value@LIBFWUPDPLUGIN_1.3.3 1.3.3
@@ -339,12 +449,16 @@
fu_plugin_order_compare@LIBFWUPDPLUGIN_1.0.8 1.0.8
fu_plugin_request_recoldplug@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_runner_activate@LIBFWUPDPLUGIN_1.2.6 1.2.6
+ fu_plugin_runner_add_security_attrs@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_plugin_runner_backend_device_added@LIBFWUPDPLUGIN_1.5.6 1.5.6
+ fu_plugin_runner_backend_device_changed@LIBFWUPDPLUGIN_1.5.6 1.5.6
fu_plugin_runner_clear_results@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_runner_coldplug@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_runner_coldplug_cleanup@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_runner_coldplug_prepare@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_runner_composite_cleanup@LIBFWUPDPLUGIN_1.0.9 1.0.9
fu_plugin_runner_composite_prepare@LIBFWUPDPLUGIN_1.0.9 1.0.9
+ fu_plugin_runner_device_added@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_plugin_runner_device_created@LIBFWUPDPLUGIN_1.4.0 1.4.0
fu_plugin_runner_device_register@LIBFWUPDPLUGIN_0.9.7 0.9.7
fu_plugin_runner_device_removed@LIBFWUPDPLUGIN_1.1.2 1.1.2
@@ -362,6 +476,7 @@
fu_plugin_runner_update_reload@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_plugin_runner_usb_device_added@LIBFWUPDPLUGIN_1.0.2 1.0.2
fu_plugin_runner_verify@LIBFWUPDPLUGIN_0.8.0 0.8.0
+ fu_plugin_security_changed@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_plugin_set_build_hash@LIBFWUPDPLUGIN_1.2.4 1.2.4
fu_plugin_set_coldplug_delay@LIBFWUPDPLUGIN_0.8.0 0.8.0
fu_plugin_set_compile_versions@LIBFWUPDPLUGIN_1.0.7 1.0.7
@@ -381,7 +496,16 @@
fu_quirks_lookup_by_id@LIBFWUPDPLUGIN_1.0.1 1.0.1
fu_quirks_lookup_by_id_iter@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_quirks_new@LIBFWUPDPLUGIN_1.0.1 1.0.1
+ fu_security_attrs_append@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_calculate_hsi@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_depsolve@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_get_all@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_get_type@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_new@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_remove_all@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_security_attrs_to_variant@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_smbios_get_data@LIBFWUPDPLUGIN_1.0.0 1.0.0
+ fu_smbios_get_integer@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_smbios_get_string@LIBFWUPDPLUGIN_1.0.0 1.0.0
fu_smbios_get_type@LIBFWUPDPLUGIN_1.0.0 1.0.0
fu_smbios_new@LIBFWUPDPLUGIN_1.0.0 1.0.0
@@ -397,12 +521,16 @@
fu_udev_device_get_dev@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_udev_device_get_device_file@LIBFWUPDPLUGIN_1.3.1 1.3.1
fu_udev_device_get_devtype@LIBFWUPDPLUGIN_1.4.5 1.4.5
+ fu_udev_device_get_driver@LIBFWUPDPLUGIN_1.5.3 1.5.3
fu_udev_device_get_fd@LIBFWUPDPLUGIN_1.3.3 1.3.3
fu_udev_device_get_model@LIBFWUPDPLUGIN_1.1.2 1.1.2
+ fu_udev_device_get_number@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_udev_device_get_parent_name@LIBFWUPDPLUGIN_1.4.5 1.4.5
fu_udev_device_get_revision@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_udev_device_get_slot_depth@LIBFWUPDPLUGIN_1.2.4 1.2.4
fu_udev_device_get_subsystem@LIBFWUPDPLUGIN_1.1.2 1.1.2
+ fu_udev_device_get_subsystem_model@LIBFWUPDPLUGIN_1.5.0 1.5.0
+ fu_udev_device_get_subsystem_vendor@LIBFWUPDPLUGIN_1.5.0 1.5.0
fu_udev_device_get_sysfs_attr@LIBFWUPDPLUGIN_1.4.5 1.4.5
fu_udev_device_get_sysfs_path@LIBFWUPDPLUGIN_1.1.2 1.1.2
fu_udev_device_get_type@LIBFWUPDPLUGIN_1.1.2 1.1.2
@@ -428,3 +556,14 @@
fu_usb_device_is_open@LIBFWUPDPLUGIN_1.0.3 1.0.3
fu_usb_device_new@LIBFWUPDPLUGIN_1.0.2 1.0.2
fu_usb_device_set_dev@LIBFWUPDPLUGIN_1.0.2 1.0.2
+ fu_volume_check_free_space@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_get_id@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_get_id_type@LIBFWUPDPLUGIN_1.5.2 1.5.2
+ fu_volume_get_mount_point@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_get_type@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_is_encrypted@LIBFWUPDPLUGIN_1.5.1 1.5.1
+ fu_volume_is_internal@LIBFWUPDPLUGIN_1.5.2 1.5.2
+ fu_volume_is_mounted@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_locker@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_mount@LIBFWUPDPLUGIN_1.4.6 1.4.6
+ fu_volume_unmount@LIBFWUPDPLUGIN_1.4.6 1.4.6
diff -Nru fwupd-1.4.5/debian/lintian/fwupd fwupd-1.5.8/debian/lintian/fwupd
--- fwupd-1.4.5/debian/lintian/fwupd 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/lintian/fwupd 2021-03-31 20:08:32.000000000 +0000
@@ -9,3 +9,7 @@
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
diff -Nru fwupd-1.4.5/debian/patches/0001-Tweak-the-SBAT-output-for-a-vendor-string.patch fwupd-1.5.8/debian/patches/0001-Tweak-the-SBAT-output-for-a-vendor-string.patch
--- fwupd-1.4.5/debian/patches/0001-Tweak-the-SBAT-output-for-a-vendor-string.patch 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/debian/patches/0001-Tweak-the-SBAT-output-for-a-vendor-string.patch 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,29 @@
+From d99074c3741ca9d30802d419d997bb90e24ea96a Mon Sep 17 00:00:00 2001
+From: Steve McIntyre <93sam@debian.org>
+Date: Fri, 26 Mar 2021 15:06:08 +0000
+Subject: [PATCH] Tweak the SBAT output for a vendor string
+
+The format is meant to be "." with a period as a
+separator.
+
+Signed-off-by: Steve McIntyre <93sam@debian.org>
+---
+ plugins/uefi-capsule/efi/generate_sbat.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/plugins/uefi-capsule/efi/generate_sbat.py b/plugins/uefi-capsule/efi/generate_sbat.py
+index 18f7c4c7..1f12ca11 100755
+--- a/plugins/uefi-capsule/efi/generate_sbat.py
++++ b/plugins/uefi-capsule/efi/generate_sbat.py
+@@ -51,7 +51,7 @@ def _generate_sbat(args):
+
+ # distro specifics, falling back to the project defaults
+ sfd.write(
+- "{0}-{1},{2},{3},{4},{5},{6}\n".format(
++ "{0}.{1},{2},{3},{4},{5},{6}\n".format(
+ args.project_name,
+ args.sbat_distro_id,
+ args.sbat_distro_generation or args.sbat_generation,
+--
+2.25.1
+
diff -Nru fwupd-1.4.5/debian/patches/series fwupd-1.5.8/debian/patches/series
--- fwupd-1.4.5/debian/patches/series 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/debian/patches/series 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1 @@
+0001-Tweak-the-SBAT-output-for-a-vendor-string.patch
diff -Nru fwupd-1.4.5/debian/rules fwupd-1.5.8/debian/rules
--- fwupd-1.4.5/debian/rules 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/rules 2021-03-31 20:08:32.000000000 +0000
@@ -6,28 +6,61 @@
export DEB_LDFLAGS_MAINT_STRIP=-Wl,-Bsymbolic-functions
#GPGME needs this for proper building on 32 bit archs
-ifeq "$(DEB_HOST_ARCH_BITS)" "32"
+ifeq ($(DEB_HOST_ARCH_BITS),32)
export DEB_CFLAGS_MAINT_APPEND = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
endif
+CONFARGS =
+
ifneq ($(CI),)
- export CI=--werror --wrap-mode=default
+ CONFARGS += --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)
ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes))
SB_STYLE := ubuntu
tar_name := fwupd_$(deb_version)_$(DEB_HOST_ARCH).tar.gz
- export FLASHROM=-Dplugin_flashrom=false
+ CONFARGS += -Dplugin_flashrom=false
+ CONFARGS += -Defi_sbat_distro_id=ubuntu
+ CONFARGS += -Defi_sbat_distro_summary=Ubuntu
+ CONFARGS += -Defi_sbat_distro_pkgname=fwupd
+ CONFARGS += -Defi_sbat_distro_version=$(deb_version)
+ CONFARGS += -Defi_sbat_distro_url="https://launchpad.net/ubuntu/+source/fwupd"
else
TMPLDIR := debian/fwupd-$(DEB_HOST_ARCH)-signed-template/usr/share/code-signing/fwupd-$(DEB_HOST_ARCH)-signed-template
- export FLASHROM=-Dplugin_flashrom=true
+ ifneq ($(DEB_HOST_ARCH_CPU),ia64)
+ CONFARGS += -Dplugin_flashrom=true
+ else
+ CONFARGS += -Dplugin_flashrom=false
+ endif
+ CONFARGS += -Defi_sbat_distro_id=debian
+ CONFARGS += -Defi_sbat_distro_summary=Debian
+ CONFARGS += -Defi_sbat_distro_pkgname=fwupd
+ CONFARGS += -Defi_sbat_distro_version=$(deb_version)
+ CONFARGS += -Defi_sbat_distro_url="https://tracker.debian.org/pkg/fwupd"
+endif
+
+ifeq (yes,$(shell pkg-config --exists libsmbios_c && echo yes))
+ CONFARGS += -Dplugin_dell=true
+else
+ CONFARGS += -Dplugin_dell=false
+endif
+
+ifeq (yes,$(shell pkg-config --exists efivar && echo yes))
+ CONFARGS += -Dplugin_uefi_capsule=true
+else
+ CONFARGS += -Dplugin_uefi_capsule=false
endif
+ifneq ($(filter $(DEB_HOST_ARCH_CPU),i386 amd64),)
+ CONFARGS += -Dplugin_msr=true
+else
+ CONFARGS += -Dplugin_msr=false
+endif
+
+CONFARGS += -Dplugin_dummy=true -Dgtkdoc=true -Dsupported_build=true
+
%:
dh $@ --with gir
@@ -39,30 +72,22 @@
endif
override_dh_auto_configure:
- if pkg-config --exists libsmbios_c; then \
- export DELL="-Dplugin_dell=true"; \
- else \
- export DELL="-Dplugin_dell=false"; \
- fi; \
- if pkg-config --exists efivar; then \
- export UEFI="-Dplugin_uefi=true -Dplugin_redfish=true -Dplugin_nvme=true"; \
- else \
- export UEFI="-Dplugin_uefi=false -Dplugin_redfish=false -Dplugin_nvme=false"; \
- fi; \
- dh_auto_configure -- $$UEFI $$DELL $$FLASHROM $$CI -Dplugin_dummy=true -Dgtkdoc=true
+ dh_auto_configure -- $(CONFARGS)
override_dh_install:
find debian/tmp/usr -type f -name "*a" -print | xargs rm -f
- sed -i 's,wheel,sudo,' ./debian/tmp/usr/share/polkit-1/rules.d/org.freedesktop.fwupd.rules
+ sed -i 's,wheel,sudo,' debian/tmp/usr/share/polkit-1/rules.d/org.freedesktop.fwupd.rules
dh_install
#install the EFI binaries if needed
- if [ -d debian/tmp/usr/libexec/fwupd/efi/ ]; then \
- dh_install -pfwupd usr/libexec/fwupd/efi ;\
- fi
+ [ ! -d debian/tmp/usr/libexec/fwupd/efi/ ] || dh_install -pfwupd usr/libexec/fwupd/efi
+ #install MSR conf if needed (depending on distro)
+ [ ! -d debian/tmp/usr/lib/modules-load.d ] || dh_install -pfwupd usr/lib/modules-load.d
+ [ ! -d debian/tmp/lib/modules-load.d ] || dh_install -pfwupd lib/modules-load.d
dh_missing -a --fail-missing
#this is placed in fwupd-tests
rm -f debian/fwupd/usr/lib/*/fwupd-plugins-3/libfu_plugin_test.so
+ rm -f debian/fwupd/usr/lib/*/fwupd-plugins-3/libfu_plugin_test_ble.so
rm -f debian/fwupd/usr/lib/*/fwupd-plugins-3/libfu_plugin_invalid.so
rm -f debian/fwupd/etc/fwupd/remotes.d/fwupd-tests.conf
@@ -73,32 +98,32 @@
cp debian/README.Debian $(TMPLDIR)/source-template/debian
find $(TMPLDIR)/source-template/debian -type f | xargs sed -i "s,SIGNARCH,$(DEB_HOST_ARCH),"
find $(TMPLDIR)/source-template/debian -type f | xargs sed -i "s,SIGNVERSION,$(deb_version),"
- for file in $$(find $(TMPLDIR)/source-template/debian -type f -name *SIGNARCH*); do file1=$$(echo $$file | sed "s,SIGNARCH,$(DEB_HOST_ARCH),"); mv -v $$file $$file1; done
+ set -e; for file in $$(find $(TMPLDIR)/source-template/debian -type f -name '*SIGNARCH*'); do \
+ file1=$$(echo $$file | sed "s,SIGNARCH,$(DEB_HOST_ARCH),"); \
+ mv -v $$file $$file1; \
+ done
install -m 0755 debian/fwupd.postinst $(TMPLDIR)/source-template/debian/fwupd-$(DEB_HOST_ARCH)-signed.postinst
install -m 0755 debian/fwupd.postrm $(TMPLDIR)/source-template/debian/fwupd-$(DEB_HOST_ARCH)-signed.postrm
- ./debian/gen_signing_changelog $(TMPLDIR)/source-template/debian fwupd $(DEB_HOST_ARCH)
- ./debian/gen_signing_json $(TMPLDIR) fwupd ${DEB_HOST_ARCH}
+ debian/gen_signing_changelog $(TMPLDIR)/source-template/debian fwupd $(DEB_HOST_ARCH)
+ debian/gen_signing_json $(TMPLDIR) fwupd ${DEB_HOST_ARCH}
endif
override_dh_strip_nondeterminism:
dh_strip_nondeterminism -Xfirmware-example.xml.gz
+ifneq (yes,$(shell command -v valgrind >/dev/null 2>&1 && echo yes))
override_dh_auto_test:
- if [ -x /usr/bin/valgrind ] ; then \
- dh_auto_test; \
- fi
+ :
+endif
override_dh_builddeb:
dh_builddeb
ifeq (ubuntu,$(SB_STYLE))
- if [ -d debian/tmp/usr/libexec/fwupd/efi/ ]; then \
- mkdir -p debian/fwupd-images/$(deb_version) ;\
- cp debian/tmp/usr/libexec/fwupd/efi/fwupd*.efi debian/fwupd-images/$(deb_version) ;\
- echo $(deb_version) > debian/fwupd-images/$(deb_version)/version ;\
- tar -C debian/fwupd-images -czvf ../$(tar_name) . ;\
- dpkg-distaddfile $(tar_name) raw-uefi - ;\
+ set -e; if [ -d debian/tmp/usr/libexec/fwupd/efi/ ]; then \
+ mkdir -p debian/fwupd-images/$(deb_version); \
+ cp debian/tmp/usr/libexec/fwupd/efi/fwupd*.efi debian/fwupd-images/$(deb_version); \
+ echo $(deb_version) > debian/fwupd-images/$(deb_version)/version; \
+ tar -C debian/fwupd-images -czvf ../$(tar_name) .; \
+ dpkg-distaddfile $(tar_name) raw-uefi -; \
fi
endif
-
-override_dh_shlibdeps:
- dh_shlibdeps $$DHSLIBS
diff -Nru fwupd-1.4.5/debian/signing-template/control fwupd-1.5.8/debian/signing-template/control
--- fwupd-1.4.5/debian/signing-template/control 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/signing-template/control 2021-03-31 20:08:32.000000000 +0000
@@ -1,7 +1,9 @@
Source: fwupd-SIGNARCH-signed
Priority: optional
Maintainer: Debian EFI
-Uploaders: Daniel Jared Dominguez , Steve McIntyre <93sam@debian.org>, Mario Limonciello
+Uploaders: Steve McIntyre <93sam@debian.org>,
+ Matthias Klumpp ,
+ Mario Limonciello
Build-Depends: debhelper (>= 9.0.0), sbsigntool [amd64 arm64 armhf i386], fwupd (= SIGNVERSION) [SIGNARCH]
Standards-Version: 4.1.3
Section: libs
diff -Nru fwupd-1.4.5/debian/tests/ci fwupd-1.5.8/debian/tests/ci
--- fwupd-1.4.5/debian/tests/ci 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/tests/ci 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
#!/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
diff -Nru fwupd-1.4.5/debian/tests/control fwupd-1.5.8/debian/tests/control
--- fwupd-1.4.5/debian/tests/control 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/debian/tests/control 2021-03-31 20:08:32.000000000 +0000
@@ -1,2 +1,6 @@
Tests: ci
Restrictions: needs-root
+
+Tests: libfwupd-dev
+Depends: build-essential, libfwupd-dev, pkg-config
+Restrictions: allow-stderr, superficial
diff -Nru fwupd-1.4.5/debian/tests/libfwupd-dev fwupd-1.5.8/debian/tests/libfwupd-dev
--- fwupd-1.4.5/debian/tests/libfwupd-dev 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/debian/tests/libfwupd-dev 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Copyright 2020 Collabora Ltd.
+# Copyright 2021 Simon McVittie
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+set -eux
+
+WORKDIR="$(mktemp -d)"
+trap 'cd /; rm -fr "$WORKDIR"' 0 INT QUIT ABRT PIPE TERM
+
+if [ -n "${DEB_HOST_GNU_TYPE:-}" ]; then
+ CROSS_COMPILE="$DEB_HOST_GNU_TYPE-"
+else
+ CROSS_COMPILE=
+fi
+
+CC="${CROSS_COMPILE}gcc"
+PKG_CONFIG="${CROSS_COMPILE}pkg-config"
+
+cd "$WORKDIR"
+
+cat > trivial.c <<'EOF'
+#undef NDEBUG
+#include
+
+#include
+
+int main (void)
+{
+ assert (fwupd_error_to_string (FWUPD_ERROR_NOTHING_TO_DO) != NULL);
+ return 0;
+}
+EOF
+
+# Deliberately word-splitting pkg-config's output:
+# shellcheck disable=SC2046
+"${CC}" -otrivial trivial.c $("${PKG_CONFIG}" --cflags --libs fwupd)
+./trivial
diff -Nru fwupd-1.4.5/docs/fwupd-docs.xml fwupd-1.5.8/docs/fwupd-docs.xml
--- fwupd-1.4.5/docs/fwupd-docs.xml 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/docs/fwupd-docs.xml 2021-03-31 20:08:32.000000000 +0000
@@ -26,8 +26,10 @@
+
+
@@ -51,6 +53,8 @@
+
+
@@ -67,405 +71,10 @@
-
- Plugin Tutorial
-
-
- Introduction
-
- 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.
-
-
- There are broadly 3 types of plugin methods:
-
-
-
-
- Mechanism: Upload binary data
- into a specific hardware device.
-
-
-
-
- Policy: Control the system when
- updates are happening, e.g. preventing the user from powering-off.
-
-
-
-
- Helpers: Providing more
- metadata about devices, for instance handling device quirks.
-
-
-
-
- In general, building things out-of-tree isn't something that we think is
- a very good idea; the API and ABI internal 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 .so
binary file
- manually.
-
-
-
- A plugin only needs to define the vfuncs that are required, and the
- plugin name is taken automatically from the suffix of the
- .so file.
-
-
- A sample plugin
-
-/*
- * Copyright (C) 2017 Richard Hughes
- */
-
-#include <fu-plugin.h>
-#include <fu-plugin-vfuncs.h>
-
-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;
-}
-
-
-
-
- We have to define when our plugin is run in reference to other plugins,
- in this case, making sure we run before the dfu
plugin.
- For most plugins it does not matter in what order they are run and
- this information is not required.
-
-
-
-
- Creating an abstract device
-
- 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 FuDevice
from the hardware,
- for example reading data from sysfs
or /dev
.
-
-
- Example adding a custom device
-
-#include <fu-plugin.h>
-
-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;
-}
-
-
-
- This shows a lot of the plugin architecture in action. Some notable points:
-
-
-
-
- The device ID (dummy-1:2:3
) has to be unique on the
- system between all plugins, so including the plugin name as a
- prefix is probably a good idea.
-
-
-
-
- The GUID value can be generated automatically using
- fu_device_add_guid(dev,"some-identifier")
but is quoted
- here explicitly.
- The GUID value has to match the provides
value in the
- .metainfo.xml
file for the firmware update to succeed.
-
-
-
-
- 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.
-
-
-
-
- The FWUPD_DEVICE_FLAG_UPDATABLE
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 FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER
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
- FWUPD_DEVICE_FLAG_REQUIRE_AC
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.
-
-
-
-
- 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
-
-
-
-
-
-
- Mechanism Plugins
-
- 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.
-
-
- When a plugin has created a device that is FWUPD_DEVICE_FLAG_UPDATABLE
- we can ask the daemon to update the device with a suitable
- .cab
file.
- When this is done the daemon checks the update for compatibility with
- the device, and then calls the vfuncs to update the device.
-
-
-
- Updating a device
-
-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, &sz);
- /* write 'buf' of size 'sz' to the hardware */
- return TRUE;
-}
-
-
-
- It's important to note that the blob_fw
is the binary
- firmware file (e.g. .dfu
) and not
- the .cab
binary data.
-
-
- If FWUPD_INSTALL_FLAG_FORCE
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.
-
-
-
-
- Policy Helpers
-
- 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.
-
-
-
- Running before a device update
-
-gboolean
-fu_plugin_update_prepare (FuPlugin *plugin, FuDevice *device, GError **error)
-{
- if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_REQUIRE_AC && !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;
-}
-
-
-
- Running after a device update
-
-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);
-}
-
-
-
-
-
- Detaching to bootloader mode
-
- 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.
-
-
- Before the device update is performed the fwupd daemon runs an optional
- update_detach()
vfunc which switches the device to
- bootloader mode.
- After the update (or if the update fails) an the daemon runs an
- optional update_attach()
vfunc which should switch the
- hardware back to runtime mode.
- Finally an optional update_reload()
vfunc is run to
- get the new firmware version from the hardware.
-
-
- The optional vfuncs are only run
- on the plugin currently registered to handle the device ID, although
- the registered plugin can change during the attach and detach phases.
-
-
-
- Running before a device update
-
-gboolean
-fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error)
-{
- if (hardware_in_bootloader)
- return TRUE;
- return _device_detach(device, error);
-}
-
-
-
- Running after a device update
-
-gboolean
-fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error)
-{
- if (!hardware_in_bootloader)
- return TRUE;
- return _device_attach(device, error);
-}
-
-
-
- Running after a device update on success
-
-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;
-}
-
-
-
-
-
- The Plugin Object Cache
-
- 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 GObject
s to enable the
- cache objects to be properly refcounted.
-
-
-
-
- Debugging a Plugin
-
- If the fwupd daemon is started with --plugin-verbose=$plugin
- then the environment variable FWUPD_$PLUGIN_VERBOSE
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 --plugin-verbose=logitech_hidpp
would set
- FWUPD_LOGITECH_HID_VERBOSE=1
.
-
-
-
-
- Using existing code to develop a plugin
-
- It is not usually possible to share 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.
-
-
- 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 vendor saves by creating a shim layer and
- importing existing source code into fwupd will be overtaken 100x by
- upstream maintenance costs longer term, which isn't fair.
-
-
- 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.
-
-
- 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.
-
-
-
-
-
+
+
API Index
diff -Nru fwupd-1.4.5/docs/hsi.xml fwupd-1.5.8/docs/hsi.xml
--- fwupd-1.4.5/docs/hsi.xml 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/docs/hsi.xml 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,893 @@
+
+
+
+ Host Security ID Specification
+
+
+ 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.
+
+
+
+
+
+
+
+
+ Introduction
+
+ Not all system vendors prioritize building a secure platform.
+ The truth is that security costs money.
+ 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.
+
+
+ The Linux Vendor Firmware Service (LVFS) could provide some
+ easy-to-understand 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.
+
+
+
+
+ Other Tools
+
+ 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.
+
+
+
+
+ Verifying Host Firmware Security
+
+ 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 (HSI:1
) is good enough.
+ For a work laptop the company IT department might restrict the choice of
+ models to anything meeting the criteria of level HSI:2
or
+ above.
+ A journalist or a security researcher would only buy level HSI:3
+ and above.
+ The reality is that HSI:4
is going to be more expensive
+ than some unbranded hardware that is rated HSI:0
.
+
+
+ To be trusted, this rating information should be distributed in a
+ centralized agnostic database such as the LVFS.
+
+
+ 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.
+
+
+ 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.
+
+
+ The HSI specification is primarily designed for laptop and desktop
+ hardware, although some tests may still make sense
+ on server or embedded hardware.
+ It is not expected that non-consumer hardware will publish an HSI number.
+
+
+
+
+ Runtime Behavior
+
+ 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 have updates on the LVFS
+ 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 core security level will not change at
+ Operating System runtime, but the suffix may.
+
+
+
+
+ HSI:0 (Insecure)
+
+ 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.
+
+
+
+
+ HSI:1 (Critical)
+
+ 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.
+
+
+
+
+ HSI:3 (Theoretical)
+
+ 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.
+
+
+
+
+ HSI:4 (System Protection)
+
+ This security level corresponds to out-of-band protection of the system
+ firmware perhaps including recovery.
+
+
+
+
+ HSI:5 (System Attestation)
+
+ 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.
+
+
+
+
+ HSI Runtime Suffix !
+
+ A runtime security issue detected.
+
+
+
+
+ UEFI
+ Secure Boot has been turned off. v1.5.0
+
+
+
+
+ The kernel is
+ tainted due to a non-free module or critical firmware issue. v1.5.0
+
+
+
+
+ The kernel is not
+ locked down. v1.5.0
+
+
+
+
+ Unencrypted
+ swap partition. v1.5.0
+
+
+
+
+ The installed fwupd is running with
+ custom or modified plugins. v1.5.0
+
+
+
+
+
+
+ Tests included in fwupd
+
+ 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.
+
+
+
+
+ UEFI SecureBoot
+
+ UEFI Secure boot is a verification mechanism for ensuring that code
+ launched by firmware is trusted.
+
+
+ Secure Boot requires that each binary loaded at boot is validated
+ against trusted certifictes.
+
+
+
+
+ For HSI-1 SecureBoot must be available for use on UEFI systems.
+ v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ UEFI Wiki Entry
+
+
+
+
+
+
+
+
+ UEFI PK
+
+ UEFI defines a platform key for the system.
+ This should not be a test key, e.g. ``DO NOT TRUST - AMI Test PK``
+
+
+
+
+ For HSI-1 a test key must not be enrolled.
+ v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ UEFI Testing Wiki Entry
+
+
+
+
+
+
+
+
+ BIOS Write Enable (BWE)
+
+ Intel hardware provides this mechanism to protect the SPI ROM chip
+ located on the motherboard from being overwritten by the operating system.
+
+
+
+
+ For HSI-1 the ``BIOSWE`` bit must be unset. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel C200 Datasheet
+
+
+
+
+
+
+
+
+ BIOS Lock Enable (BLE)
+
+ If the lock bit is set then System Management Interrupts (SMIs) are
+ raised when setting BIOS Write Enable.
+ The BLE
` bit must be enabled in the PCH otherwise
+ BIOSWE
can easily be unset.
+
+
+
+
+ For HSI-1 this should be set. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel C200 Datasheet
+
+
+
+
+
+
+
+
+ SMM Bios Write Protect (SMM_BWP)
+
+ This bit set defines when the BIOS region can be written by the host.
+ The SMM_BWP
bit must be set to make the BIOS region
+ non-writable unless all processors are in system management mode.
+
+
+
+
+ For HSI-1 this should be set v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel C200 Datasheet
+
+
+
+
+
+
+
+
+ TPM 2.0 Present
+
+ A TPM securely stores platform specific secrets that can only be divulged
+ to trusted consumers in a secure environment.
+
+
+
+
+ For HSI-1 this should be available for use by the OS or applications v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Wikipedia TPM Article
+
+
+
+
+
+
+
+
+ ME not in manufacturing mode
+
+ 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 platform’s security.
+
+
+
+
+ For HSI-1 this should be unset v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ ME Manufacturing Mode: obscured dangers
+
+
+
+
+ Intel security advisory SA-00086
+
+
+
+
+
+
+
+
+ ME Flash Descriptor Override
+
+ The Flash Descriptor Security Override Strap is not accessible to end
+ users on consumer boards and Intel stresses that this is for debugging only.
+
+
+
+
+ For HSI-1 this should be unset v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Chromium documentation for Intel ME
+
+
+
+
+
+
+
+
+ CSME Version
+
+ 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.
+
+
+
+
+ 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 v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel CSME Security Review Cumulative Update
+
+
+
+
+
+
+
+
+ Intel DCI
+
+ 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.
+
+
+
+
+ For HSI-1 this should be disabled. v1.5.0
+
+
+
+
+ For HSI-2 this should be locked. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel Direct Connect Interface
+
+
+
+
+ Chipsec 4xxlp register definitions
+
+
+
+
+ RISC-V EDK PCH register definitions
+
+
+
+
+
+
+
+
+ PCR0 TPM Event Log Reconstruction
+
+ 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.
+
+
+
+
+ For HSI-2 this should match the TPM-provided PCR0 v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Linux Kernel TPM Documentation
+
+
+
+
+
+
+
+ Pre-boot DMA protection
+
+ 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.
+
+
+
+
+ For HSI-2 this should be available v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Wikipedia IOMMU article
+
+
+
+
+
+
+
+
+ Intel BootGuard
+
+ 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.
+
+
+
+
+ For HSI-1 verified boot must be enabled with ACM protection. v1.5.0
+
+
+
+
+ For HSI-2 the error enforcement policy must be set to “immediate shutdown”. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Coreboot documentation
+
+
+
+
+
+
+
+
+ Suspend to RAM disabled
+
+ 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.
+
+
+
+
+ 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. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Wikipedia article on cold boot attacks
+
+
+
+
+
+
+
+
+ Intel CET Available
+
+ 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).
+
+
+
+
+ For HSI-3 this should be available and enabled v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel CET Technology Preview
+
+
+
+
+
+
+
+
+ DRAM memory encryption
+
+ TME (Intel) or TSME (AMD) 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.
+
+
+
+
+ For HSI-4 this should be supported and enabled v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Intel TME Press Release
+
+
+
+
+ WikiChip SME Overview
+
+
+
+
+
+
+
+ Supervisor Mode Access Prevention
+
+ 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.
+
+
+
+
+ For HSI-4 the SMAP and SMEP features should be available on the CPU. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Wikipedia SMAP Article
+
+
+
+
+
+
+
+
+ Kernel DMA protection
+
+ 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.
+
+
+
+
+ For HSI-2 this should be available for use. v1.5.0
+
+
+
+
+
+ See also:
+
+
+
+ Wikipedia IOMMU article
+
+
+
+
+
+
+
+
+ Suspend-to-Idle
+
+ The platform should be set up with Suspend-to-Idle as the default S3
+ sleep state.
+
+
+
+
+ For HSI-3 this should be set v1.5.0
+
+
+
+
+
+
+ Conclusion
+
+ Any system with a Host Security ID of 0
can easily be
+ modified from userspace.
+ PCs with confidential documents should have a HSI:3
or
+ higher level of protection.
+ In a graphical tool that would show details about the computer (such as
+ GNOME Control Center’s 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 HSI:1
or the suffix is !
.
+
+
+ On Linux fwupd
is used to enumerate and update firmware.
+ It exports a property HostSecurityId
and a
+ GetHostSecurityAttrs()
method.
+ The attributes are supposed to represent the system as a whole
+ 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 org.intel.prx
.
+
+
+ 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.
+
+
+ The long term goal is to increase the HSI:x
level of systems
+ being sold to consumers.
+ By making some of the HSI:x
attributes part of the LVFS
+ uploaded report we can allow users to compare vendors and models before
+ purchasing hardware.
+
+
+
+
+ Intentional Omissions
+
+
+ Intel SGX
+
+ This is not widely used as it has several high severity security issues.
+
+
+
+ Intel MPX
+
+ MPX support was removed from GCC and the Linux kernel in 2019 and it is
+ now considered obsolete.
+
+
+
+
+ Further Work
+
+ 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.
+
+
+ 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.
+
+
+
+
+
diff -Nru fwupd-1.4.5/docs/meson.build fwupd-1.5.8/docs/meson.build
--- fwupd-1.4.5/docs/meson.build 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/docs/meson.build 2021-03-31 20:08:32.000000000 +0000
@@ -5,6 +5,11 @@
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
diff -Nru fwupd-1.4.5/docs/tutorial.xml fwupd-1.5.8/docs/tutorial.xml
--- fwupd-1.4.5/docs/tutorial.xml 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/docs/tutorial.xml 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,402 @@
+
+
+
+ Plugin Tutorial
+
+
+ Introduction
+
+ 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.
+
+
+ There are broadly 3 types of plugin methods:
+
+
+
+
+ Mechanism: Upload binary data
+ into a specific hardware device.
+
+
+
+
+ Policy: Control the system when
+ updates are happening, e.g. preventing the user from powering-off.
+
+
+
+
+ Helpers: Providing more
+ metadata about devices, for instance handling device quirks.
+
+
+
+
+ In general, building things out-of-tree isn't something that we think is
+ a very good idea; the API and ABI internal 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 .so
binary file
+ manually.
+
+
+
+ A plugin only needs to define the vfuncs that are required, and the
+ plugin name is taken automatically from the suffix of the
+ .so file.
+
+
+ A sample plugin
+
+/*
+* Copyright (C) 2017 Richard Hughes
+*/
+
+#include <fu-plugin.h>
+#include <fu-plugin-vfuncs.h>
+
+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;
+}
+
+
+
+
+ We have to define when our plugin is run in reference to other plugins,
+ in this case, making sure we run before the dfu
plugin.
+ For most plugins it does not matter in what order they are run and
+ this information is not required.
+
+
+
+
+ Creating an abstract device
+
+ 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 FuDevice
from the hardware,
+ for example reading data from sysfs
or /dev
.
+
+
+ Example adding a custom device
+
+#include <fu-plugin.h>
+
+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;
+}
+
+
+
+ This shows a lot of the plugin architecture in action. Some notable points:
+
+
+
+
+ The device ID (dummy-1:2:3
) has to be unique on the
+ system between all plugins, so including the plugin name as a
+ prefix is probably a good idea.
+
+
+
+
+ The GUID value can be generated automatically using
+ fu_device_add_guid(dev,"some-identifier")
but is quoted
+ here explicitly.
+ The GUID value has to match the provides
value in the
+ .metainfo.xml
file for the firmware update to succeed.
+
+
+
+
+ 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.
+
+
+
+
+ The FWUPD_DEVICE_FLAG_UPDATABLE
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 FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER
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
+ FWUPD_DEVICE_FLAG_REQUIRE_AC
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.
+
+
+
+
+ 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
+
+
+
+
+
+
+ Mechanism Plugins
+
+ 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.
+
+
+ When a plugin has created a device that is FWUPD_DEVICE_FLAG_UPDATABLE
+ we can ask the daemon to update the device with a suitable
+ .cab
file.
+ When this is done the daemon checks the update for compatibility with
+ the device, and then calls the vfuncs to update the device.
+
+
+
+ Updating a device
+
+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, &sz);
+/* write 'buf' of size 'sz' to the hardware */
+return TRUE;
+}
+
+
+
+ It's important to note that the blob_fw
is the binary
+ firmware file (e.g. .dfu
) and not
+ the .cab
binary data.
+
+
+ If FWUPD_INSTALL_FLAG_FORCE
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.
+
+
+
+
+ Policy Helpers
+
+ 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.
+
+
+
+ Running before a device update
+
+gboolean
+fu_plugin_update_prepare (FuPlugin *plugin, FuDevice *device, GError **error)
+{
+if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_REQUIRE_AC && !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;
+}
+
+
+
+ Running after a device update
+
+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);
+}
+
+
+
+
+
+ Detaching to bootloader mode
+
+ 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.
+
+
+ Before the device update is performed the fwupd daemon runs an optional
+ update_detach()
vfunc which switches the device to
+ bootloader mode.
+ After the update (or if the update fails) an the daemon runs an
+ optional update_attach()
vfunc which should switch the
+ hardware back to runtime mode.
+ Finally an optional update_reload()
vfunc is run to
+ get the new firmware version from the hardware.
+
+
+ The optional vfuncs are only run
+ on the plugin currently registered to handle the device ID, although
+ the registered plugin can change during the attach and detach phases.
+
+
+
+ Running before a device update
+
+gboolean
+fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error)
+{
+if (hardware_in_bootloader)
+ return TRUE;
+return _device_detach(device, error);
+}
+
+
+
+ Running after a device update
+
+gboolean
+fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error)
+{
+if (!hardware_in_bootloader)
+ return TRUE;
+return _device_attach(device, error);
+}
+
+
+
+ Running after a device update on success
+
+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;
+}
+
+
+
+
+
+ The Plugin Object Cache
+
+ 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 GObject
s to enable the
+ cache objects to be properly refcounted.
+
+
+
+
+ Debugging a Plugin
+
+ If the fwupd daemon is started with --plugin-verbose=$plugin
+ then the environment variable FWUPD_$PLUGIN_VERBOSE
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 --plugin-verbose=logitech_hidpp
would set
+ FWUPD_LOGITECH_HID_VERBOSE=1
.
+
+
+
+
+ Using existing code to develop a plugin
+
+ It is not usually possible to share 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.
+
+
+ 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 vendor saves by creating a shim layer and
+ importing existing source code into fwupd will be overtaken 100x by
+ upstream maintenance costs longer term, which isn't fair.
+
+
+ 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.
+
+
+ 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.
+
+
+
+
+
diff -Nru fwupd-1.4.5/.editorconfig fwupd-1.5.8/.editorconfig
--- fwupd-1.4.5/.editorconfig 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/.editorconfig 2021-03-31 20:08:32.000000000 +0000
@@ -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
+
diff -Nru fwupd-1.4.5/.github/ISSUE_TEMPLATE/bug-report-uefi.md fwupd-1.5.8/.github/ISSUE_TEMPLATE/bug-report-uefi.md
--- fwupd-1.4.5/.github/ISSUE_TEMPLATE/bug-report-uefi.md 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/.github/ISSUE_TEMPLATE/bug-report-uefi.md 2021-03-31 20:08:32.000000000 +0000
@@ -53,3 +53,4 @@
- Is this a regression?
- Are you using an NVMe disk?
- Is secure boot enabled?
+- Is this a Lenovo system with 'Boot Order Lock' turned on in the BIOS?
diff -Nru fwupd-1.4.5/.github/ISSUE_TEMPLATE/bug-report-wd19.md fwupd-1.5.8/.github/ISSUE_TEMPLATE/bug-report-wd19.md
--- fwupd-1.4.5/.github/ISSUE_TEMPLATE/bug-report-wd19.md 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/.github/ISSUE_TEMPLATE/bug-report-wd19.md 2021-03-31 20:08:32.000000000 +0000
@@ -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?
+
diff -Nru fwupd-1.4.5/.github/pull_request_template.md fwupd-1.5.8/.github/pull_request_template.md
--- fwupd-1.4.5/.github/pull_request_template.md 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/.github/pull_request_template.md 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
Type of pull request:
-- [ ] New plugin (Please include [new plugin checklist](https://github.com/hughsie/fwupd/wiki/New-plugin-checklist))
+- [ ] New plugin (Please include [new plugin checklist](https://github.com/fwupd/fwupd/wiki/New-plugin-checklist))
- [ ] Code fix
- [ ] Feature
- [ ] Documentation
diff -Nru fwupd-1.4.5/.github/workflows/create_containers.yml fwupd-1.5.8/.github/workflows/create_containers.yml
--- fwupd-1.4.5/.github/workflows/create_containers.yml 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/.github/workflows/create_containers.yml 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,36 @@
+name: Create containers
+on:
+ schedule:
+ - cron: '0 0 * * *'
+
+jobs:
+ push_to_registry:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [fedora, debian-x86_64, arch, debian-i386]
+
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v2
+ # TODO(#122): Remove step when https://github.com/actions/virtual-environments/issues/2658 fixed
+ - name: update runc # https://github.com/actions/virtual-environments/issues/2698#issuecomment-779262068
+ if: startsWith(matrix.os, 'arch')
+ run: |
+ sudo apt-get install --assume-yes libseccomp-dev
+ git clone https://github.com/opencontainers/runc
+ cd runc && git checkout v1.0.0-rc93 && make -j`nproc` && sudo make install
+ cd .. && rm --recursive runc
+ - name: "Generate Dockerfile"
+ env:
+ OS: ${{ matrix.os }}
+ run: ./contrib/ci/generate_docker.py
+ - name: Push to GitHub Packages
+ uses: docker/build-push-action@v1
+ with:
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ registry: docker.pkg.github.com
+ repository: fwupd/fwupd/fwupd-${{matrix.os}}
+ tags: latest
diff -Nru fwupd-1.4.5/.github/workflows/main.yml fwupd-1.5.8/.github/workflows/main.yml
--- fwupd-1.4.5/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/.github/workflows/main.yml 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,61 @@
+name: Continuous Integration
+on:
+ push:
+ branches: [ 1_5_X ]
+ pull_request:
+ branches: [ 1_5_X ]
+
+jobs:
+ abi:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Refresh dependencies
+ run: sudo apt update
+ - name: Install dependencies
+ run: ./contrib/ci/generate_dependencies.py | sudo xargs apt install -y
+ - name: Check ABI
+ run: ./contrib/ci/check-abi $(git describe --abbrev=0 --tags) $(git rev-parse HEAD)
+
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os: [fedora, debian-x86_64, arch, debian-i386]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Docker login
+ run: docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $GITHUB_TOKEN
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ - name: Build in container
+ env:
+ CI_NETWORK: true
+ CI: true
+ run: |
+ echo $GITHUB_WORKSPACE
+ docker run --privileged -e CI=true -t -v $GITHUB_WORKSPACE:/github/workspace docker.pkg.github.com/fwupd/fwupd/fwupd-${{matrix.os}}:latest
+
+ fuzzing:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Build Fuzzers
+ id: build
+ uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
+ with:
+ oss-fuzz-project-name: 'fwupd'
+ dry-run: false
+ - name: Run Fuzzers
+ uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
+ with:
+ oss-fuzz-project-name: 'fwupd'
+ fuzz-seconds: 300
+ dry-run: false
+ - name: Upload Crash
+ uses: actions/upload-artifact@v1
+ if: failure() && steps.build.outcome == 'success'
+ with:
+ name: artifacts
+ path: ./out/artifacts
diff -Nru fwupd-1.4.5/.gitignore fwupd-1.5.8/.gitignore
--- fwupd-1.4.5/.gitignore 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/.gitignore 2021-03-31 20:08:32.000000000 +0000
@@ -1,4 +1,5 @@
/build
+/build-win32
/dist
/.vscode
/build-dir
@@ -21,3 +22,14 @@
/*.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/
+.buildconfig
+.ossfuzz
diff -Nru fwupd-1.4.5/.lgtm.yml fwupd-1.5.8/.lgtm.yml
--- fwupd-1.4.5/.lgtm.yml 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/.lgtm.yml 2021-03-31 20:08:32.000000000 +0000
@@ -13,6 +13,7 @@
- python3-setuptools
- python3-wheel
- python3-cairo
+ - python3-gi-cairo
- libssl-dev
after_prepare:
- python3 -m pip install --user "meson >= 0.52.0"
diff -Nru fwupd-1.4.5/libfwupd/fwupd-client.c fwupd-1.5.8/libfwupd/fwupd-client.c
--- fwupd-1.4.5/libfwupd/fwupd-client.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-client.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2018 Richard Hughes
+ * Copyright (C) 2016 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -8,7 +8,10 @@
#include
#include
-#include
+#include
+#ifdef HAVE_LIBCURL
+#include
+#endif
#ifdef HAVE_GIO_UNIX
#include
#endif
@@ -18,15 +21,20 @@
#include
#include
-#include "fwupd-client.h"
+#include "fwupd-client-private.h"
+#include "fwupd-client-sync.h"
#include "fwupd-common-private.h"
#include "fwupd-deprecated.h"
#include "fwupd-enums.h"
#include "fwupd-error.h"
#include "fwupd-device-private.h"
+#include "fwupd-plugin-private.h"
+#include "fwupd-security-attr-private.h"
#include "fwupd-release-private.h"
#include "fwupd-remote-private.h"
+typedef GObject *(*FwupdClientObjectNewFunc) (void);
+
/**
* SECTION:fwupd-client
* @short_description: a way of interfacing with the daemon
@@ -39,19 +47,36 @@
static void fwupd_client_finalize (GObject *object);
typedef struct {
+ GMainContext *main_ctx;
FwupdStatus status;
gboolean tainted;
gboolean interactive;
guint percentage;
+ GMutex idle_mutex; /* for @idle_id and @idle_sources */
+ guint idle_id;
+ GPtrArray *idle_sources; /* element-type FwupdClientContextHelper */
gchar *daemon_version;
gchar *host_product;
gchar *host_machine_id;
- GDBusConnection *conn;
+ gchar *host_security_id;
+ GMutex proxy_mutex; /* for @proxy */
GDBusProxy *proxy;
- SoupSession *soup_session;
gchar *user_agent;
+#ifdef SOUP_SESSION_COMPAT
+ GObject *soup_session;
+ GModule *soup_module; /* we leak this */
+#endif
} FwupdClientPrivate;
+#ifdef HAVE_LIBCURL
+typedef struct {
+ GPtrArray *urls;
+ CURL *curl;
+ curl_mime *mime;
+ struct curl_slist *headers;
+} FwupdCurlHelper;
+#endif
+
enum {
SIGNAL_CHANGED,
SIGNAL_STATUS_CHANGED,
@@ -67,9 +92,10 @@
PROP_PERCENTAGE,
PROP_DAEMON_VERSION,
PROP_TAINTED,
- PROP_SOUP_SESSION,
+ PROP_SOUP_SESSION, /* compat ABI, do not use! */
PROP_HOST_PRODUCT,
PROP_HOST_MACHINE_ID,
+ PROP_HOST_SECURITY_ID,
PROP_INTERACTIVE,
PROP_LAST
};
@@ -79,98 +105,233 @@
G_DEFINE_TYPE_WITH_PRIVATE (FwupdClient, fwupd_client, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fwupd_client_get_instance_private (o))
+#ifdef HAVE_LIBCURL_7_62_0
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURLU, curl_url_cleanup)
+#endif
+
+#ifdef HAVE_LIBCURL
+static void
+fwupd_client_curl_helper_free (FwupdCurlHelper *helper)
+{
+ if (helper->curl != NULL)
+ curl_easy_cleanup (helper->curl);
+ if (helper->mime != NULL)
+ curl_mime_free (helper->mime);
+ if (helper->headers != NULL)
+ curl_slist_free_all (helper->headers);
+ if (helper->urls != NULL)
+ g_ptr_array_unref (helper->urls);
+ g_free (helper);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(FwupdCurlHelper, fwupd_client_curl_helper_free)
+#endif
+
typedef struct {
- gboolean ret;
- GError *error;
- GMainLoop *loop;
- GVariant *val;
- GDBusMessage *message;
-} FwupdClientHelper;
-
-static void
-fwupd_client_helper_free (FwupdClientHelper *helper)
-{
- if (helper->message != NULL)
- g_object_unref (helper->message);
- if (helper->val != NULL)
- g_variant_unref (helper->val);
- if (helper->error != NULL)
- g_error_free (helper->error);
- g_main_loop_unref (helper->loop);
+ FwupdClient *self;
+ gchar *property_name;
+ guint signal_id;
+ FwupdDevice *device;
+} FwupdClientContextHelper;
+
+static void
+fwupd_client_context_helper_free (FwupdClientContextHelper *helper)
+{
+ g_clear_object (&helper->device);
+ g_object_unref (helper->self);
+ g_free (helper->property_name);
g_free (helper);
}
-static FwupdClientHelper *
-fwupd_client_helper_new (void)
+/* always executed in the main context given by priv->main_ctx */
+static void
+fwupd_client_context_object_notify (FwupdClient *self, const gchar *property_name)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+
+ g_return_if_fail (g_main_context_is_owner (priv->main_ctx));
+
+ /* property */
+ g_object_notify (G_OBJECT (self), property_name);
+
+ /* legacy signal name */
+ if (g_strcmp0 (property_name, "status") == 0)
+ g_signal_emit (self, signals[SIGNAL_STATUS_CHANGED], 0, priv->status);
+}
+
+/* emits all pending context helpers in the correct GMainContext */
+static gboolean
+fwupd_client_context_idle_cb (gpointer user_data)
+{
+ FwupdClient *self = FWUPD_CLIENT (user_data);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->idle_mutex);
+
+ g_assert (locker != NULL);
+
+ for (guint i = 0; i < priv->idle_sources->len; i++) {
+ FwupdClientContextHelper *helper = g_ptr_array_index (priv->idle_sources, i);
+
+ /* property */
+ if (helper->property_name != NULL)
+ fwupd_client_context_object_notify (self, helper->property_name);
+
+ /* device signal */
+ if (helper->signal_id !=0 && helper->device != NULL)
+ g_signal_emit (self, signals[helper->signal_id], 0, helper->device);
+ }
+
+ /* all done */
+ g_ptr_array_set_size (priv->idle_sources, 0);
+ priv->idle_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+fwupd_client_context_helper (FwupdClient *self, FwupdClientContextHelper *helper)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->idle_mutex);
+
+ g_assert (locker != NULL);
+
+ /* no source already attached to the context */
+ if (priv->idle_id == 0) {
+ g_autoptr(GSource) source = g_idle_source_new ();
+ g_source_set_callback (source, fwupd_client_context_idle_cb, self, NULL);
+ priv->idle_id = g_source_attach (g_steal_pointer (&source), priv->main_ctx);
+ }
+
+ /* run in the correct GMainContext and thread */
+ g_ptr_array_add (priv->idle_sources, helper);
+}
+
+/* run callback in the correct thread */
+static void
+fwupd_client_object_notify (FwupdClient *self, const gchar *property_name)
{
- FwupdClientHelper *helper;
- helper = g_new0 (FwupdClientHelper, 1);
- helper->loop = g_main_loop_new (NULL, FALSE);
- return helper;
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ FwupdClientContextHelper *helper = NULL;
+
+ /* shortcut */
+ if (g_main_context_is_owner (priv->main_ctx)) {
+ fwupd_client_context_object_notify (self, property_name);
+ return;
+ }
+
+ /* run in the correct GMainContext and thread */
+ helper = g_new0 (FwupdClientContextHelper, 1);
+ helper->self = g_object_ref (self);
+ helper->property_name = g_strdup (property_name);
+ fwupd_client_context_helper (self, helper);
}
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(FwupdClientHelper, fwupd_client_helper_free)
-#pragma clang diagnostic pop
+/* run callback in the correct thread */
+static void
+fwupd_client_signal_emit_device (FwupdClient *self, guint signal_id, FwupdDevice *device)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ FwupdClientContextHelper *helper = NULL;
+
+ /* shortcut */
+ if (g_main_context_is_owner (priv->main_ctx)) {
+ g_signal_emit (self, signals[signal_id], 0, device);
+ return;
+ }
+
+ /* run in the correct GMainContext and thread */
+ helper = g_new0 (FwupdClientContextHelper, 1);
+ helper->self = g_object_ref (self);
+ helper->signal_id = signal_id;
+ helper->device = g_object_ref (device);
+ fwupd_client_context_helper (self, helper);
+}
static void
-fwupd_client_set_host_product (FwupdClient *client, const gchar *host_product)
+fwupd_client_set_host_product (FwupdClient *self, const gchar *host_product)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->host_product, host_product) == 0)
+ return;
+
g_free (priv->host_product);
priv->host_product = g_strdup (host_product);
- g_object_notify (G_OBJECT (client), "host-product");
+ fwupd_client_object_notify (self, "host-product");
}
static void
-fwupd_client_set_host_machine_id (FwupdClient *client, const gchar *host_machine_id)
+fwupd_client_set_host_machine_id (FwupdClient *self, const gchar *host_machine_id)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->host_machine_id, host_machine_id) == 0)
+ return;
+
g_free (priv->host_machine_id);
priv->host_machine_id = g_strdup (host_machine_id);
- g_object_notify (G_OBJECT (client), "host-machine-id");
+ fwupd_client_object_notify (self, "host-machine-id");
+}
+
+static void
+fwupd_client_set_host_security_id (FwupdClient *self, const gchar *host_security_id)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->host_security_id, host_security_id) == 0)
+ return;
+
+ g_free (priv->host_security_id);
+ priv->host_security_id = g_strdup (host_security_id);
+ fwupd_client_object_notify (self, "host-security-id");
}
static void
-fwupd_client_set_daemon_version (FwupdClient *client, const gchar *daemon_version)
+fwupd_client_set_daemon_version (FwupdClient *self, const gchar *daemon_version)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->daemon_version, daemon_version) == 0)
+ return;
+
g_free (priv->daemon_version);
priv->daemon_version = g_strdup (daemon_version);
- g_object_notify (G_OBJECT (client), "daemon-version");
+ fwupd_client_object_notify (self, "daemon-version");
}
static void
-fwupd_client_set_status (FwupdClient *client, FwupdStatus status)
+fwupd_client_set_status (FwupdClient *self, FwupdStatus status)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
if (priv->status == status)
return;
priv->status = status;
g_debug ("Emitting ::status-changed() [%s]",
fwupd_status_to_string (priv->status));
- g_signal_emit (client, signals[SIGNAL_STATUS_CHANGED], 0, priv->status);
- g_object_notify (G_OBJECT (client), "status");
+ fwupd_client_object_notify (self, "status");
}
static void
-fwupd_client_set_percentage (FwupdClient *client, guint percentage)
+fwupd_client_set_percentage (FwupdClient *self, guint percentage)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
if (priv->percentage == percentage)
return;
priv->percentage = percentage;
- g_object_notify (G_OBJECT (client), "percentage");
+ fwupd_client_object_notify (self, "percentage");
}
static void
fwupd_client_properties_changed_cb (GDBusProxy *proxy,
GVariant *changed_properties,
GStrv invalidated_properties,
- FwupdClient *client)
+ FwupdClient *self)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
g_autoptr(GVariantDict) dict = NULL;
/* print to the console */
@@ -179,14 +340,14 @@
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy, "Status");
if (val != NULL)
- fwupd_client_set_status (client, g_variant_get_uint32 (val));
+ fwupd_client_set_status (self, g_variant_get_uint32 (val));
}
if (g_variant_dict_contains (dict, "Tainted")) {
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy, "Tainted");
if (val != NULL) {
priv->tainted = g_variant_get_boolean (val);
- g_object_notify (G_OBJECT (client), "tainted");
+ fwupd_client_object_notify (self, "tainted");
}
}
if (g_variant_dict_contains (dict, "Interactive")) {
@@ -194,32 +355,38 @@
val = g_dbus_proxy_get_cached_property (proxy, "Interactive");
if (val != NULL) {
priv->interactive = g_variant_get_boolean (val);
- g_object_notify (G_OBJECT (client), "interactive");
+ fwupd_client_object_notify (self, "interactive");
}
}
if (g_variant_dict_contains (dict, "Percentage")) {
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy, "Percentage");
if (val != NULL)
- fwupd_client_set_percentage (client, g_variant_get_uint32 (val));
+ fwupd_client_set_percentage (self, g_variant_get_uint32 (val));
}
if (g_variant_dict_contains (dict, "DaemonVersion")) {
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy, "DaemonVersion");
if (val != NULL)
- fwupd_client_set_daemon_version (client, g_variant_get_string (val, NULL));
+ fwupd_client_set_daemon_version (self, g_variant_get_string (val, NULL));
}
if (g_variant_dict_contains (dict, "HostProduct")) {
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy, "HostProduct");
if (val != NULL)
- fwupd_client_set_host_product (client, g_variant_get_string (val, NULL));
+ fwupd_client_set_host_product (self, g_variant_get_string (val, NULL));
}
if (g_variant_dict_contains (dict, "HostMachineId")) {
g_autoptr(GVariant) val = NULL;
val = g_dbus_proxy_get_cached_property (proxy, "HostMachineId");
if (val != NULL)
- fwupd_client_set_host_machine_id (client, g_variant_get_string (val, NULL));
+ fwupd_client_set_host_machine_id (self, g_variant_get_string (val, NULL));
+ }
+ if (g_variant_dict_contains (dict, "HostSecurityId")) {
+ g_autoptr(GVariant) val = NULL;
+ val = g_dbus_proxy_get_cached_property (proxy, "HostSecurityId");
+ if (val != NULL)
+ fwupd_client_set_host_security_id (self, g_variant_get_string (val, NULL));
}
}
@@ -228,41 +395,81 @@
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
- FwupdClient *client)
+ FwupdClient *self)
{
g_autoptr(FwupdDevice) dev = NULL;
if (g_strcmp0 (signal_name, "Changed") == 0) {
g_debug ("Emitting ::changed()");
- g_signal_emit (client, signals[SIGNAL_CHANGED], 0);
+ g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
return;
}
if (g_strcmp0 (signal_name, "DeviceAdded") == 0) {
dev = fwupd_device_from_variant (parameters);
g_debug ("Emitting ::device-added(%s)",
fwupd_device_get_id (dev));
- g_signal_emit (client, signals[SIGNAL_DEVICE_ADDED], 0, dev);
+ fwupd_client_signal_emit_device (self, SIGNAL_DEVICE_ADDED, dev);
return;
}
if (g_strcmp0 (signal_name, "DeviceRemoved") == 0) {
dev = fwupd_device_from_variant (parameters);
- g_signal_emit (client, signals[SIGNAL_DEVICE_REMOVED], 0, dev);
g_debug ("Emitting ::device-removed(%s)",
fwupd_device_get_id (dev));
+ fwupd_client_signal_emit_device (self, SIGNAL_DEVICE_REMOVED, dev);
return;
}
if (g_strcmp0 (signal_name, "DeviceChanged") == 0) {
dev = fwupd_device_from_variant (parameters);
- g_signal_emit (client, signals[SIGNAL_DEVICE_CHANGED], 0, dev);
g_debug ("Emitting ::device-changed(%s)",
fwupd_device_get_id (dev));
+ fwupd_client_signal_emit_device (self, SIGNAL_DEVICE_CHANGED, dev);
return;
}
g_debug ("Unknown signal name '%s' from %s", signal_name, sender_name);
}
/**
+ * fwupd_client_get_main_context:
+ * @self: A #FwupdClient
+ *
+ * Gets the internal #GMainContext to use for synchronous methods.
+ * By default the value is set a new #GMainContext.
+ *
+ * Return value: (transfer full): the #GMainContext
+ *
+ * Since: 1.5.3
+ **/
+GMainContext *
+fwupd_client_get_main_context (FwupdClient *self)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ if (priv->main_ctx != NULL)
+ return g_main_context_ref (priv->main_ctx);
+ return g_main_context_new ();
+}
+
+/**
+ * fwupd_client_set_main_context:
+ * @self: A #FwupdClient
+ * @main_ctx: (nullable): #GMainContext or %NULL to use the global default main context
+ *
+ * Sets the internal #GMainContext to use for returning progress signals.
+ *
+ * Since: 1.5.3
+ **/
+void
+fwupd_client_set_main_context (FwupdClient *self, GMainContext *main_ctx)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ if (main_ctx == priv->main_ctx)
+ return;
+ g_clear_pointer (&priv->main_ctx, g_main_context_unref);
+ if (main_ctx != NULL)
+ priv->main_ctx = g_main_context_ref (main_ctx);
+}
+
+/**
* fwupd_client_ensure_networking:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
* @error: the #GError, or %NULL
*
* Sets up the client networking support ready for use. Most other download and
@@ -274,15 +481,12 @@
* Since: 1.4.5
**/
gboolean
-fwupd_client_ensure_networking (FwupdClient *client, GError **error)
+fwupd_client_ensure_networking (FwupdClient *self, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- const gchar *http_proxy;
- g_autoptr(SoupSession) session = NULL;
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
- /* already exists */
- if (priv->soup_session != NULL)
- return TRUE;
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* check the user agent is sane */
if (priv->user_agent == NULL) {
@@ -299,22 +503,71 @@
"user agent unsuitable; fwupd version required");
return FALSE;
}
+#ifdef SOUP_SESSION_COMPAT
+ if (priv->soup_session != NULL) {
+ g_object_set (priv->soup_session,
+ "user-agent", priv->user_agent,
+ NULL);
+ }
+#endif
+ return TRUE;
+}
+
+#ifdef HAVE_LIBCURL
+static int
+fwupd_client_progress_callback_cb (void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow)
+{
+ FwupdClient *self = FWUPD_CLIENT (clientp);
+
+ /* calculate percentage */
+ if (dltotal > 0 && dlnow >= 0 && dlnow <= dltotal) {
+ guint percentage = (guint) ((100 * dlnow) / dltotal);
+ g_debug ("download progress: %u%%", percentage);
+ fwupd_client_set_percentage (self, percentage);
+ } else if (ultotal > 0 && ulnow >= 0 && ulnow <= ultotal) {
+ guint percentage = (guint) ((100 * ulnow) / ultotal);
+ g_debug ("upload progress: %u%%", percentage);
+ fwupd_client_set_percentage (self, percentage);
+ }
+
+ return 0;
+}
+
+static FwupdCurlHelper *
+fwupd_client_curl_new (FwupdClient *self, GError **error)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ const gchar *http_proxy;
+ g_autoptr(FwupdCurlHelper) helper = g_new0 (FwupdCurlHelper, 1);
- /* create the soup session */
- session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, priv->user_agent,
- SOUP_SESSION_TIMEOUT, 60,
- NULL);
- if (session == NULL) {
+ /* check the user agent is sane */
+ if (!fwupd_client_ensure_networking (self, error))
+ return NULL;
+
+ /* create the session */
+ helper->curl = curl_easy_init ();
+ if (helper->curl == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to setup networking");
- return FALSE;
+ return NULL;
}
+ if (g_getenv ("FWUPD_CURL_VERBOSE") != NULL)
+ curl_easy_setopt (helper->curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt (helper->curl, CURLOPT_XFERINFOFUNCTION, fwupd_client_progress_callback_cb);
+ curl_easy_setopt (helper->curl, CURLOPT_XFERINFODATA, self);
+ curl_easy_setopt (helper->curl, CURLOPT_USERAGENT, priv->user_agent);
+ curl_easy_setopt (helper->curl, CURLOPT_CONNECTTIMEOUT, 60L);
+ curl_easy_setopt (helper->curl, CURLOPT_NOPROGRESS, 0L);
/* relax the SSL checks for broken corporate proxies */
if (g_getenv ("DISABLE_SSL_STRICT") != NULL)
- g_object_set (session, SOUP_SESSION_SSL_STRICT, FALSE, NULL);
+ curl_easy_setopt (helper->curl, CURLOPT_SSL_VERIFYPEER, 0L);
/* set the proxy */
http_proxy = g_getenv ("https_proxy");
@@ -324,90 +577,143 @@
http_proxy = g_getenv ("http_proxy");
if (http_proxy == NULL)
http_proxy = g_getenv ("HTTP_PROXY");
- if (http_proxy != NULL && strlen (http_proxy) > 0) {
- g_autoptr(SoupURI) proxy_uri = soup_uri_new (http_proxy);
- if (proxy_uri == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "invalid proxy URI: %s", http_proxy);
- return FALSE;
- }
- g_object_set (session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
- }
+ if (http_proxy != NULL && strlen (http_proxy) > 0)
+ curl_easy_setopt (helper->curl, CURLOPT_PROXY, http_proxy);
/* this disables the double-compression of the firmware.xml.gz file */
- soup_session_remove_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
- priv->soup_session = g_steal_pointer (&session);
- return TRUE;
+ curl_easy_setopt (helper->curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
+ return g_steal_pointer (&helper);
}
+#endif
-/**
- * fwupd_client_connect:
- * @client: A #FwupdClient
- * @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
- *
- * Sets up the client ready for use. Most other methods call this
- * for you, and do you only need to call this if you are just watching
- * the client.
- *
- * Returns: %TRUE for success
- *
- * Since: 0.7.1
- **/
-gboolean
-fwupd_client_connect (FwupdClient *client, GCancellable *cancellable, GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+static void
+fwupd_client_connect_get_proxy_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ FwupdClient *self = g_task_get_source_object (task);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GError) error = NULL;
g_autoptr(GVariant) val = NULL;
g_autoptr(GVariant) val2 = NULL;
+ g_autoptr(GVariant) val3 = NULL;
+ g_autoptr(GVariant) val4 = NULL;
+ g_autoptr(GVariant) val5 = NULL;
+ g_autoptr(GVariant) val6 = NULL;
+ g_autoptr(GVariant) val7 = NULL;
+ g_autoptr(GMutexLocker) locker = NULL;
+
+ proxy = g_dbus_proxy_new_finish (res, &error);
+ if (proxy == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* nothing to do */
- if (priv->proxy != NULL)
- return TRUE;
-
- /* connect to the daemon */
- priv->conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
- if (priv->conn == NULL) {
- g_prefix_error (error, "Failed to connect to system D-Bus: ");
- return FALSE;
+ /* another thread did this for us */
+ locker = g_mutex_locker_new (&priv->proxy_mutex);
+ if (priv->proxy != NULL) {
+ g_task_return_boolean (task, TRUE);
+ return;
}
- priv->proxy = g_dbus_proxy_new_sync (priv->conn,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL,
- FWUPD_DBUS_SERVICE,
- FWUPD_DBUS_PATH,
- FWUPD_DBUS_INTERFACE,
- NULL,
- error);
- if (priv->proxy == NULL)
- return FALSE;
+ priv->proxy = g_steal_pointer (&proxy);
+
+ /* connect signals, etc. */
g_signal_connect (priv->proxy, "g-properties-changed",
- G_CALLBACK (fwupd_client_properties_changed_cb), client);
+ G_CALLBACK (fwupd_client_properties_changed_cb), self);
g_signal_connect (priv->proxy, "g-signal",
- G_CALLBACK (fwupd_client_signal_cb), client);
+ G_CALLBACK (fwupd_client_signal_cb), self);
val = g_dbus_proxy_get_cached_property (priv->proxy, "DaemonVersion");
if (val != NULL)
- fwupd_client_set_daemon_version (client, g_variant_get_string (val, NULL));
+ fwupd_client_set_daemon_version (self, g_variant_get_string (val, NULL));
val2 = g_dbus_proxy_get_cached_property (priv->proxy, "Tainted");
if (val2 != NULL)
priv->tainted = g_variant_get_boolean (val2);
- val2 = g_dbus_proxy_get_cached_property (priv->proxy, "Interactive");
- if (val2 != NULL)
- priv->interactive = g_variant_get_boolean (val2);
- val = g_dbus_proxy_get_cached_property (priv->proxy, "HostProduct");
- if (val != NULL)
- fwupd_client_set_host_product (client, g_variant_get_string (val, NULL));
- val = g_dbus_proxy_get_cached_property (priv->proxy, "HostMachineId");
- if (val != NULL)
- fwupd_client_set_host_machine_id (client, g_variant_get_string (val, NULL));
+ val3 = g_dbus_proxy_get_cached_property (priv->proxy, "Status");
+ if (val3 != NULL)
+ fwupd_client_set_status (self, g_variant_get_uint32 (val3));
+ val4 = g_dbus_proxy_get_cached_property (priv->proxy, "Interactive");
+ if (val4 != NULL)
+ priv->interactive = g_variant_get_boolean (val4);
+ val5 = g_dbus_proxy_get_cached_property (priv->proxy, "HostProduct");
+ if (val5 != NULL)
+ fwupd_client_set_host_product (self, g_variant_get_string (val5, NULL));
+ val6 = g_dbus_proxy_get_cached_property (priv->proxy, "HostMachineId");
+ if (val6 != NULL)
+ fwupd_client_set_host_machine_id (self, g_variant_get_string (val6, NULL));
+ val7 = g_dbus_proxy_get_cached_property (priv->proxy, "HostSecurityId");
+ if (val7 != NULL)
+ fwupd_client_set_host_security_id (self, g_variant_get_string (val7, NULL));
- return TRUE;
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_connect_async:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Sets up the client ready for use. This is probably the first method you call
+ * when wanting to use libfwupd in an asynchronous manner.
+ *
+ * Other methods such as fwupd_client_get_devices_async() should only be called
+ * after fwupd_client_connect_finish() has been called without an error.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_connect_async (FwupdClient *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->proxy_mutex);
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ g_assert (locker != NULL);
+
+ /* nothing to do */
+ if (priv->proxy != NULL) {
+ g_task_return_boolean (task, TRUE);
+ return;
+ }
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ FWUPD_DBUS_SERVICE,
+ FWUPD_DBUS_PATH,
+ FWUPD_DBUS_INTERFACE,
+ cancellable,
+ fwupd_client_connect_get_proxy_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_connect_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_connect_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_connect_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
}
static void
@@ -443,712 +749,1452 @@
g_dbus_error_strip_remote_error (error);
}
+static void
+fwupd_client_get_host_security_attrs_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_security_attr_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
+}
+
/**
- * fwupd_client_get_devices:
- * @client: A #FwupdClient
+ * fwupd_client_get_host_security_attrs_async:
+ * @self: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Gets all the devices registered with the daemon.
+ * Gets all the host security attributes from the daemon.
*
- * Returns: (element-type FwupdDevice) (transfer container): results
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 0.9.2
+ * Since: 1.5.0
**/
-GPtrArray *
-fwupd_client_get_devices (FwupdClient *client, GCancellable *cancellable, GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+void
+fwupd_client_get_host_security_attrs_async (FwupdClient *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetDevices",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
- if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
- }
- return fwupd_device_array_from_variant (val);
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetHostSecurityAttrs",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_host_security_attrs_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_get_history:
- * @client: A #FwupdClient
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_host_security_attrs_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Gets all the history.
+ * Gets the result of fwupd_client_get_host_security_attrs_async().
*
- * Returns: (element-type FwupdDevice) (transfer container): results
+ * Returns: (element-type FwupdSecurityAttr) (transfer container): attributes
*
- * Since: 1.0.4
+ * Since: 1.5.0
**/
GPtrArray *
-fwupd_client_get_history (FwupdClient *client, GCancellable *cancellable, GError **error)
+fwupd_client_get_host_security_attrs_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+static GHashTable *
+fwupd_report_metadata_hash_from_variant (GVariant *value)
+{
+ GHashTable *hash;
+ gsize sz;
+ g_autoptr(GVariant) untuple = NULL;
+
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ untuple = g_variant_get_child_value (value, 0);
+ sz = g_variant_n_children (untuple);
+ for (guint i = 0; i < sz; i++) {
+ g_autoptr(GVariant) data = NULL;
+ const gchar *key = NULL;
+ const gchar *val = NULL;
+ data = g_variant_get_child_value (untuple, i);
+ g_variant_get (data, "{&s&s}", &key, &val);
+ g_hash_table_insert (hash, g_strdup (key), g_strdup (val));
+ }
+ return hash;
+}
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetHistory",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+static void
+fwupd_client_get_report_metadata_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return fwupd_device_array_from_variant (val);
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_report_metadata_hash_from_variant (val),
+ (GDestroyNotify) g_hash_table_unref);
}
/**
- * fwupd_client_get_device_by_id:
- * @client: A #FwupdClient
- * @device_id: the device ID, e.g. `usb:00:01:03:03`
+ * fwupd_client_get_report_metadata_async:
+ * @self: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets all the report metadata from the daemon.
+ *
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_report_metadata_async (FwupdClient *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetReportMetadata",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_report_metadata_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_report_metadata_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Gets a device by it's device ID.
+ * Gets the result of fwupd_client_get_report_metadata_async().
*
- * Returns: (transfer full): a #FwupdDevice or %NULL
+ * Returns: (transfer container): attributes
*
- * Since: 0.9.3
+ * Since: 1.5.0
**/
-FwupdDevice *
-fwupd_client_get_device_by_id (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error)
+GHashTable *
+fwupd_client_get_report_metadata_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- g_autoptr(GPtrArray) devices = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (device_id != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* get all the devices */
- devices = fwupd_client_get_devices (client, cancellable, error);
- if (devices == NULL)
- return NULL;
+static void
+fwupd_client_get_devices_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* find the device by ID (client side) */
- for (guint i = 0; i < devices->len; i++) {
- FwupdDevice *dev = g_ptr_array_index (devices, i);
- if (g_strcmp0 (fwupd_device_get_id (dev), device_id) == 0)
- return g_object_ref (dev);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_FOUND,
- "failed to find %s", device_id);
- return NULL;
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_device_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
}
/**
- * fwupd_client_get_devices_by_guid:
- * @client: A #FwupdClient
- * @guid: the GUID, e.g. `e22c4520-43dc-5bb3-8245-5787fead9b63`
+ * fwupd_client_get_devices_async:
+ * @self: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Gets any devices that provide a specific GUID. An error is returned if no
- * devices contains this GUID.
+ * Gets all the devices registered with the daemon.
*
- * Returns: (element-type FwupdDevice) (transfer container): devices or %NULL
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 1.4.1
+ * Since: 1.5.0
**/
-GPtrArray *
-fwupd_client_get_devices_by_guid (FwupdClient *client,
- const gchar *guid,
- GCancellable *cancellable,
- GError **error)
+void
+fwupd_client_get_devices_async (FwupdClient *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer callback_data)
{
- g_autoptr(GPtrArray) devices = NULL;
- g_autoptr(GPtrArray) devices_tmp = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (guid != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* get all the devices */
- devices_tmp = fwupd_client_get_devices (client, cancellable, error);
- if (devices_tmp == NULL)
- return NULL;
-
- /* find the devices by GUID (client side) */
- devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
- for (guint i = 0; i < devices_tmp->len; i++) {
- FwupdDevice *dev_tmp = g_ptr_array_index (devices_tmp, i);
- if (fwupd_device_has_guid (dev_tmp, guid))
- g_ptr_array_add (devices, g_object_ref (dev_tmp));
- }
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
- /* nothing */
- if (devices->len == 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_FOUND,
- "failed to find any device providing %s", guid);
- return NULL;
- }
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
- /* success */
- return g_steal_pointer (&devices);
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetDevices",
+ NULL, G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_devices_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_get_releases:
- * @client: A #FwupdClient
- * @device_id: the device ID
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_devices_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Gets all the releases for a specific device
+ * Gets the result of fwupd_client_get_devices_async().
*
- * Returns: (element-type FwupdRelease) (transfer container): results
+ * Returns: (element-type FwupdDevice) (transfer container): results
*
- * Since: 0.9.3
+ * Since: 1.5.0
**/
GPtrArray *
-fwupd_client_get_releases (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
+fwupd_client_get_devices_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (device_id != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+static void
+fwupd_client_get_plugins_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetReleases",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return fwupd_release_array_from_variant (val);
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_plugin_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
}
/**
- * fwupd_client_get_downgrades:
- * @client: A #FwupdClient
- * @device_id: the device ID
+ * fwupd_client_get_plugins_async:
+ * @self: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Gets all the downgrades for a specific device.
+ * Gets all the plugins being used by the daemon.
*
- * Returns: (element-type FwupdRelease) (transfer container): results
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 0.9.8
+ * Since: 1.5.0
**/
-GPtrArray *
-fwupd_client_get_downgrades (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
+void
+fwupd_client_get_plugins_async (FwupdClient *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer callback_data)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (device_id != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetDowngrades",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
- if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
- }
- return fwupd_release_array_from_variant (val);
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetPlugins",
+ NULL, G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_plugins_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_get_upgrades:
- * @client: A #FwupdClient
- * @device_id: the device ID
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_plugins_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Gets all the upgrades for a specific device.
+ * Gets the result of fwupd_client_get_plugins_async().
*
- * Returns: (element-type FwupdRelease) (transfer container): results
+ * Returns: (element-type FwupdDevice) (transfer container): results
*
- * Since: 0.9.8
+ * Since: 1.5.0
**/
GPtrArray *
-fwupd_client_get_upgrades (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
+fwupd_client_get_plugins_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (device_id != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+static void
+fwupd_client_get_history_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetUpgrades",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return fwupd_release_array_from_variant (val);
-}
-static void
-fwupd_client_proxy_call_cb (GObject *source, GAsyncResult *res, gpointer user_data)
-{
- FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
- helper->val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source),
- res, &helper->error);
- if (helper->val != NULL)
- helper->ret = TRUE;
- if (helper->error != NULL)
- fwupd_client_fixup_dbus_error (helper->error);
- g_main_loop_quit (helper->loop);
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_device_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
}
/**
- * fwupd_client_modify_config
- * @client: A #FwupdClient
- * @key: key, e.g. `BlacklistPlugins`
- * @value: value, e.g. `*`
+ * fwupd_client_get_history_async:
+ * @self: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Modifies a daemon config option.
- * The daemon will only respond to this request with proper permissions
+ * Gets all the history.
*
- * Returns: %TRUE for success
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 1.2.8
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_modify_config (FwupdClient *client, const gchar *key, const gchar *value,
- GCancellable *cancellable, GError **error)
+void
+fwupd_client_get_history_async (FwupdClient *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer callback_data)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "ModifyConfig",
- g_variant_new ("(ss)", key, value),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
- }
- return TRUE;
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetHistory",
+ NULL, G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_history_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_activate:
- * @client: A #FwupdClient
- * @cancellable: the #GCancellable, or %NULL
- * @device_id: a device
+ * fwupd_client_get_history_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Activates up a device, which normally means the device switches to a new
- * firmware version. This should only be called when data loss cannot occur.
+ * Gets the result of fwupd_client_get_history_async().
*
- * Returns: %TRUE for success
+ * Returns: (element-type FwupdDevice) (transfer container): results
*
- * Since: 1.2.6
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_activate (FwupdClient *client, GCancellable *cancellable,
- const gchar *device_id, GError **error)
+GPtrArray *
+fwupd_client_get_history_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+static void
+fwupd_client_get_device_by_id_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ const gchar *device_id = g_task_get_task_data (task);
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+ devices = fwupd_client_get_devices_finish (FWUPD_CLIENT (source), res, &error);
+ if (devices == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
- /* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "Activate",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
+ /* find the device by ID (client side) */
+ for (guint i = 0; i < devices->len; i++) {
+ FwupdDevice *dev = g_ptr_array_index (devices, i);
+ if (g_strcmp0 (fwupd_device_get_id (dev), device_id) == 0) {
+ g_task_return_pointer (task,
+ g_object_ref (dev),
+ (GDestroyNotify) g_object_unref);
+ return;
+ }
}
- return TRUE;
+
+ /* failed */
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "failed to find %s", device_id);
}
/**
- * fwupd_client_verify:
- * @client: A #FwupdClient
+ * fwupd_client_get_device_by_id_async:
+ * @self: A #FwupdClient
* @device_id: the device ID
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Verify a specific device.
+ * Gets a device by it's device ID.
*
- * Returns: %TRUE for verification success
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 0.7.0
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_verify (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+void
+fwupd_client_get_device_by_id_async (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "Verify",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
- }
- return TRUE;
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_set_task_data (task, g_strdup (device_id), g_free);
+ fwupd_client_get_devices_async (self, cancellable,
+ fwupd_client_get_device_by_id_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_verify_update:
- * @client: A #FwupdClient
- * @device_id: the device ID
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_device_by_id_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Update the verification record for a specific device.
+ * Gets the result of fwupd_client_get_device_by_id_async().
*
- * Returns: %TRUE for verification success
+ * Returns: (transfer full): a #FwupdDevice, or %NULL for failure
*
- * Since: 0.8.0
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_verify_update (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
+FwupdDevice *
+fwupd_client_get_device_by_id_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+static void
+fwupd_client_get_devices_by_guid_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GPtrArray) devices_tmp = NULL;
+ const gchar *guid = g_task_get_task_data (task);
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+ /* get all the devices */
+ devices_tmp = fwupd_client_get_devices_finish (FWUPD_CLIENT (source), res, &error);
+ if (devices_tmp == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
- /* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "VerifyUpdate",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
+ /* find the devices by GUID (client side) */
+ devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+ for (guint i = 0; i < devices_tmp->len; i++) {
+ FwupdDevice *dev_tmp = g_ptr_array_index (devices_tmp, i);
+ if (fwupd_device_has_guid (dev_tmp, guid))
+ g_ptr_array_add (devices, g_object_ref (dev_tmp));
}
- return TRUE;
+
+ /* nothing */
+ if (devices->len == 0) {
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "failed to find any device providing %s", guid);
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ g_steal_pointer (&devices),
+ (GDestroyNotify) g_ptr_array_unref);
}
/**
- * fwupd_client_unlock:
- * @client: A #FwupdClient
- * @device_id: the device ID
+ * fwupd_client_get_devices_by_guid_async:
+ * @self: A #FwupdClient
+ * @guid: the GUID, e.g. `e22c4520-43dc-5bb3-8245-5787fead9b63`
* @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets any devices that provide a specific GUID. An error is returned if no
+ * devices contains this GUID.
+ *
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_devices_by_guid_async (FwupdClient *self, const gchar *guid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (guid != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_set_task_data (task, g_strdup (guid), g_free);
+ fwupd_client_get_devices_async (self, cancellable,
+ fwupd_client_get_devices_by_guid_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_devices_by_guid_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Unlocks a specific device so firmware can be read or wrote.
+ * Gets the result of fwupd_client_get_devices_by_guid_async().
*
- * Returns: %TRUE for success
+ * Returns: (element-type FwupdRelease) (transfer container): results
*
- * Since: 0.7.0
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_unlock (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
+GPtrArray *
+fwupd_client_get_devices_by_guid_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+static void
+fwupd_client_get_releases_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "Unlock",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return TRUE;
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_release_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
}
/**
- * fwupd_client_clear_results:
- * @client: A #FwupdClient
+ * fwupd_client_get_releases_async:
+ * @self: A #FwupdClient
* @device_id: the device ID
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Clears the results for a specific device.
+ * Gets all the releases for a specific device
*
- * Returns: %TRUE for success
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 0.7.0
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_clear_results (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+void
+fwupd_client_get_releases_async (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "ClearResults",
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetReleases",
g_variant_new ("(s)", device_id),
G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
- }
- return TRUE;
+ -1, cancellable,
+ fwupd_client_get_releases_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_get_results:
- * @client: A #FwupdClient
- * @device_id: the device ID
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_releases_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Gets the results of a previous firmware update for a specific device.
+ * Gets the result of fwupd_client_get_releases_async().
*
- * Returns: (transfer full): a #FwupdDevice, or %NULL for failure
+ * Returns: (element-type FwupdRelease) (transfer container): results
*
- * Since: 0.7.0
+ * Since: 1.5.0
**/
-FwupdDevice *
-fwupd_client_get_results (FwupdClient *client, const gchar *device_id,
- GCancellable *cancellable, GError **error)
+GPtrArray *
+fwupd_client_get_releases_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(FwupdClientHelper) helper = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (device_id != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
-
- /* call into daemon */
- helper = fwupd_client_helper_new ();
- g_dbus_proxy_call (priv->proxy,
- "GetResults",
- g_variant_new ("(s)", device_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- fwupd_client_proxy_call_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return NULL;
- }
- return fwupd_device_from_variant (helper->val);
+ return g_task_propagate_pointer (G_TASK(res), error);
}
-#ifdef HAVE_GIO_UNIX
static void
-fwupd_client_send_message_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+fwupd_client_get_downgrades_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
{
- FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
- GDBusConnection *con = G_DBUS_CONNECTION (source_object);
- helper->message = g_dbus_connection_send_message_with_reply_finish (con, res,
- &helper->error);
- if (helper->message &&
- !g_dbus_message_to_gerror (helper->message, &helper->error)) {
- helper->ret = TRUE;
- helper->val = g_dbus_message_get_body (helper->message);
- if (helper->val != NULL)
- g_variant_ref (helper->val);
- }
- if (helper->error != NULL)
- fwupd_client_fixup_dbus_error (helper->error);
- g_main_loop_quit (helper->loop);
-}
-#endif
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_release_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
+}
+
+/**
+ * fwupd_client_get_downgrades_async:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets all the downgrades for a specific device.
+ *
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_downgrades_async (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetDowngrades",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_downgrades_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_downgrades_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_get_downgrades_async().
+ *
+ * Returns: (element-type FwupdRelease) (transfer container): results
+ *
+ * Since: 1.5.0
+ **/
+GPtrArray *
+fwupd_client_get_downgrades_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
+
+static void
+fwupd_client_get_upgrades_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_release_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
+}
+
+/**
+ * fwupd_client_get_upgrades_async:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets all the upgrades for a specific device.
+ *
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_upgrades_async (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetUpgrades",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_upgrades_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_upgrades_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_get_upgrades_async().
+ *
+ * Returns: (element-type FwupdRelease) (transfer container): results
+ *
+ * Since: 1.5.0
+ **/
+GPtrArray *
+fwupd_client_get_upgrades_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
+
+static void
+fwupd_client_modify_config_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_modify_config_async:
+ * @self: A #FwupdClient
+ * @key: key, e.g. `DisabledPlugins`
+ * @value: value, e.g. `*`
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Modifies a daemon config option.
+ * The daemon will only respond to this request with proper permissions
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_modify_config_async (FwupdClient *self,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "ModifyConfig",
+ g_variant_new ("(ss)", key, value),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_modify_config_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_modify_config_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_modify_config_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_modify_config_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_activate_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_activate_async:
+ * @self: A #FwupdClient
+ * @device_id: a device
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Activates up a device, which normally means the device switches to a new
+ * firmware version. This should only be called when data loss cannot occur.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_activate_async (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "Activate",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_activate_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_activate_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_activate_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_activate_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_verify_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_verify_async:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Verify a specific device.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_verify_async (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "Verify",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_verify_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_verify_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_verify_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_verify_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_verify_update_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_verify_update_async:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Update the verification record for a specific device.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_verify_update_async (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "VerifyUpdate",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_verify_update_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_verify_update_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_verify_update_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_verify_update_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_unlock_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_unlock_async:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Unlocks a specific device so firmware can be read or wrote.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_unlock_async (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "Unlock",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_unlock_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_unlock_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_unlock_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_unlock_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_clear_results_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * fwupd_client_clear_results_async:
+ * @self: A #FwupdClient
+ * @device_id: a device
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Clears the results for a specific device.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_clear_results_async (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "ClearResults",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_clear_results_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_clear_results_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_clear_results_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_clear_results_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_get_results_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_device_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
+}
+
+/**
+ * fwupd_client_get_results_async:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets the results of a previous firmware update for a specific device.
+ *
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_results_async (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetResults",
+ g_variant_new ("(s)", device_id),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_results_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_results_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_get_results_async().
+ *
+ * Returns: (transfer full): a #FwupdDevice, or %NULL for failure
+ *
+ * Since: 1.5.0
+ **/
+FwupdDevice *
+fwupd_client_get_results_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
#ifdef HAVE_GIO_UNIX
-static gboolean
-fwupd_client_install_fd (FwupdClient *client,
- const gchar *device_id,
- GUnixInputStream *istr,
- const gchar *filename_hint,
- FwupdInstallFlags install_flags,
- GCancellable *cancellable,
- GError **error)
+
+static void
+fwupd_client_install_stream_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GDBusMessage) msg = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ msg = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+ res, &error);
+ if (msg == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ if (g_dbus_message_to_gerror (msg, &error)) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+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)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- GVariant *body;
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
GVariantBuilder builder;
- gint retval;
- g_autoptr(FwupdClientHelper) helper = NULL;
g_autoptr(GDBusMessage) request = NULL;
g_autoptr(GUnixFDList) fd_list = NULL;
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
/* set options */
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
@@ -1170,10 +2216,18 @@
g_variant_builder_add (&builder, "{sv}",
"allow-reinstall", g_variant_new_boolean (TRUE));
}
+ if (install_flags & FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH) {
+ g_variant_builder_add (&builder, "{sv}",
+ "allow-branch-switch", g_variant_new_boolean (TRUE));
+ }
if (install_flags & FWUPD_INSTALL_FLAG_FORCE) {
g_variant_builder_add (&builder, "{sv}",
"force", g_variant_new_boolean (TRUE));
}
+ if (install_flags & FWUPD_INSTALL_FLAG_IGNORE_POWER) {
+ g_variant_builder_add (&builder, "{sv}",
+ "ignore-power", g_variant_new_boolean (TRUE));
+ }
if (install_flags & FWUPD_INSTALL_FLAG_NO_HISTORY) {
g_variant_builder_add (&builder, "{sv}",
"no-history", g_variant_new_boolean (TRUE));
@@ -1181,8 +2235,7 @@
/* set out of band file descriptor */
fd_list = g_unix_fd_list_new ();
- retval = g_unix_fd_list_append (fd_list, g_unix_input_stream_get_fd (istr), NULL);
- g_assert (retval != -1);
+ g_unix_fd_list_append (fd_list, g_unix_input_stream_get_fd (istr), NULL);
request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
FWUPD_DBUS_PATH,
FWUPD_DBUS_INTERFACE,
@@ -1190,315 +2243,648 @@
g_dbus_message_set_unix_fd_list (request, fd_list);
/* call into daemon */
- helper = fwupd_client_helper_new ();
- body = g_variant_new ("(sha{sv})", device_id, g_unix_input_stream_get_fd (istr), &builder);
- g_dbus_message_set_body (request, body);
- g_dbus_connection_send_message_with_reply (priv->conn,
+ g_dbus_message_set_body (request, g_variant_new ("(sha{sv})",
+ device_id,
+ g_unix_input_stream_get_fd (istr),
+ &builder));
+ g_dbus_connection_send_message_with_reply (g_dbus_proxy_get_connection (priv->proxy),
request,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
G_MAXINT,
NULL,
cancellable,
- fwupd_client_send_message_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
- }
- return TRUE;
+ fwupd_client_install_stream_cb,
+ g_steal_pointer (&task));
}
#endif
/**
- * fwupd_client_install_bytes:
- * @client: A #FwupdClient
+ * fwupd_client_install_bytes_async:
+ * @self: A #FwupdClient
* @device_id: the device ID
* @bytes: #GBytes
* @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Install firmware onto a specific device.
*
- * Returns: %TRUE for success
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
*
- * Since: 1.4.5
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_install_bytes (FwupdClient *client,
- const gchar *device_id,
- GBytes *bytes,
- FwupdInstallFlags install_flags,
- GCancellable *cancellable,
- GError **error)
+void
+fwupd_client_install_bytes_async (FwupdClient *self,
+ const gchar *device_id,
+ GBytes *bytes,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
{
#ifdef HAVE_GIO_UNIX
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GError) error = NULL;
g_autoptr(GUnixInputStream) istr = NULL;
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (bytes != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* move to a thread if this ever takes more than a few ms */
+ istr = fwupd_unix_input_stream_from_bytes (bytes, &error);
+ if (istr == NULL) {
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
- istr = fwupd_unix_input_stream_from_bytes (bytes, error);
- if (istr == NULL)
- return FALSE;
- return fwupd_client_install_fd (client, device_id, istr, NULL,
- install_flags, cancellable, error);
+ /* call into daemon */
+ fwupd_client_install_stream_async (self, device_id, istr, NULL,
+ install_flags, cancellable,
+ callback, callback_data);
#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not supported as is unavailable");
- return FALSE;
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
#endif
}
/**
- * fwupd_client_install:
- * @client: A #FwupdClient
+ * fwupd_client_install_bytes_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_install_bytes_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_install_bytes_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+/**
+ * fwupd_client_install_async:
+ * @self: A #FwupdClient
* @device_id: the device ID
* @filename: the filename to install
* @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Install a file onto a specific device.
+ * Install firmware onto a specific device.
*
- * Returns: %TRUE for success
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
*
- * Since: 0.7.0
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_install (FwupdClient *client,
- const gchar *device_id,
- const gchar *filename,
- FwupdInstallFlags install_flags,
- GCancellable *cancellable,
- GError **error)
+void
+fwupd_client_install_async (FwupdClient *self,
+ const gchar *device_id,
+ const gchar *filename,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
{
#ifdef HAVE_GIO_UNIX
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GError) error = NULL;
g_autoptr(GUnixInputStream) istr = NULL;
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (device_id != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (filename != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* move to a thread if this ever takes more than a few ms */
+ istr = fwupd_unix_input_stream_from_fn (filename, &error);
+ if (istr == NULL) {
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* call into daemon */
+ fwupd_client_install_stream_async (self, device_id, istr, NULL,
+ install_flags, cancellable,
+ callback, callback_data);
+#else
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
+#endif
+}
+
+/**
+ * fwupd_client_install_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_install_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_install_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+typedef struct {
+ FwupdDevice *device;
+ FwupdRelease *release;
+ FwupdInstallFlags install_flags;
+ FwupdClientDownloadFlags download_flags;
+} FwupdClientInstallReleaseData;
- istr = fwupd_unix_input_stream_from_fn (filename, error);
- if (istr == NULL)
- return FALSE;
- return fwupd_client_install_fd (client, device_id, istr, filename,
- install_flags, cancellable, error);
+static void
+fwupd_client_install_release_data_free (FwupdClientInstallReleaseData *data)
+{
+ g_object_unref (data->device);
+ g_object_unref (data->release);
+ g_free (data);
+}
+
+static void
+fwupd_client_install_release_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ if (!fwupd_client_install_release_finish (FWUPD_CLIENT (source), res, &error)) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+fwupd_client_install_release_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ if (!fwupd_client_install_bytes_finish (FWUPD_CLIENT (source), res, &error)) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+fwupd_client_install_release_download_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GBytes) blob = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ FwupdClientInstallReleaseData *data = g_task_get_task_data (task);
+ GChecksumType checksum_type;
+ GCancellable *cancellable = g_task_get_cancellable (task);
+ const gchar *checksum_expected;
+ g_autofree gchar *checksum_actual = NULL;
+
+ blob = fwupd_client_download_bytes_finish (FWUPD_CLIENT (source), res, &error);
+ if (blob == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* verify checksum */
+ checksum_expected = fwupd_checksum_get_best (fwupd_release_get_checksums (data->release));
+ checksum_type = fwupd_checksum_guess_kind (checksum_expected);
+ checksum_actual = g_compute_checksum_for_bytes (checksum_type, blob);
+ if (g_strcmp0 (checksum_expected, checksum_actual) != 0) {
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "checksum invalid, expected %s got %s",
+ checksum_expected, checksum_actual);
+ return;
+ }
+
+ /* if the device specifies ONLY_OFFLINE automatically set this flag */
+ if (fwupd_device_has_flag (data->device, FWUPD_DEVICE_FLAG_ONLY_OFFLINE))
+ data->install_flags |= FWUPD_INSTALL_FLAG_OFFLINE;
+ fwupd_client_install_bytes_async (FWUPD_CLIENT (source),
+ fwupd_device_get_id (data->device), blob,
+ data->install_flags, cancellable,
+ fwupd_client_install_release_bytes_cb,
+ g_steal_pointer (&task));
+}
+
+static gboolean
+fwupd_client_is_url_http (const gchar *perhaps_url)
+{
+#ifdef HAVE_LIBCURL_7_62_0
+ g_autoptr(CURLU) h = curl_url ();
+ return curl_url_set (h, CURLUPART_URL, perhaps_url, 0) == CURLUE_OK;
#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not supported as is unavailable");
- return FALSE;
+ return g_str_has_prefix (perhaps_url, "http://") ||
+ g_str_has_prefix (perhaps_url, "https://");
#endif
}
+static gboolean
+fwupd_client_is_url_ipfs (const gchar *perhaps_url)
+{
+ return g_str_has_prefix (perhaps_url, "ipfs://") ||
+ g_str_has_prefix (perhaps_url, "ipns://");
+}
+
+static void
+fwupd_client_install_release_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ GPtrArray *locations;
+ const gchar *uri_tmp;
+ g_autofree gchar *fn = NULL;
+ g_autoptr(FwupdRemote) remote = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GPtrArray) uris_built = g_ptr_array_new_with_free_func (g_free);
+ FwupdClientInstallReleaseData *data = g_task_get_task_data (task);
+ GCancellable *cancellable = g_task_get_cancellable (task);
+
+ /* if a remote-id was specified, the remote has to exist */
+ remote = fwupd_client_get_remote_by_id_finish (FWUPD_CLIENT (source), res, &error);
+ if (remote == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* get the default release only until other parts of fwupd can cope */
+ locations = fwupd_release_get_locations (data->release);
+ if (locations->len == 0) {
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "release missing URI");
+ return;
+ }
+ uri_tmp = g_ptr_array_index (locations, 0);
+
+ /* local and directory remotes may have the firmware already */
+ if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL &&
+ !fwupd_client_is_url_http (uri_tmp)) {
+ const gchar *fn_cache = fwupd_remote_get_filename_cache (remote);
+ g_autofree gchar *path = g_path_get_dirname (fn_cache);
+ fn = g_build_filename (path, uri_tmp, NULL);
+ } else if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_DIRECTORY) {
+ fn = g_strdup (uri_tmp + 7);
+ }
+
+ /* install with flags chosen by the user */
+ if (fn != NULL) {
+ fwupd_client_install_async (FWUPD_CLIENT (source),
+ fwupd_device_get_id (data->device),
+ fn, data->install_flags,
+ cancellable,
+ fwupd_client_install_release_cb,
+ g_steal_pointer (&task));
+ return;
+ }
+
+ /* remote file */
+ for (guint i = 0; i < locations->len; i++) {
+ uri_tmp = g_ptr_array_index (locations, i);
+ if (fwupd_client_is_url_ipfs (uri_tmp)) {
+ g_ptr_array_add (uris_built, g_strdup (uri_tmp));
+ } else if (fwupd_client_is_url_http (uri_tmp)) {
+ g_autofree gchar *uri_str = NULL;
+ uri_str = fwupd_remote_build_firmware_uri (remote,
+ uri_tmp,
+ &error);
+ if (uri_str == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ g_ptr_array_add (uris_built, g_steal_pointer (&uri_str));
+ }
+ }
+
+ /* download file */
+ fwupd_client_download_bytes2_async (FWUPD_CLIENT (source),
+ uris_built,
+ data->download_flags,
+ cancellable,
+ fwupd_client_install_release_download_cb,
+ g_steal_pointer (&task));
+}
+
+#ifdef HAVE_LIBCURL
+static GPtrArray *
+fwupd_client_filter_locations (GPtrArray *locations,
+ FwupdClientDownloadFlags download_flags,
+ GError **error)
+{
+ g_autoptr(GPtrArray) uris_filtered = g_ptr_array_new_with_free_func (g_free);
+
+ g_return_val_if_fail (locations != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ for (guint i = 0; i < locations->len; i++) {
+ const gchar *uri = g_ptr_array_index (locations, i);
+ if ((download_flags & FWUPD_CLIENT_DOWNLOAD_FLAG_ONLY_IPFS) > 0 &&
+ !fwupd_client_is_url_ipfs (uri))
+ continue;
+ g_ptr_array_add (uris_filtered, g_strdup (uri));
+ }
+ if (uris_filtered->len == 0) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "no valid release URIs");
+ return NULL;
+ }
+ return g_steal_pointer (&uris_filtered);
+}
+#endif
+
/**
- * fwupd_client_install_release:
- * @client: A #FwupdClient
+ * fwupd_client_install_release2_async:
+ * @self: A #FwupdClient
* @device: A #FwupdDevice
* @release: A #FwupdRelease
* @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
- * @cancellable: A #GCancellable, or %NULL
- * @error: A #GError, or %NULL
+ * @download_flags: the #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_DISABLE_IPFS
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Installs a new release on a device, downloading the firmware if required.
*
- * Returns: %TRUE for success
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
*
- * Since: 1.4.5
+ * Since: 1.5.6
**/
-gboolean
-fwupd_client_install_release (FwupdClient *client,
- FwupdDevice *device,
- FwupdRelease *release,
- FwupdInstallFlags install_flags,
- GCancellable *cancellable,
- GError **error)
-{
- GChecksumType checksum_type;
- const gchar *checksum_expected;
+void
+fwupd_client_install_release2_async (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ FwupdClientDownloadFlags download_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+ FwupdClientInstallReleaseData *data;
const gchar *remote_id;
- const gchar *uri_tmp;
- g_autofree gchar *checksum_actual = NULL;
- g_autofree gchar *uri_str = NULL;
- g_autoptr(GBytes) blob = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (FWUPD_IS_DEVICE (device));
+ g_return_if_fail (FWUPD_IS_RELEASE (release));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ data = g_new0 (FwupdClientInstallReleaseData, 1);
+ data->device = g_object_ref (device);
+ data->release = g_object_ref (release);
+ data->download_flags = download_flags;
+ data->install_flags = install_flags;
+ g_task_set_task_data (task, data, (GDestroyNotify) fwupd_client_install_release_data_free);
/* work out what remote-specific URI fields this should use */
- uri_tmp = fwupd_release_get_uri (release);
remote_id = fwupd_release_get_remote_id (release);
- if (remote_id != NULL) {
- g_autoptr(FwupdRemote) remote = NULL;
- g_autofree gchar *fn = NULL;
+ if (remote_id == NULL) {
+ fwupd_client_download_bytes2_async (self,
+ fwupd_release_get_locations (release),
+ download_flags,
+ cancellable,
+ fwupd_client_install_release_download_cb,
+ g_steal_pointer (&task));
+ return;
+ }
- /* if a remote-id was specified, the remote has to exist */
- remote = fwupd_client_get_remote_by_id (client, remote_id, cancellable, error);
- if (remote == NULL)
- return FALSE;
-
- /* local and directory remotes have the firmware already */
- if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL) {
- const gchar *fn_cache = fwupd_remote_get_filename_cache (remote);
- g_autofree gchar *path = g_path_get_dirname (fn_cache);
-
- fn = g_build_filename (path, uri_tmp, NULL);
- } else if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_DIRECTORY) {
- fn = g_strdup (uri_tmp + 7);
- }
+ /* if a remote-id was specified, the remote has to exist */
+ fwupd_client_get_remote_by_id_async (self, remote_id, cancellable,
+ fwupd_client_install_release_remote_cb,
+ g_steal_pointer (&task));
+}
- /* install with flags chosen by the user */
- if (fn != NULL) {
- return fwupd_client_install (client, fwupd_device_get_id (device),
- fn, install_flags, cancellable, error);
- }
+/**
+ * fwupd_client_install_release_async:
+ * @self: A #FwupdClient
+ * @device: A #FwupdDevice
+ * @release: A #FwupdRelease
+ * @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Installs a new release on a device, downloading the firmware if required.
+ *
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
+ *
+ * Since: 1.5.0
+ * Deprecated: 1.5.6
+ **/
+void
+fwupd_client_install_release_async (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ return fwupd_client_install_release2_async (self, device, release, install_flags,
+ FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
+ cancellable, callback, callback_data);
+}
- /* remote file */
- uri_str = fwupd_remote_build_firmware_uri (remote, uri_tmp, error);
- if (uri_str == NULL)
- return FALSE;
- } else {
- uri_str = g_strdup (uri_tmp);
- }
+/**
+ * fwupd_client_install_release_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_install_release_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_install_release_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
- /* download file */
- blob = fwupd_client_download_bytes (client, uri_str,
- FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
- cancellable, error);
- if (blob == NULL)
- return FALSE;
+#ifdef HAVE_GIO_UNIX
- /* verify checksum */
- checksum_expected = fwupd_checksum_get_best (fwupd_release_get_checksums (release));
- checksum_type = fwupd_checksum_guess_kind (checksum_expected);
- checksum_actual = g_compute_checksum_for_bytes (checksum_type, blob);
- if (g_strcmp0 (checksum_expected, checksum_actual) != 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Checksum invalid, expected %s got %s",
- checksum_expected, checksum_actual);
- return FALSE;
+static void
+fwupd_client_get_details_stream_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GDBusMessage) msg = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ msg = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+ res, &error);
+ if (msg == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ if (g_dbus_message_to_gerror (msg, &error)) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- /* if the device specifies ONLY_OFFLINE automatically set this flag */
- if (fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_ONLY_OFFLINE))
- install_flags |= FWUPD_INSTALL_FLAG_OFFLINE;
- return fwupd_client_install_bytes (client,
- fwupd_device_get_id (device), blob,
- install_flags, NULL, error);
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_device_array_from_variant (g_dbus_message_get_body (msg)),
+ (GDestroyNotify) g_ptr_array_unref);
}
-/**
- * fwupd_client_get_details:
- * @client: A #FwupdClient
- * @filename: the firmware filename, e.g. `firmware.cab`
- * @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
- *
- * Gets details about a specific firmware file.
- *
- * Returns: (transfer container) (element-type FwupdDevice): an array of results
- *
- * Since: 1.0.0
- **/
-GPtrArray *
-fwupd_client_get_details (FwupdClient *client, const gchar *filename,
- GCancellable *cancellable, GError **error)
+void
+fwupd_client_get_details_stream_async (FwupdClient *self,
+ GUnixInputStream *istr,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
{
-#ifdef HAVE_GIO_UNIX
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- GVariant *body;
- gint fd;
- gint retval;
- g_autoptr(FwupdClientHelper) helper = NULL;
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ gint fd = g_unix_input_stream_get_fd (istr);
g_autoptr(GDBusMessage) request = NULL;
g_autoptr(GUnixFDList) fd_list = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
-
- /* open file */
- fd = open (filename, O_RDONLY);
- if (fd < 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "failed to open %s",
- filename);
- return NULL;
- }
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
/* set out of band file descriptor */
fd_list = g_unix_fd_list_new ();
- retval = g_unix_fd_list_append (fd_list, fd, NULL);
- g_assert (retval != -1);
+ g_unix_fd_list_append (fd_list, fd, NULL);
request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
FWUPD_DBUS_PATH,
FWUPD_DBUS_INTERFACE,
"GetDetails");
g_dbus_message_set_unix_fd_list (request, fd_list);
- /* g_unix_fd_list_append did a dup() already */
- close (fd);
-
/* call into daemon */
- helper = fwupd_client_helper_new ();
- body = g_variant_new ("(h)", fd);
- g_dbus_message_set_body (request, body);
-
- g_dbus_connection_send_message_with_reply (priv->conn,
+ g_dbus_message_set_body (request, g_variant_new ("(h)", fd));
+ g_dbus_connection_send_message_with_reply (g_dbus_proxy_get_connection (priv->proxy),
request,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
- -1,
+ G_MAXINT,
NULL,
cancellable,
- fwupd_client_send_message_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return NULL;
+ fwupd_client_get_details_stream_cb,
+ g_steal_pointer (&task));
+}
+#endif
+
+/**
+ * fwupd_client_get_details_bytes_async:
+ * @self: A #FwupdClient
+ * @bytes: a #GBytes for the firmware, e.g. `firmware.cab`
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets details about a specific firmware file.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_details_bytes_async (FwupdClient *self,
+ GBytes *bytes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+#ifdef HAVE_GIO_UNIX
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GUnixInputStream) istr = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* move to a thread if this ever takes more than a few ms */
+ istr = fwupd_unix_input_stream_from_bytes (bytes, &error);
+ if (istr == NULL) {
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- /* return results */
- return fwupd_device_array_from_variant (helper->val);
+ /* call into daemon */
+ fwupd_client_get_details_stream_async (self, istr, cancellable,
+ callback, callback_data);
#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not supported as is unavailable");
- return NULL;
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
#endif
}
/**
+ * fwupd_client_get_details_bytes_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_get_details_bytes_async().
+ *
+ * Returns: (transfer container) (element-type FwupdDevice): an array of results
+ *
+ * Since: 1.5.0
+ **/
+GPtrArray *
+fwupd_client_get_details_bytes_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
+
+/**
* fwupd_client_get_percentage:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
*
* Gets the last returned percentage value.
*
@@ -1507,16 +2893,16 @@
* Since: 0.7.3
**/
guint
-fwupd_client_get_percentage (FwupdClient *client)
+fwupd_client_get_percentage (FwupdClient *self)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), 0);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), 0);
return priv->percentage;
}
/**
* fwupd_client_get_daemon_version:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
*
* Gets the daemon version number.
*
@@ -1525,16 +2911,16 @@
* Since: 0.9.6
**/
const gchar *
-fwupd_client_get_daemon_version (FwupdClient *client)
+fwupd_client_get_daemon_version (FwupdClient *self)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
return priv->daemon_version;
}
/**
* fwupd_client_get_host_product:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
*
* Gets the string that represents the host running fwupd
*
@@ -1543,16 +2929,16 @@
* Since: 1.3.1
**/
const gchar *
-fwupd_client_get_host_product (FwupdClient *client)
+fwupd_client_get_host_product (FwupdClient *self)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
return priv->host_product;
}
/**
* fwupd_client_get_host_machine_id:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
*
* Gets the string that represents the host machine ID
*
@@ -1561,16 +2947,34 @@
* Since: 1.3.2
**/
const gchar *
-fwupd_client_get_host_machine_id (FwupdClient *client)
+fwupd_client_get_host_machine_id (FwupdClient *self)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
return priv->host_machine_id;
}
/**
+ * fwupd_client_get_host_security_id:
+ * @self: A #FwupdClient
+ *
+ * Gets the string that represents the host machine ID
+ *
+ * Returns: a string, or %NULL for unknown.
+ *
+ * Since: 1.5.0
+ **/
+const gchar *
+fwupd_client_get_host_security_id (FwupdClient *self)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ return priv->host_security_id;
+}
+
+/**
* fwupd_client_get_status:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
*
* Gets the last returned status value.
*
@@ -1579,492 +2983,939 @@
* Since: 0.7.3
**/
FwupdStatus
-fwupd_client_get_status (FwupdClient *client)
+fwupd_client_get_status (FwupdClient *self)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FWUPD_STATUS_UNKNOWN);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FWUPD_STATUS_UNKNOWN);
return priv->status;
}
/**
* fwupd_client_get_tainted:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
+ *
+ * Gets if the daemon has been tainted by 3rd party code.
+ *
+ * Returns: %TRUE if the daemon is unsupported
+ *
+ * Since: 1.2.4
+ **/
+gboolean
+fwupd_client_get_tainted (FwupdClient *self)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ return priv->tainted;
+}
+
+/**
+ * fwupd_client_get_daemon_interactive:
+ * @self: A #FwupdClient
+ *
+ * Gets if the daemon is running in an interactive terminal.
+ *
+ * Returns: %TRUE if the daemon is running in an interactive terminal
+ *
+ * Since: 1.3.4
+ **/
+gboolean
+fwupd_client_get_daemon_interactive (FwupdClient *self)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ return priv->interactive;
+}
+
+#ifdef HAVE_GIO_UNIX
+
+static void
+fwupd_client_update_metadata_stream_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GDBusMessage) msg = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ msg = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source),
+ res, &error);
+ if (msg == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ if (g_dbus_message_to_gerror (msg, &error)) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+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)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GDBusMessage) request = NULL;
+ g_autoptr(GUnixFDList) fd_list = NULL;
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+
+ /* set out of band file descriptor */
+ fd_list = g_unix_fd_list_new ();
+ g_unix_fd_list_append (fd_list, g_unix_input_stream_get_fd (istr), NULL);
+ g_unix_fd_list_append (fd_list, g_unix_input_stream_get_fd (istr_sig), NULL);
+ request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
+ FWUPD_DBUS_PATH,
+ FWUPD_DBUS_INTERFACE,
+ "UpdateMetadata");
+ g_dbus_message_set_unix_fd_list (request, fd_list);
+
+ /* call into daemon */
+ g_dbus_message_set_body (request, g_variant_new ("(shh)",
+ remote_id,
+ g_unix_input_stream_get_fd (istr),
+ g_unix_input_stream_get_fd (istr_sig)));
+ g_dbus_connection_send_message_with_reply (g_dbus_proxy_get_connection (priv->proxy),
+ request,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ G_MAXINT,
+ NULL,
+ cancellable,
+ fwupd_client_update_metadata_stream_cb,
+ g_steal_pointer (&task));
+}
+#endif
+
+/**
+ * fwupd_client_update_metadata_bytes_async:
+ * @self: A #FwupdClient
+ * @remote_id: remote ID, e.g. `lvfs-testing`
+ * @metadata: XML metadata data
+ * @signature: signature data
+ * @cancellable: #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Updates the metadata. This allows a session process to download the metadata
+ * and metadata signing file to be passed into the daemon to be checked and
+ * parsed.
+ *
+ * The @remote_id allows the firmware to be tagged so that the remote can be
+ * matched when the firmware is downloaded.
+ *
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_update_metadata_bytes_async (FwupdClient *self,
+ const gchar *remote_id,
+ GBytes *metadata,
+ GBytes *signature,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+#ifdef HAVE_GIO_UNIX
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GUnixInputStream) istr = NULL;
+ g_autoptr(GUnixInputStream) istr_sig = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (remote_id != NULL);
+ g_return_if_fail (metadata != NULL);
+ g_return_if_fail (signature != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* move to a thread if this ever takes more than a few ms */
+ istr = fwupd_unix_input_stream_from_bytes (metadata, &error);
+ if (istr == NULL) {
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ istr_sig = fwupd_unix_input_stream_from_bytes (signature, &error);
+ if (istr_sig == NULL) {
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* call into daemon */
+ fwupd_client_update_metadata_stream_async (self, remote_id, istr, istr_sig,
+ cancellable,
+ callback, callback_data);
+#else
+ g_autoptr(GTask) task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
+#endif
+}
+
+/**
+ * fwupd_client_update_metadata_bytes_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_update_metadata_bytes_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_update_metadata_bytes_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+typedef struct {
+ FwupdRemote *remote;
+ GBytes *signature;
+ GBytes *metadata;
+} FwupdClientRefreshRemoteData;
+
+static void
+fwupd_client_refresh_remote_data_free (FwupdClientRefreshRemoteData *data)
+{
+ if (data->signature != NULL)
+ g_bytes_unref (data->signature);
+ if (data->metadata != NULL)
+ g_bytes_unref (data->metadata);
+ g_object_unref (data->remote);
+ g_free (data);
+}
+
+static void
+fwupd_client_refresh_remote_update_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ /* save metadata */
+ if (!fwupd_client_update_metadata_bytes_finish (FWUPD_CLIENT (source), res, &error)) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+fwupd_client_refresh_remote_metadata_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GBytes) bytes = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ FwupdClientRefreshRemoteData *data = g_task_get_task_data (task);
+ FwupdClient *self = g_task_get_source_object (task);
+ GCancellable *cancellable = g_task_get_cancellable (task);
+
+ /* save metadata */
+ bytes = fwupd_client_download_bytes_finish (FWUPD_CLIENT (source), res, &error);
+ if (bytes == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ data->metadata = g_steal_pointer (&bytes);
+
+ /* send all this to fwupd */
+ fwupd_client_update_metadata_bytes_async (self,
+ fwupd_remote_get_id (data->remote),
+ data->metadata,
+ data->signature,
+ cancellable,
+ fwupd_client_refresh_remote_update_cb,
+ g_steal_pointer (&task));
+}
+
+static void
+fwupd_client_refresh_remote_signature_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GBytes) bytes = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ FwupdClientRefreshRemoteData *data = g_task_get_task_data (task);
+ FwupdClient *self = g_task_get_source_object (task);
+ GCancellable *cancellable = g_task_get_cancellable (task);
+ GChecksumType checksum_kind;
+ g_autofree gchar *checksum = NULL;
+
+ /* save signature */
+ bytes = fwupd_client_download_bytes_finish (FWUPD_CLIENT (source), res, &error);
+ if (bytes == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ data->signature = g_steal_pointer (&bytes);
+ if (fwupd_remote_get_keyring_kind (data->remote) == FWUPD_KEYRING_KIND_JCAT) {
+ if (!fwupd_remote_load_signature_bytes (data->remote, data->signature, &error)) {
+ g_prefix_error (&error, "Failed to load signature: ");
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ }
+
+ /* is the signature checksum the same? */
+ checksum_kind = fwupd_checksum_guess_kind (fwupd_remote_get_checksum (data->remote));
+ checksum = g_compute_checksum_for_data (checksum_kind,
+ (const guchar *) g_bytes_get_data (data->signature, NULL),
+ g_bytes_get_size (data->signature));
+ if (g_strcmp0 (checksum, fwupd_remote_get_checksum (data->remote)) == 0) {
+ g_debug ("metadata signature of %s is unchanged, skipping",
+ fwupd_remote_get_id (data->remote));
+ g_task_return_boolean (task, TRUE);
+ return;
+ }
+
+ /* download metadata */
+ fwupd_client_download_bytes_async (self,
+ fwupd_remote_get_metadata_uri (data->remote),
+ FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
+ cancellable,
+ fwupd_client_refresh_remote_metadata_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_refresh_remote_async:
+ * @self: A #FwupdClient
+ * @remote: A #FwupdRemote
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Refreshes a remote by downloading new metadata.
+ *
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_refresh_remote_async (FwupdClient *self,
+ FwupdRemote *remote,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientRefreshRemoteData *data;
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (FWUPD_IS_REMOTE (remote));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, callback_data);
+ data = g_new0 (FwupdClientRefreshRemoteData, 1);
+ data->remote = g_object_ref (remote);
+ g_task_set_task_data (task,
+ g_steal_pointer (&data),
+ (GDestroyNotify) fwupd_client_refresh_remote_data_free);
+
+ /* download signature */
+ fwupd_client_download_bytes_async (self,
+ fwupd_remote_get_metadata_uri_sig (remote),
+ FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
+ cancellable,
+ fwupd_client_refresh_remote_signature_cb,
+ g_steal_pointer (&task));
+
+}
+
+/**
+ * fwupd_client_refresh_remote_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_refresh_remote_async().
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fwupd_client_refresh_remote_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
+
+static void
+fwupd_client_get_remotes_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ fwupd_remote_array_from_variant (val),
+ (GDestroyNotify) g_ptr_array_unref);
+}
+
+/**
+ * fwupd_client_get_remotes_async:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Gets the list of remotes that have been configured for the system.
+ *
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_remotes_async (FwupdClient *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetRemotes",
+ NULL, G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_remotes_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_remotes_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
*
- * Gets if the daemon has been tainted by 3rd party code.
+ * Gets the result of fwupd_client_get_remotes_async().
*
- * Returns: %TRUE if the daemon is unsupported
+ * Returns: (element-type FwupdRemote) (transfer container): results
*
- * Since: 1.2.4
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_get_tainted (FwupdClient *client)
+GPtrArray *
+fwupd_client_get_remotes_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- return priv->tainted;
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
}
+static void
+fwupd_client_get_approved_firmware_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_auto(GStrv) strv = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) array = g_ptr_array_new_with_free_func (g_free);
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ g_variant_get (val, "(^as)", &strv);
+ for (guint i = 0; strv[i] != NULL; i++)
+ g_ptr_array_add (array, g_strdup (strv[i]));
+
+ /* success */
+ g_task_return_pointer (task,
+ g_steal_pointer (&array),
+ (GDestroyNotify) g_ptr_array_unref);
+}
/**
- * fwupd_client_get_daemon_interactive:
- * @client: A #FwupdClient
+ * fwupd_client_get_approved_firmware_async:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Gets if the daemon is running in an interactive terminal.
+ * Gets the list of approved firmware.
*
- * Returns: %TRUE if the daemon is running in an interactive terminal
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 1.3.4
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_get_daemon_interactive (FwupdClient *client)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- return priv->interactive;
-}
-
-#ifdef HAVE_GIO_UNIX
-static gboolean
-fwupd_client_update_metadata_fds (FwupdClient *client,
- const gchar *remote_id,
- GUnixInputStream *metadata,
- GUnixInputStream *signature,
- GCancellable *cancellable,
- GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- GVariant *body;
- g_autoptr(FwupdClientHelper) helper = NULL;
- g_autoptr(GDBusMessage) request = NULL;
- g_autoptr(GUnixFDList) fd_list = NULL;
-
- /* set out of band file descriptor */
- fd_list = g_unix_fd_list_new ();
- g_unix_fd_list_append (fd_list, g_unix_input_stream_get_fd (metadata), NULL);
- g_unix_fd_list_append (fd_list, g_unix_input_stream_get_fd (signature), NULL);
- request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
- FWUPD_DBUS_PATH,
- FWUPD_DBUS_INTERFACE,
- "UpdateMetadata");
- g_dbus_message_set_unix_fd_list (request, fd_list);
+void
+fwupd_client_get_approved_firmware_async (FwupdClient *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- body = g_variant_new ("(shh)",
- remote_id,
- g_unix_input_stream_get_fd (metadata),
- g_unix_input_stream_get_fd (signature));
- g_dbus_message_set_body (request, body);
- helper = fwupd_client_helper_new ();
- g_dbus_connection_send_message_with_reply (priv->conn,
- request,
- G_DBUS_SEND_MESSAGE_FLAGS_NONE,
- -1,
- NULL,
- cancellable,
- fwupd_client_send_message_cb,
- helper);
- g_main_loop_run (helper->loop);
- if (!helper->ret) {
- g_propagate_error (error, helper->error);
- helper->error = NULL;
- return FALSE;
- }
- return TRUE;
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetApprovedFirmware",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_approved_firmware_cb,
+ g_steal_pointer (&task));
}
-#endif
-
/**
- * fwupd_client_update_metadata:
- * @client: A #FwupdClient
- * @remote_id: the remote ID, e.g. `lvfs-testing`
- * @metadata_fn: the XML metadata filename
- * @signature_fn: the GPG signature file
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_approved_firmware_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Updates the metadata. This allows a session process to download the metadata
- * and metadata signing file to be passed into the daemon to be checked and
- * parsed.
- *
- * The @remote_id allows the firmware to be tagged so that the remote can be
- * matched when the firmware is downloaded.
+ * Gets the result of fwupd_client_get_approved_firmware_async().
*
- * Returns: %TRUE for success
+ * Returns: (element-type utf8) (transfer container): checksums, or %NULL for error
*
- * Since: 1.0.0
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_update_metadata (FwupdClient *client,
- const gchar *remote_id,
- const gchar *metadata_fn,
- const gchar *signature_fn,
- GCancellable *cancellable,
- GError **error)
+GPtrArray *
+fwupd_client_get_approved_firmware_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
-#ifdef HAVE_GIO_UNIX
- GUnixInputStream *istr;
- GUnixInputStream *istr_sig;
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (remote_id != NULL, FALSE);
- g_return_val_if_fail (metadata_fn != NULL, FALSE);
- g_return_val_if_fail (signature_fn != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+static void
+fwupd_client_set_approved_firmware_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
- /* open files */
- istr = fwupd_unix_input_stream_from_fn (metadata_fn, error);
- if (istr == NULL)
- return FALSE;
- istr_sig = fwupd_unix_input_stream_from_fn (signature_fn, error);
- if (istr_sig == NULL)
- return FALSE;
- return fwupd_client_update_metadata_fds (client, remote_id,
- istr, istr_sig,
- cancellable, error);
-#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not supported as is unavailable");
- return FALSE;
-#endif
+ /* success */
+ g_task_return_boolean (task, TRUE);
}
/**
- * fwupd_client_update_metadata_bytes:
- * @client: A #FwupdClient
- * @remote_id: remote ID, e.g. `lvfs-testing`
- * @metadata: XML metadata data
- * @signature: signature data
- * @cancellable: #GCancellable, or %NULL
- * @error: the #GError, or %NULL
- *
- * Updates the metadata. This allows a session process to download the metadata
- * and metadata signing file to be passed into the daemon to be checked and
- * parsed.
- *
- * The @remote_id allows the firmware to be tagged so that the remote can be
- * matched when the firmware is downloaded.
+ * fwupd_client_set_approved_firmware_async:
+ * @self: A #FwupdClient
+ * @checksums: (element-type utf8): firmware checksums
+ * @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Returns: %TRUE for success
+ * Sets the list of approved firmware.
*
- * Since: 1.4.5
+ * Since: 1.5.0
**/
-gboolean
-fwupd_client_update_metadata_bytes (FwupdClient *client,
- const gchar *remote_id,
- GBytes *metadata,
- GBytes *signature,
- GCancellable *cancellable,
- GError **error)
-{
-#ifdef HAVE_GIO_UNIX
- GUnixInputStream *istr;
- GUnixInputStream *istr_sig;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (remote_id != NULL, FALSE);
- g_return_val_if_fail (metadata != NULL, FALSE);
- g_return_val_if_fail (signature != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+void
+fwupd_client_set_approved_firmware_async (FwupdClient *self,
+ GPtrArray *checksums,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+ g_auto(GStrv) strv = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
- /* convert bytes to a readable fd */
- istr = fwupd_unix_input_stream_from_bytes (metadata, error);
- if (istr == NULL)
- return FALSE;
- istr_sig = fwupd_unix_input_stream_from_bytes (signature, error);
- if (istr_sig == NULL)
- return FALSE;
- return fwupd_client_update_metadata_fds (client, remote_id,
- istr, istr_sig,
- cancellable, error);
-#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "Not supported as is unavailable");
- return FALSE;
-#endif
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ strv = g_new0 (gchar *, checksums->len + 1);
+ for (guint i = 0; i < checksums->len; i++) {
+ const gchar *tmp = g_ptr_array_index (checksums, i);
+ strv[i] = g_strdup (tmp);
+ }
+ g_dbus_proxy_call (priv->proxy, "SetApprovedFirmware",
+ g_variant_new ("(^as)", strv),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_set_approved_firmware_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_refresh_remote:
- * @client: A #FwupdClient
- * @remote: A #FwupdRemote
- * @cancellable: A #GCancellable, or %NULL
- * @error: A #GError, or %NULL
+ * fwupd_client_set_approved_firmware_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
*
- * Refreshes a remote by downloading new metadata.
+ * Gets the result of fwupd_client_set_approved_firmware_async().
*
* Returns: %TRUE for success
*
- * Since: 1.4.5
+ * Since: 1.5.0
**/
gboolean
-fwupd_client_refresh_remote (FwupdClient *client,
- FwupdRemote *remote,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_set_approved_firmware_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- g_autoptr(GBytes) metadata = NULL;
- g_autoptr(GBytes) signature = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (FWUPD_IS_REMOTE (remote), FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
- /* download the signature */
- signature = fwupd_client_download_bytes (client,
- fwupd_remote_get_metadata_uri_sig (remote),
- FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
- cancellable, error);
- if (signature == NULL)
- return FALSE;
+static void
+fwupd_client_get_blocked_firmware_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_auto(GStrv) strv = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) array = g_ptr_array_new_with_free_func (g_free);
+ g_autoptr(GVariant) val = NULL;
- /* find the download URI of the metadata from the JCat file */
- if (!fwupd_remote_load_signature_bytes (remote, signature, error))
- return FALSE;
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL) {
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
- /* download the metadata */
- metadata = fwupd_client_download_bytes (client,
- fwupd_remote_get_metadata_uri (remote),
- FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
- cancellable, error);
- if (metadata == NULL)
- return FALSE;
+ g_variant_get (val, "(^as)", &strv);
+ for (guint i = 0; strv[i] != NULL; i++)
+ g_ptr_array_add (array, g_strdup (strv[i]));
- /* send all this to fwupd */
- return fwupd_client_update_metadata_bytes (client,
- fwupd_remote_get_id (remote),
- metadata, signature,
- cancellable, error);
+ /* success */
+ g_task_return_pointer (task,
+ g_steal_pointer (&array),
+ (GDestroyNotify) g_ptr_array_unref);
}
/**
- * fwupd_client_get_remotes:
- * @client: A #FwupdClient
+ * fwupd_client_get_blocked_firmware_async:
+ * @self: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
- * Gets the list of remotes that have been configured for the system.
+ * Gets the list of blocked firmware.
*
- * Returns: (element-type FwupdRemote) (transfer container): list of remotes, or %NULL
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 0.9.3
+ * Since: 1.5.0
**/
-GPtrArray *
-fwupd_client_get_remotes (FwupdClient *client, GCancellable *cancellable, GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+void
+fwupd_client_get_blocked_firmware_async (FwupdClient *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetRemotes",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
- if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
- }
- return fwupd_remote_array_from_variant (val);
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "GetBlockedFirmware",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_get_blocked_firmware_cb,
+ g_steal_pointer (&task));
}
/**
- * fwupd_client_get_approved_firmware:
- * @client: A #FwupdClient
- * @cancellable: the #GCancellable, or %NULL
+ * fwupd_client_get_blocked_firmware_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Gets the list of approved firmware.
+ * Gets the result of fwupd_client_get_blocked_firmware_async().
*
- * Returns: (transfer full): list of remotes, or %NULL
+ * Returns: (element-type utf8) (transfer container): checksums, or %NULL for error
*
- * Since: 1.2.6
+ * Since: 1.5.0
**/
-gchar **
-fwupd_client_get_approved_firmware (FwupdClient *client,
- GCancellable *cancellable,
- GError **error)
+GPtrArray *
+fwupd_client_get_blocked_firmware_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
- gchar **retval = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+static void
+fwupd_client_set_blocked_firmware_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "GetApprovedFirmware",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- g_variant_get (val, "(^as)", &retval);
- return retval;
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
}
/**
- * fwupd_client_set_approved_firmware:
- * @client: A #FwupdClient
- * @checksums: Array of checksums
+ * fwupd_client_set_blocked_firmware_async:
+ * @self: A #FwupdClient
+ * @checksums: (element-type utf8): firmware checksums
* @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Sets the list of blocked firmware.
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_set_blocked_firmware_async (FwupdClient *self,
+ GPtrArray *checksums,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+ g_auto(GStrv) strv = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ strv = g_new0 (gchar *, checksums->len + 1);
+ for (guint i = 0; i < checksums->len; i++) {
+ const gchar *tmp = g_ptr_array_index (checksums, i);
+ strv[i] = g_strdup (tmp);
+ }
+ g_dbus_proxy_call (priv->proxy, "SetBlockedFirmware",
+ g_variant_new ("(^as)", strv),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_set_blocked_firmware_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_set_blocked_firmware_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Sets the list of approved firmware.
+ * Gets the result of fwupd_client_set_blocked_firmware_async().
*
* Returns: %TRUE for success
*
- * Since: 1.2.6
+ * Since: 1.5.0
**/
gboolean
-fwupd_client_set_approved_firmware (FwupdClient *client,
- gchar **checksums,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_set_blocked_firmware_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+static void
+fwupd_client_set_feature_flags_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "SetApprovedFirmware",
- g_variant_new ("(^as)", checksums),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return FALSE;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return TRUE;
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
}
/**
- * fwupd_client_set_feature_flags:
- * @client: A #FwupdClient
+ * fwupd_client_set_feature_flags_async:
+ * @self: A #FwupdClient
* @feature_flags: #FwupdFeatureFlags, e.g. %FWUPD_FEATURE_FLAG_UPDATE_TEXT
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Sets the features the client supports. This allows firmware to depend on
* specific front-end features, for instance showing the user an image on
* how to detach the hardware.
*
- * Clients can call this none or multiple times.
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_set_feature_flags_async (FwupdClient *self,
+ FwupdFeatureFlags feature_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "SetFeatureFlags",
+ g_variant_new ("(t)", (guint64) feature_flags),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_set_feature_flags_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_set_feature_flags_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_set_feature_flags_async().
*
* Returns: %TRUE for success
*
- * Since: 1.4.5
+ * Since: 1.5.0
**/
gboolean
-fwupd_client_set_feature_flags (FwupdClient *client,
- FwupdFeatureFlags feature_flags,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_set_feature_flags_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+static void
+fwupd_client_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ gchar *str = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "SetFeatureFlags",
- g_variant_new ("(t)", (guint64) feature_flags),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return FALSE;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return TRUE;
+
+ /* success */
+ g_variant_get (val, "(s)", &str);
+ g_task_return_pointer (task,
+ g_steal_pointer (&str),
+ (GDestroyNotify) g_free);
}
/**
- * fwupd_client_self_sign:
- * @client: A #FwupdClient
+ * fwupd_client_self_sign_async:
+ * @self: A #FwupdClient
* @value: A string to sign, typically a JSON blob
* @flags: #FwupdSelfSignFlags, e.g. %FWUPD_SELF_SIGN_FLAG_ADD_TIMESTAMP
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Signs the data using the client self-signed certificate.
*
- * Returns: %TRUE for success
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 1.2.6
+ * Since: 1.5.0
**/
-gchar *
-fwupd_client_self_sign (FwupdClient *client,
- const gchar *value,
- FwupdSelfSignFlags flags,
- GCancellable *cancellable,
- GError **error)
+void
+fwupd_client_self_sign_async (FwupdClient *self,
+ const gchar *value,
+ FwupdSelfSignFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
GVariantBuilder builder;
- g_autoptr(GVariant) val = NULL;
- gchar *retval = NULL;
+ g_autoptr(GTask) task = NULL;
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return NULL;
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* set options */
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
@@ -2078,131 +3929,204 @@
}
/* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "SelfSign",
- g_variant_new ("(sa{sv})", value, &builder),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy,
+ "SelfSign",
+ g_variant_new ("(sa{sv})", value, &builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, cancellable,
+ fwupd_client_self_sign_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_self_sign_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_self_sign_async().
+ *
+ * Returns: a signature, or %NULL for failure
+ *
+ * Since: 1.5.0
+ **/
+gchar *
+fwupd_client_self_sign_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
+
+static void
+fwupd_client_modify_remote_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return NULL;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- g_variant_get (val, "(s)", &retval);
- return retval;
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
}
/**
- * fwupd_client_modify_remote:
- * @client: A #FwupdClient
+ * fwupd_client_modify_remote_async:
+ * @self: A #FwupdClient
* @remote_id: the remote ID, e.g. `lvfs-testing`
* @key: the key, e.g. `Enabled`
* @value: the key, e.g. `true`
* @cancellable: the #GCancellable, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
+ *
+ * Modifies a system remote in a specific way.
+ *
+ * Since: 1.5.0
+ **/
+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)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (remote_id != NULL);
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "ModifyRemote",
+ g_variant_new ("(sss)", remote_id, key, value),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_modify_remote_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_modify_remote_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
* @error: the #GError, or %NULL
*
- * Modifies a system remote in a specific way.
- *
- * NOTE: User authentication may be required to complete this action.
+ * Gets the result of fwupd_client_modify_remote_async().
*
* Returns: %TRUE for success
*
- * Since: 0.9.8
+ * Since: 1.5.0
**/
gboolean
-fwupd_client_modify_remote (FwupdClient *client,
- const gchar *remote_id,
- const gchar *key,
- const gchar *value,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_modify_remote_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (remote_id != NULL, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
- g_return_val_if_fail (value != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK(res), error);
+}
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
+static void
+fwupd_client_modify_device_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) val = NULL;
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "ModifyRemote",
- g_variant_new ("(sss)", remote_id, key, value),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return FALSE;
+ fwupd_client_fixup_dbus_error (error);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
}
- return TRUE;
+
+ /* success */
+ g_task_return_boolean (task, TRUE);
}
/**
- * fwupd_client_modify_device:
- * @client: A #FwupdClient
+ * fwupd_client_modify_device_async:
+ * @self: A #FwupdClient
* @device_id: the device ID
* @key: the key, e.g. `Flags`
* @value: the key, e.g. `reported`
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Modifies a device in a specific way. Not all properties on the #FwupdDevice
* are settable by the client, and some may have other restrictions on @value.
*
- * NOTE: User authentication may be required to complete this action.
+ * Since: 1.5.0
+ **/
+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)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (device_id != NULL);
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_dbus_proxy_call (priv->proxy, "ModifyDevice",
+ g_variant_new ("(sss)", device_id, key, value),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable,
+ fwupd_client_modify_device_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_modify_device_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_modify_device_async().
*
* Returns: %TRUE for success
*
- * Since: 1.0.4
+ * Since: 1.5.0
**/
gboolean
-fwupd_client_modify_device (FwupdClient *client,
- const gchar *remote_id,
- const gchar *key,
- const gchar *value,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_modify_device_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_autoptr(GVariant) val = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (remote_id != NULL, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
- g_return_val_if_fail (value != NULL, FALSE);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* connect */
- if (!fwupd_client_connect (client, cancellable, error))
- return FALSE;
-
- /* call into daemon */
- val = g_dbus_proxy_call_sync (priv->proxy,
- "ModifyDevice",
- g_variant_new ("(sss)", remote_id, key, value),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- error);
- if (val == NULL) {
- if (error != NULL)
- fwupd_client_fixup_dbus_error (*error);
- return FALSE;
- }
- return TRUE;
+ return g_task_propagate_boolean (G_TASK(res), error);
}
static FwupdRemote *
@@ -2216,54 +4140,98 @@
return NULL;
}
+static void
+fwupd_client_get_remote_by_id_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ FwupdRemote *remote_tmp;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) remotes = NULL;
+ const gchar *remote_id = g_task_get_task_data (task);
+
+ remotes = fwupd_client_get_remotes_finish (FWUPD_CLIENT (source), res, &error);
+ if (remotes == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ remote_tmp = fwupd_client_get_remote_by_id_noref (remotes, remote_id);
+ if (remote_tmp == NULL) {
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "no remote '%s' found in search paths",
+ remote_id);
+ return;
+ }
+
+ /* success */
+ g_task_return_pointer (task,
+ g_object_ref (remote_tmp),
+ (GDestroyNotify) g_object_unref);
+}
+
/**
- * fwupd_client_get_remote_by_id:
- * @client: A #FwupdClient
+ * fwupd_client_get_remote_by_id_async:
+ * @self: A #FwupdClient
* @remote_id: the remote ID, e.g. `lvfs-testing`
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Gets a specific remote that has been configured for the system.
*
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_get_remote_by_id_async (FwupdClient *self,
+ const gchar *remote_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (remote_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* call into daemon */
+ task = g_task_new (self, cancellable, callback, callback_data);
+ g_task_set_task_data (task, g_strdup (remote_id), g_free);
+ fwupd_client_get_remotes_async (self, cancellable,
+ fwupd_client_get_remote_by_id_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * fwupd_client_get_remote_by_id_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_get_remote_by_id_async().
+ *
* Returns: (transfer full): a #FwupdRemote, or %NULL if not found
*
- * Since: 0.9.3
+ * Since: 1.5.0
**/
FwupdRemote *
-fwupd_client_get_remote_by_id (FwupdClient *client,
- const gchar *remote_id,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_get_remote_by_id_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdRemote *remote;
- g_autoptr(GPtrArray) remotes = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (remote_id != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* find remote in list */
- remotes = fwupd_client_get_remotes (client, cancellable, error);
- if (remotes == NULL)
- return NULL;
- remote = fwupd_client_get_remote_by_id_noref (remotes, remote_id);
- if (remote == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_FOUND,
- "No remote '%s' found in search paths",
- remote_id);
- return NULL;
- }
-
- /* success */
- return g_object_ref (remote);
+ return g_task_propagate_pointer (G_TASK(res), error);
}
/**
* fwupd_client_set_user_agent:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
* @user_agent: the user agent ID, e.g. `gnome-software/3.34.1`
*
* Manually sets the user agent that is used for downloading. The user agent
@@ -2272,18 +4240,44 @@
* Since: 1.4.5
**/
void
-fwupd_client_set_user_agent (FwupdClient *client, const gchar *user_agent)
+fwupd_client_set_user_agent (FwupdClient *self, const gchar *user_agent)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- g_return_if_fail (FWUPD_IS_CLIENT (client));
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
g_return_if_fail (user_agent != NULL);
+
+ /* not changed */
+ if (g_strcmp0 (priv->user_agent, user_agent) == 0)
+ return;
+
g_free (priv->user_agent);
priv->user_agent = g_strdup (user_agent);
}
/**
+ * fwupd_client_get_user_agent:
+ * @self: A #FwupdClient
+ *
+ * Gets the string that represents the user agent that is used for
+ * uploading and downloading. The user agent will contain the runtime
+ * version of fwupd somewhere in the provided string.
+ *
+ * Returns: a string, or %NULL for unknown.
+ *
+ * Since: 1.5.2
+ **/
+const gchar *
+fwupd_client_get_user_agent (FwupdClient *self)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ return priv->user_agent;
+}
+
+/**
* fwupd_client_set_user_agent_for_package:
- * @client: A #FwupdClient
+ * @self: A #FwupdClient
* @package_name: client program name, e.g. "gnome-software"
* @package_version: client program version, e.g. "3.28.1"
*
@@ -2300,15 +4294,15 @@
* Since: 1.4.5
**/
void
-fwupd_client_set_user_agent_for_package (FwupdClient *client,
+fwupd_client_set_user_agent_for_package (FwupdClient *self,
const gchar *package_name,
const gchar *package_version)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
GString *str = g_string_new (NULL);
g_autofree gchar *system = NULL;
- g_return_if_fail (FWUPD_IS_CLIENT (client));
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
g_return_if_fail (package_name != NULL);
g_return_if_fail (package_version != NULL);
@@ -2329,203 +4323,471 @@
priv->user_agent = g_string_free (str, FALSE);
}
+#ifdef HAVE_LIBCURL
+static size_t
+fwupd_client_download_write_callback_cb (char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ GByteArray *buf = (GByteArray *) userdata;
+ gsize realsize = size * nmemb;
+ g_byte_array_append (buf, (const guint8 *) ptr, realsize);
+ return realsize;
+}
+
+static GBytes *
+fwupd_client_stream_read_bytes (GInputStream *stream, GError **error)
+{
+ guint8 tmp[0x8000] = { 0x0 };
+ g_autoptr(GByteArray) buf = g_byte_array_new ();
+
+ /* read from stream in 32kB chunks */
+ while (TRUE) {
+ gssize sz;
+ sz = g_input_stream_read (stream, tmp, sizeof(tmp), NULL, error);
+ if (sz == 0)
+ break;
+ if (sz < 0)
+ return NULL;
+ g_byte_array_append (buf, tmp, sz);
+ }
+ return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
+}
+
+static GBytes *
+fwupd_client_download_ipfs (FwupdClient *self, const gchar *url, GError **error)
+{
+ GInputStream *stream = NULL;
+ g_autofree gchar *path = NULL;
+ g_autoptr(GSubprocess) subprocess = NULL;
+
+ /* we get no detailed progess details */
+ fwupd_client_set_status (self, FWUPD_STATUS_DOWNLOADING);
+ fwupd_client_set_percentage (self, 0);
+
+ /* convert from URI to path */
+ if (g_str_has_prefix (url, "ipfs://")) {
+ path = g_strdup_printf ("/ipfs/%s", url + 7);
+ } else if (g_str_has_prefix (url, "ipns://")) {
+ path = g_strdup_printf ("/ipns/%s", url + 7);
+ } else {
+ path = g_strdup (url);
+ }
+
+ /* run sync */
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE,
+ error, "ipfs", "cat", path, NULL);
+ if (subprocess == NULL)
+ return NULL;
+ if (!g_subprocess_wait_check (subprocess, NULL, error))
+ return NULL;
+
+ /* get raw stdout */
+ stream = g_subprocess_get_stdout_pipe (subprocess);
+ return fwupd_client_stream_read_bytes (stream, error);
+}
+
+static GBytes *
+fwupd_client_download_http (FwupdClient *self,
+ CURL *curl,
+ const gchar *url,
+ GError **error)
+{
+ CURLcode res;
+ gchar errbuf[CURL_ERROR_SIZE] = { '\0' };
+ g_autoptr(GByteArray) buf = g_byte_array_new ();
+
+ fwupd_client_set_status (self, FWUPD_STATUS_DOWNLOADING);
+ curl_easy_setopt (curl, CURLOPT_URL, url);
+ curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf);
+ curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, fwupd_client_download_write_callback_cb);
+ curl_easy_setopt (curl, CURLOPT_WRITEDATA, buf);
+ res = curl_easy_perform (curl);
+ fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
+ if (res != CURLE_OK) {
+ glong status_code = 0;
+ curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &status_code);
+ g_debug ("status-code was %ld", status_code);
+ if (status_code == 429) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "Failed to download due to server limit");
+ return NULL;
+ }
+ if (errbuf[0] != '\0') {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "failed to download file: %s",
+ errbuf);
+ return NULL;
+ }
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "failed to download file: %s",
+ curl_easy_strerror (res));
+ return NULL;
+ }
+ return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
+}
static void
-fwupd_client_download_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
+fwupd_client_download_bytes_thread_cb (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ FwupdClient *self = FWUPD_CLIENT (source_object);
+ FwupdCurlHelper *helper = g_task_get_task_data (task);
+ g_autoptr(GBytes) blob = NULL;
+
+ for (guint i = 0; i < helper->urls->len; i++) {
+ const gchar *url = g_ptr_array_index (helper->urls, i);
+ g_autoptr(GError) error = NULL;
+ g_debug ("downloading %s", url);
+ if (fwupd_client_is_url_http (url)) {
+ blob = fwupd_client_download_http (self, helper->curl, url, &error);
+ if (blob != NULL)
+ break;
+ } else if (fwupd_client_is_url_ipfs (url)) {
+ blob = fwupd_client_download_ipfs (self, url, &error);
+ if (blob != NULL)
+ break;
+ } else {
+ g_set_error (&error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "not sure how to handle: %s", url);
+ }
+ if (i == helper->urls->len - 1) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+ fwupd_client_set_percentage (self, 0);
+ fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
+ g_debug ("failed to download %s: %s, trying next URI…",
+ url, error->message);
+ }
+ g_task_return_pointer (task,
+ g_steal_pointer (&blob),
+ (GDestroyNotify) g_bytes_unref);
+}
+#endif
+
+/* private */
+void
+fwupd_client_download_bytes2_async (FwupdClient *self,
+ GPtrArray *urls,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
{
- guint percentage;
- goffset header_size;
- goffset body_length;
- FwupdClient *client = FWUPD_CLIENT (user_data);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+#ifdef HAVE_LIBCURL
+ g_autoptr(GError) error = NULL;
+ g_autoptr(FwupdCurlHelper) helper = NULL;
+#endif
- /* if it's returning "Found" or an error, ignore the percentage */
- if (msg->status_code != SOUP_STATUS_OK) {
- g_debug ("ignoring status code %u (%s)",
- msg->status_code, msg->reason_phrase);
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (urls != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* ensure networking set up */
+ task = g_task_new (self, cancellable, callback, callback_data);
+#ifdef HAVE_LIBCURL
+ helper = fwupd_client_curl_new (self, &error);
+ if (helper == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
return;
}
-
- /* get data */
- body_length = msg->response_body->length;
- header_size = soup_message_headers_get_content_length (msg->response_headers);
- if (header_size < body_length)
+ helper->urls = fwupd_client_filter_locations (urls, flags, &error);
+ if (helper->urls == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
return;
+ }
+ g_task_set_task_data (task, g_steal_pointer (&helper), (GDestroyNotify) fwupd_client_curl_helper_free);
- /* calculate percentage */
- percentage = (guint) ((100 * body_length) / header_size);
- g_debug ("progress: %u%%", percentage);
- fwupd_client_set_status (client, FWUPD_STATUS_DOWNLOADING);
- fwupd_client_set_percentage (client, percentage);
+ /* download data */
+ g_task_run_in_thread (task, fwupd_client_download_bytes_thread_cb);
+#else
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "no libcurl support");
+#endif
}
/**
- * fwupd_client_download_bytes:
- * @client: A #FwupdClient
+ * fwupd_client_download_bytes_async:
+ * @self: A #FwupdClient
* @url: the remote URL
* @flags: #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_NONE
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Downloads data from a remote server. The fwupd_client_set_user_agent() function
* should be called before this method is used.
*
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
+ *
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
+ *
+ * Since: 1.5.0
+ **/
+void
+fwupd_client_download_bytes_async (FwupdClient *self,
+ const gchar *url,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GPtrArray) urls = g_ptr_array_new_with_free_func (g_free);
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (url != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
+
+ /* just proxy */
+ g_ptr_array_add (urls, g_strdup (url));
+ fwupd_client_download_bytes2_async (self, urls, flags, cancellable,
+ callback, callback_data);
+}
+
+/**
+ * fwupd_client_download_bytes_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_download_bytes_async().
+ *
* Returns: (transfer full): downloaded data, or %NULL for error
*
- * Since: 1.4.5
+ * Since: 1.5.0
**/
GBytes *
-fwupd_client_download_bytes (FwupdClient *client,
- const gchar *url,
- FwupdClientDownloadFlags flags,
- GCancellable *cancellable,
- GError **error)
+fwupd_client_download_bytes_finish (FwupdClient *self, GAsyncResult *res, GError **error)
{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- guint status_code;
- g_autoptr(SoupMessage) msg = NULL;
- g_autoptr(SoupURI) uri = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (url != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
- /* ensure networking set up */
- if (!fwupd_client_ensure_networking (client, error))
- return NULL;
-
- /* download data */
- g_debug ("downloading %s", url);
- uri = soup_uri_new (url);
- msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
- if (msg == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to parse URI %s", url);
- return NULL;
- }
- g_signal_connect (msg, "got-chunk",
- G_CALLBACK (fwupd_client_download_chunk_cb),
- client);
- status_code = soup_session_send_message (priv->soup_session, msg);
- fwupd_client_set_status (client, FWUPD_STATUS_IDLE);
- if (status_code == 429) {
- g_autofree gchar *str = g_strndup (msg->response_body->data,
- msg->response_body->length);
- if (g_strcmp0 (str, "Too Many Requests") == 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to download due to server limit");
- return NULL;
+#ifdef HAVE_LIBCURL
+static void
+fwupd_client_upload_bytes_thread_cb (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ FwupdClient *self = FWUPD_CLIENT (source_object);
+ FwupdCurlHelper *helper = g_task_get_task_data (task);
+ CURLcode res;
+ gchar errbuf[CURL_ERROR_SIZE] = { '\0' };
+ g_autoptr(GByteArray) buf = g_byte_array_new ();
+
+ curl_easy_setopt (helper->curl, CURLOPT_ERRORBUFFER, errbuf);
+ curl_easy_setopt (helper->curl, CURLOPT_WRITEFUNCTION, fwupd_client_download_write_callback_cb);
+ curl_easy_setopt (helper->curl, CURLOPT_WRITEDATA, buf);
+ res = curl_easy_perform (helper->curl);
+ fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
+ if (res != CURLE_OK) {
+ glong status_code = 0;
+ curl_easy_getinfo (helper->curl, CURLINFO_RESPONSE_CODE, &status_code);
+ g_debug ("status-code was %ld", status_code);
+ if (errbuf[0] != '\0') {
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "failed to upload file: %s",
+ errbuf);
+ return;
}
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to download due to server limit: %s", str);
- return NULL;
- }
- if (status_code != SOUP_STATUS_OK) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to download %s: %s",
- url, soup_status_get_phrase (status_code));
- return NULL;
- }
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "failed to upload file: %s",
+ curl_easy_strerror (res));
- /* success */
- return g_bytes_new (msg->response_body->data, msg->response_body->length);
+ return;
+ }
+ g_task_return_pointer (task,
+ g_byte_array_free_to_bytes (g_steal_pointer (&buf)),
+ (GDestroyNotify) g_bytes_unref);
}
+#endif
/**
- * fwupd_client_upload_bytes:
- * @client: A #FwupdClient
+ * fwupd_client_upload_bytes_async:
+ * @self: A #FwupdClient
* @url: the remote URL
* @payload: payload string
* @signature: (nullable): signature string
* @flags: #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_NONE
* @cancellable: the #GCancellable, or %NULL
- * @error: the #GError, or %NULL
+ * @callback: the function to run on completion
+ * @callback_data: the data to pass to @callback
*
* Uploads data to a remote server. The fwupd_client_set_user_agent() function
* should be called before this method is used.
*
- * Returns: (transfer full): downloaded data, or %NULL for error
+ * You must have called fwupd_client_connect_async() on @self before using
+ * this method.
*
- * Since: 1.4.5
+ * NOTE: This method is thread-safe, but progress signals will be
+ * emitted in the global default main context, if not explicitly set with
+ * fwupd_client_set_main_context().
+ *
+ * Since: 1.5.0
**/
-GBytes *
-fwupd_client_upload_bytes (FwupdClient *client,
- const gchar *url,
- const gchar *payload,
- const gchar *signature,
- FwupdClientUploadFlags flags,
- GCancellable *cancellable,
- GError **error)
-{
- FwupdClientPrivate *priv = GET_PRIVATE (client);
- guint status_code;
- g_autoptr(SoupMessage) msg = NULL;
- g_autoptr(SoupURI) uri = NULL;
-
- g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
- g_return_val_if_fail (url != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+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)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GTask) task = NULL;
+#ifdef HAVE_LIBCURL
+ g_autoptr(FwupdCurlHelper) helper = NULL;
+ g_autoptr(GError) error = NULL;
+#endif
+
+ g_return_if_fail (FWUPD_IS_CLIENT (self));
+ g_return_if_fail (url != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (priv->proxy != NULL);
/* ensure networking set up */
- if (!fwupd_client_ensure_networking (client, error))
- return NULL;
+ task = g_task_new (self, cancellable, callback, callback_data);
+#ifdef HAVE_LIBCURL
+ helper = fwupd_client_curl_new (self, &error);
+ if (helper == NULL) {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
/* build message */
- if ((flags | FWUPD_CLIENT_UPLOAD_FLAG_ALWAYS_MULTIPART) > 0 ||
+ if ((flags & FWUPD_CLIENT_UPLOAD_FLAG_ALWAYS_MULTIPART) > 0 ||
signature != NULL) {
- g_autoptr(SoupMultipart) mp = NULL;
- mp = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
- soup_multipart_append_form_string (mp, "payload", payload);
- if (signature != NULL)
- soup_multipart_append_form_string (mp, "signature", signature);
- msg = soup_form_request_new_from_multipart (url, mp);
+ curl_mimepart *part;
+ helper->mime = curl_mime_init (helper->curl);
+ curl_easy_setopt (helper->curl, CURLOPT_MIMEPOST, helper->mime);
+ part = curl_mime_addpart (helper->mime);
+ curl_mime_data (part, payload, CURL_ZERO_TERMINATED);
+ curl_mime_name (part, "payload");
+ if (signature != NULL) {
+ part = curl_mime_addpart (helper->mime);
+ curl_mime_data (part, signature, CURL_ZERO_TERMINATED);
+ curl_mime_name (part, "signature");
+ }
} else {
- msg = soup_message_new (SOUP_METHOD_POST, url);
- soup_message_set_request (msg, "application/json; charset=utf-8",
- SOUP_MEMORY_COPY, payload, strlen (payload));
+ helper->headers = curl_slist_append (helper->headers, "Content-Type: text/plain");
+ curl_easy_setopt (helper->curl, CURLOPT_HTTPHEADER, helper->headers);
+ curl_easy_setopt (helper->curl, CURLOPT_POST, 1L);
+ curl_easy_setopt (helper->curl, CURLOPT_POSTFIELDSIZE, strlen (payload));
+ curl_easy_setopt (helper->curl, CURLOPT_COPYPOSTFIELDS, payload);
}
- /* POST request */
- if (msg == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to parse URI %s", url);
- return NULL;
- }
+ fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
g_debug ("uploading to %s", url);
- status_code = soup_session_send_message (priv->soup_session, msg);
- g_debug ("server returned: %s", msg->response_body->data);
+ curl_easy_setopt (helper->curl, CURLOPT_URL, url);
+ g_task_set_task_data (task, g_steal_pointer (&helper), (GDestroyNotify) fwupd_client_curl_helper_free);
+ g_task_run_in_thread (task, fwupd_client_upload_bytes_thread_cb);
+#else
+ g_task_return_new_error (task,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "no libcurl support");
+#endif
+}
- /* fall back to HTTP status codes in case the server is offline */
- if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to upllooad to %s: %s",
- url, soup_status_get_phrase (status_code));
- return NULL;
+/**
+ * fwupd_client_upload_bytes_finish:
+ * @self: A #FwupdClient
+ * @res: the #GAsyncResult
+ * @error: the #GError, or %NULL
+ *
+ * Gets the result of fwupd_client_upload_bytes_async().
+ *
+ * Returns: (transfer full): response data, or %NULL for error
+ *
+ * Since: 1.5.0
+ **/
+GBytes *
+fwupd_client_upload_bytes_finish (FwupdClient *self, GAsyncResult *res, GError **error)
+{
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK(res), error);
+}
+
+#ifdef SOUP_SESSION_COMPAT
+/* this is bad; we dlopen libsoup-2.4.so.1 and get the gtype manually
+ * to avoid deps on both libcurl and libsoup whilst preserving ABI */
+static void
+fwupd_client_ensure_soup_session (FwupdClient *self)
+{
+ FwupdClientObjectNewFunc func = NULL;
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ GType soup_gtype;
+
+ /* already set up */
+ if (priv->soup_session != NULL)
+ return;
+
+ /* known GType, just create */
+ soup_gtype = g_type_from_name ("SoupSession");
+ if (soup_gtype != 0) {
+ priv->soup_session = g_object_new (soup_gtype, NULL);
+ return;
}
- /* success */
- return g_bytes_new (msg->response_body->data, msg->response_body->length);
+ /* load the library at runtime, leaking the module */
+ if (priv->soup_module == NULL) {
+ g_autofree gchar *fn = NULL;
+ fn = g_build_filename (FWUPD_LIBDIR, "libsoup-2.4.so.1", NULL);
+ priv->soup_module = g_module_open (fn, G_MODULE_BIND_LAZY);
+ if (priv->soup_module == NULL) {
+ g_warning ("failed to find libsoup library");
+ return;
+ }
+ }
+ if (!g_module_symbol (priv->soup_module,
+ "soup_session_new",
+ (gpointer *) &func)) {
+ g_warning ("failed to find soup_session_get_type()");
+ g_module_close (priv->soup_module);
+ priv->soup_module = NULL;
+ return;
+ }
+ priv->soup_session = func ();
+ g_object_set (priv->soup_session, "timeout", (guint) 60, NULL);
}
+#endif
static void
fwupd_client_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
- FwupdClient *client = FWUPD_CLIENT (object);
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClient *self = FWUPD_CLIENT (object);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
switch (prop_id) {
case PROP_STATUS:
@@ -2535,7 +4797,12 @@
g_value_set_boolean (value, priv->tainted);
break;
case PROP_SOUP_SESSION:
+#ifdef SOUP_SESSION_COMPAT
+ fwupd_client_ensure_soup_session (self);
g_value_set_object (value, priv->soup_session);
+#else
+ g_value_set_object (value, NULL);
+#endif
break;
case PROP_PERCENTAGE:
g_value_set_uint (value, priv->percentage);
@@ -2549,6 +4816,9 @@
case PROP_HOST_MACHINE_ID:
g_value_set_string (value, priv->host_machine_id);
break;
+ case PROP_HOST_SECURITY_ID:
+ g_value_set_string (value, priv->host_security_id);
+ break;
case PROP_INTERACTIVE:
g_value_set_boolean (value, priv->interactive);
break;
@@ -2562,8 +4832,8 @@
fwupd_client_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
- FwupdClient *client = FWUPD_CLIENT (object);
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClient *self = FWUPD_CLIENT (object);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
switch (prop_id) {
case PROP_STATUS:
@@ -2572,9 +4842,6 @@
case PROP_PERCENTAGE:
priv->percentage = g_value_get_uint (value);
break;
- case PROP_SOUP_SESSION:
- g_set_object (&priv->soup_session, g_value_get_object (value));
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2592,7 +4859,7 @@
/**
* FwupdClient::changed:
- * @client: the #FwupdClient instance that emitted the signal
+ * @self: the #FwupdClient instance that emitted the signal
*
* The ::changed signal is emitted when the daemon internal has
* changed, for instance when a device has been added or removed.
@@ -2608,7 +4875,7 @@
/**
* FwupdClient::state-changed:
- * @client: the #FwupdClient instance that emitted the signal
+ * @self: the #FwupdClient instance that emitted the signal
* @status: the #FwupdStatus
*
* The ::state-changed signal is emitted when the daemon status has
@@ -2625,7 +4892,7 @@
/**
* FwupdClient::device-added:
- * @client: the #FwupdClient instance that emitted the signal
+ * @self: the #FwupdClient instance that emitted the signal
* @result: the #FwupdDevice
*
* The ::device-added signal is emitted when a device has been
@@ -2642,7 +4909,7 @@
/**
* FwupdClient::device-removed:
- * @client: the #FwupdClient instance that emitted the signal
+ * @self: the #FwupdClient instance that emitted the signal
* @result: the #FwupdDevice
*
* The ::device-removed signal is emitted when a device has been
@@ -2659,7 +4926,7 @@
/**
* FwupdClient::device-changed:
- * @client: the #FwupdClient instance that emitted the signal
+ * @self: the #FwupdClient instance that emitted the signal
* @result: the #FwupdDevice
*
* The ::device-changed signal is emitted when a device has been
@@ -2734,12 +5001,12 @@
/**
* FwupdClient:soup-session:
*
- * The libsoup session.
+ * The libsoup session, now unused.
*
* Since: 1.4.5
*/
- pspec = g_param_spec_object ("soup-session", NULL, NULL, SOUP_TYPE_SESSION,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
+ pspec = g_param_spec_object ("soup-session", NULL, NULL, G_TYPE_OBJECT,
+ G_PARAM_READABLE | G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_SOUP_SESSION, pspec);
/**
@@ -2763,29 +5030,51 @@
pspec = g_param_spec_string ("host-machine-id", NULL, NULL,
NULL, G_PARAM_READABLE | G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_HOST_MACHINE_ID, pspec);
+
+ /**
+ * FwupdClient:host-security-id:
+ *
+ * The host machine-id string
+ *
+ * Since: 1.5.0
+ */
+ pspec = g_param_spec_string ("host-security-id", NULL, NULL,
+ NULL, G_PARAM_READABLE | G_PARAM_STATIC_NAME);
+ g_object_class_install_property (object_class, PROP_HOST_SECURITY_ID, pspec);
}
static void
-fwupd_client_init (FwupdClient *client)
+fwupd_client_init (FwupdClient *self)
{
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_mutex_init (&priv->proxy_mutex);
+ g_mutex_init (&priv->idle_mutex);
+ priv->idle_sources = g_ptr_array_new_with_free_func ((GDestroyNotify) fwupd_client_context_helper_free);
}
static void
fwupd_client_finalize (GObject *object)
{
- FwupdClient *client = FWUPD_CLIENT (object);
- FwupdClientPrivate *priv = GET_PRIVATE (client);
+ FwupdClient *self = FWUPD_CLIENT (object);
+ FwupdClientPrivate *priv = GET_PRIVATE (self);
+ g_clear_pointer (&priv->main_ctx, g_main_context_unref);
g_free (priv->user_agent);
g_free (priv->daemon_version);
g_free (priv->host_product);
g_free (priv->host_machine_id);
- if (priv->conn != NULL)
- g_object_unref (priv->conn);
+ g_free (priv->host_security_id);
+ g_mutex_clear (&priv->idle_mutex);
+ if (priv->idle_id != 0)
+ g_source_remove (priv->idle_id);
+ g_ptr_array_unref (priv->idle_sources);
+ g_mutex_clear (&priv->proxy_mutex);
if (priv->proxy != NULL)
g_object_unref (priv->proxy);
+#ifdef SOUP_SESSION_COMPAT
if (priv->soup_session != NULL)
g_object_unref (priv->soup_session);
+#endif
G_OBJECT_CLASS (fwupd_client_parent_class)->finalize (object);
}
@@ -2802,7 +5091,7 @@
FwupdClient *
fwupd_client_new (void)
{
- FwupdClient *client;
- client = g_object_new (FWUPD_TYPE_CLIENT, NULL);
- return FWUPD_CLIENT (client);
+ FwupdClient *self;
+ self = g_object_new (FWUPD_TYPE_CLIENT, NULL);
+ return FWUPD_CLIENT (self);
}
diff -Nru fwupd-1.4.5/libfwupd/fwupd-client.h fwupd-1.5.8/libfwupd/fwupd-client.h
--- fwupd-1.4.5/libfwupd/fwupd-client.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-client.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2018 Richard Hughes
+ * Copyright (C) 2016 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -11,6 +11,7 @@
#include "fwupd-enums.h"
#include "fwupd-device.h"
+#include "fwupd-plugin.h"
#include "fwupd-remote.h"
G_BEGIN_DECLS
@@ -43,11 +44,13 @@
/**
* FwupdClientDownloadFlags:
* @FWUPD_CLIENT_DOWNLOAD_FLAG_NONE: No flags set
+ * @FWUPD_CLIENT_DOWNLOAD_FLAG_ONLY_IPFS: Only use IPFS when downloading URIs
*
* The options to use for downloading.
**/
typedef enum {
FWUPD_CLIENT_DOWNLOAD_FLAG_NONE = 0, /* Since: 1.4.5 */
+ FWUPD_CLIENT_DOWNLOAD_FLAG_ONLY_IPFS = 1 << 0, /* Since: 1.5.6 */
/*< private >*/
FWUPD_CLIENT_DOWNLOAD_FLAG_LAST
} FwupdClientDownloadFlags;
@@ -67,164 +70,369 @@
} FwupdClientUploadFlags;
FwupdClient *fwupd_client_new (void);
-gboolean fwupd_client_connect (FwupdClient *client,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_devices (FwupdClient *client,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_history (FwupdClient *client,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_releases (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_downgrades (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_upgrades (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_details (FwupdClient *client,
- const gchar *filename,
- GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_verify (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_verify_update (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_unlock (FwupdClient *client,
- const gchar *device_id,
+GMainContext *fwupd_client_get_main_context (FwupdClient *self);
+void fwupd_client_set_main_context (FwupdClient *self,
+ GMainContext *main_ctx);
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_get_details_bytes_async (FwupdClient *self,
+ GBytes *bytes,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_modify_config (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+GPtrArray *fwupd_client_get_details_bytes_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_modify_config_async (FwupdClient *self,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_activate (FwupdClient *client,
- GCancellable *cancellable,
- const gchar *device_id,
- GError **error);
-gboolean fwupd_client_clear_results (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-FwupdDevice *fwupd_client_get_results (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-FwupdDevice *fwupd_client_get_device_by_id (FwupdClient *client,
- const gchar *device_id,
- GCancellable *cancellable,
- GError **error);
-GPtrArray *fwupd_client_get_devices_by_guid (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_modify_config_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_get_devices_by_guid_async (FwupdClient *self,
const gchar *guid,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_install (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+GPtrArray *fwupd_client_get_devices_by_guid_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_install_async (FwupdClient *self,
const gchar *device_id,
const gchar *filename,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_install_bytes (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_install_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_install_bytes_async (FwupdClient *self,
const gchar *device_id,
GBytes *bytes,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_install_release (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_install_bytes_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_install_release_async (FwupdClient *self,
FwupdDevice *device,
FwupdRelease *release,
FwupdInstallFlags install_flags,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_update_metadata (FwupdClient *client,
- const gchar *remote_id,
- const gchar *metadata_fn,
- const gchar *signature_fn,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+G_DEPRECATED_FOR(fwupd_client_install_release2_async);
+void fwupd_client_install_release2_async (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ FwupdClientDownloadFlags download_flags,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_update_metadata_bytes (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_install_release_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_update_metadata_bytes_async (FwupdClient *self,
const gchar *remote_id,
GBytes *metadata,
GBytes *signature,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_refresh_remote (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_update_metadata_bytes_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_refresh_remote_async (FwupdClient *self,
FwupdRemote *remote,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_modify_remote (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_refresh_remote_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_modify_remote_async (FwupdClient *self,
const gchar *remote_id,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_modify_device (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_modify_remote_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_modify_device_async (FwupdClient *self,
const gchar *device_id,
const gchar *key,
const gchar *value,
GCancellable *cancellable,
- 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,
- GCancellable *cancellable,
- GError **error);
-FwupdRemote *fwupd_client_get_remote_by_id (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_modify_device_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_get_remote_by_id_async (FwupdClient *self,
const gchar *remote_id,
GCancellable *cancellable,
- GError **error);
-
-gchar **fwupd_client_get_approved_firmware (FwupdClient *client,
- GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_set_approved_firmware (FwupdClient *client,
- gchar **checksums,
- GCancellable *cancellable,
- GError **error);
-gchar *fwupd_client_self_sign (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+FwupdRemote *fwupd_client_get_remote_by_id_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+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)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_self_sign_async (FwupdClient *self,
const gchar *value,
FwupdSelfSignFlags flags,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_set_feature_flags (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gchar *fwupd_client_self_sign_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_set_feature_flags_async (FwupdClient *self,
FwupdFeatureFlags feature_flags,
GCancellable *cancellable,
- GError **error);
-void fwupd_client_set_user_agent (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean fwupd_client_set_feature_flags_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+const gchar *fwupd_client_get_user_agent (FwupdClient *self);
+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,
- GError **error);
-GBytes *fwupd_client_upload_bytes (FwupdClient *client,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+GBytes *fwupd_client_download_bytes_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fwupd_client_upload_bytes_async (FwupdClient *self,
const gchar *url,
const gchar *payload,
const gchar *signature,
FwupdClientUploadFlags flags,
GCancellable *cancellable,
- GError **error);
-gboolean fwupd_client_ensure_networking (FwupdClient *client,
- GError **error);
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+GBytes *fwupd_client_upload_bytes_finish (FwupdClient *self,
+ GAsyncResult *res,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_ensure_networking (FwupdClient *self,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
G_END_DECLS
diff -Nru fwupd-1.4.5/libfwupd/fwupd-client-private.h fwupd-1.5.8/libfwupd/fwupd-client-private.h
--- fwupd-1.4.5/libfwupd/fwupd-client-private.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-client-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fwupd-client.h"
+
+#ifdef HAVE_GIO_UNIX
+#include
+#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);
+void fwupd_client_download_bytes2_async (FwupdClient *self,
+ GPtrArray *urls,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+#endif
diff -Nru fwupd-1.4.5/libfwupd/fwupd-client-sync.c fwupd-1.5.8/libfwupd/fwupd-client-sync.c
--- fwupd-1.4.5/libfwupd/fwupd-client-sync.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-client-sync.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,2181 @@
+/*
+ * Copyright (C) 2016 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#ifdef HAVE_GIO_UNIX
+#include
+#endif
+
+#include "fwupd-client.h"
+#include "fwupd-client-private.h"
+#include "fwupd-client-sync.h"
+#include "fwupd-common-private.h"
+#include "fwupd-error.h"
+
+typedef struct {
+ gboolean ret;
+ gchar *str;
+ GError *error;
+ GPtrArray *array;
+ GMainContext *context;
+ GMainLoop *loop;
+ GVariant *val;
+ GHashTable *hash;
+ GBytes *bytes;
+ FwupdDevice *device;
+} FwupdClientHelper;
+
+static void
+fwupd_client_helper_free (FwupdClientHelper *helper)
+{
+ if (helper->val != NULL)
+ g_variant_unref (helper->val);
+ if (helper->error != NULL)
+ g_error_free (helper->error);
+ if (helper->array != NULL)
+ g_ptr_array_unref (helper->array);
+ if (helper->hash != NULL)
+ g_hash_table_unref (helper->hash);
+ if (helper->bytes != NULL)
+ g_bytes_unref (helper->bytes);
+ if (helper->device != NULL)
+ g_object_unref (helper->device);
+ g_free (helper->str);
+ g_main_loop_unref (helper->loop);
+ g_main_context_unref (helper->context);
+ g_main_context_pop_thread_default (helper->context);
+ g_free (helper);
+}
+
+static FwupdClientHelper *
+fwupd_client_helper_new (FwupdClient *self)
+{
+ FwupdClientHelper *helper;
+ helper = g_new0 (FwupdClientHelper, 1);
+ helper->context = fwupd_client_get_main_context (self);
+ helper->loop = g_main_loop_new (helper->context, FALSE);
+ g_main_context_push_thread_default (helper->context);
+ return helper;
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(FwupdClientHelper, fwupd_client_helper_free)
+#pragma clang diagnostic pop
+
+static void
+fwupd_client_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_connect_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_connect:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Sets up the client ready for use. Most other methods call this
+ * for you, and do you only need to call this if you are just watching
+ * the client.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.7.1
+ **/
+gboolean
+fwupd_client_connect (FwupdClient *self, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_connect_async (self, cancellable, fwupd_client_connect_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_get_devices_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_devices_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_devices:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the devices registered with the daemon.
+ *
+ * Returns: (element-type FwupdDevice) (transfer container): results
+ *
+ * Since: 0.9.2
+ **/
+GPtrArray *
+fwupd_client_get_devices (FwupdClient *self, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_devices_async (self, cancellable,
+ fwupd_client_get_devices_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_plugins_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_plugins_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_plugins:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the plugins being used the daemon.
+ *
+ * Returns: (element-type FwupdPlugin) (transfer container): results
+ *
+ * Since: 1.5.0
+ **/
+GPtrArray *
+fwupd_client_get_plugins (FwupdClient *self, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_plugins_async (self, cancellable,
+ fwupd_client_get_plugins_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_history_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_history_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_history:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the history.
+ *
+ * Returns: (element-type FwupdDevice) (transfer container): results
+ *
+ * Since: 1.0.4
+ **/
+GPtrArray *
+fwupd_client_get_history (FwupdClient *self, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_history_async (self, cancellable,
+ fwupd_client_get_history_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_releases_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_releases_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_releases:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the releases for a specific device
+ *
+ * Returns: (element-type FwupdRelease) (transfer container): results
+ *
+ * Since: 0.9.3
+ **/
+GPtrArray *
+fwupd_client_get_releases (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (device_id != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_releases_async (self, device_id, cancellable,
+ fwupd_client_get_releases_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_downgrades_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_downgrades_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_downgrades:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the downgrades for a specific device.
+ *
+ * Returns: (element-type FwupdRelease) (transfer container): results
+ *
+ * Since: 0.9.8
+ **/
+GPtrArray *
+fwupd_client_get_downgrades (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (device_id != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_downgrades_async (self, device_id, cancellable,
+ fwupd_client_get_downgrades_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_upgrades_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_upgrades_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_upgrades:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the upgrades for a specific device.
+ *
+ * Returns: (element-type FwupdRelease) (transfer container): results
+ *
+ * Since: 0.9.8
+ **/
+GPtrArray *
+fwupd_client_get_upgrades (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (device_id != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_upgrades_async (self, device_id, cancellable,
+ fwupd_client_get_upgrades_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_details_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_details_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_details_bytes:
+ * @self: A #FwupdClient
+ * @bytes: the firmware blob, e.g. the contents of `firmware.cab`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets details about a specific firmware file.
+ *
+ * Returns: (transfer container) (element-type FwupdDevice): an array of results
+ *
+ * Since: 1.5.0
+ **/
+GPtrArray *
+fwupd_client_get_details_bytes (FwupdClient *self,
+ GBytes *bytes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (bytes != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_details_bytes_async (self, bytes,
+ cancellable,
+ fwupd_client_get_details_bytes_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+#ifdef HAVE_GIO_UNIX
+static void
+fwupd_client_get_details_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_details_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+#endif
+
+/**
+ * fwupd_client_get_details:
+ * @self: A #FwupdClient
+ * @filename: the firmware filename, e.g. `firmware.cab`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets details about a specific firmware file.
+ *
+ * Returns: (transfer container) (element-type FwupdDevice): an array of results
+ *
+ * Since: 1.0.0
+ **/
+GPtrArray *
+fwupd_client_get_details (FwupdClient *self,
+ const gchar *filename,
+ GCancellable *cancellable,
+ GError **error)
+{
+#ifdef HAVE_GIO_UNIX
+ g_autoptr(GUnixInputStream) istr = NULL;
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ istr = fwupd_unix_input_stream_from_fn (filename, error);
+ if (istr == NULL)
+ return NULL;
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_details_stream_async (self, istr, cancellable,
+ fwupd_client_get_details_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+#else
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
+ return NULL;
+#endif
+}
+
+static void
+fwupd_client_verify_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_verify_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_verify:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Verify a specific device.
+ *
+ * Returns: %TRUE for verification success
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+fwupd_client_verify (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_verify_async (self, device_id, cancellable,
+ fwupd_client_verify_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_verify_update_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_verify_update_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_verify_update:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Update the verification record for a specific device.
+ *
+ * Returns: %TRUE for verification success
+ *
+ * Since: 0.8.0
+ **/
+gboolean
+fwupd_client_verify_update (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_verify_update_async (self, device_id, cancellable,
+ fwupd_client_verify_update_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_unlock_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_unlock_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_unlock:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Unlocks a specific device so firmware can be read or wrote.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+fwupd_client_unlock (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_unlock_async (self, device_id, cancellable,
+ fwupd_client_unlock_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+static void
+fwupd_client_modify_config_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_modify_config_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_modify_config
+ * @self: A #FwupdClient
+ * @key: key, e.g. `DisabledPlugins`
+ * @value: value, e.g. `*`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Modifies a daemon config option.
+ * The daemon will only respond to this request with proper permissions
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.2.8
+ **/
+gboolean
+fwupd_client_modify_config (FwupdClient *self,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_modify_config_async (self, key, value,
+ cancellable,
+ fwupd_client_modify_config_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_activate_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_activate_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_activate:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @device_id: a device
+ * @error: the #GError, or %NULL
+ *
+ * Activates up a device, which normally means the device switches to a new
+ * firmware version. This should only be called when data loss cannot occur.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.2.6
+ **/
+gboolean
+fwupd_client_activate (FwupdClient *self,
+ GCancellable *cancellable,
+ const gchar *device_id, /* yes, this is the wrong way around :/ */
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_activate_async (self, device_id,
+ cancellable,
+ fwupd_client_activate_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_clear_results_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_clear_results_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_clear_results:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Clears the results for a specific device.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+fwupd_client_clear_results (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_clear_results_async (self, device_id,
+ cancellable,
+ fwupd_client_clear_results_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_get_results_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->device = fwupd_client_get_results_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_results:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets the results of a previous firmware update for a specific device.
+ *
+ * Returns: (transfer full): a #FwupdDevice, or %NULL for failure
+ *
+ * Since: 0.7.0
+ **/
+FwupdDevice *
+fwupd_client_get_results (FwupdClient *self, const gchar *device_id,
+ GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (device_id != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_results_async (self, device_id, cancellable,
+ fwupd_client_get_results_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->device == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->device);
+}
+
+static void
+fwupd_client_get_host_security_attrs_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_host_security_attrs_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_host_security_attrs:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the host security attributes from the daemon.
+ *
+ * Returns: (element-type FwupdSecurityAttr) (transfer container): attributes
+ *
+ * Since: 1.5.0
+ **/
+GPtrArray *
+fwupd_client_get_host_security_attrs (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_host_security_attrs_async (self, cancellable,
+ fwupd_client_get_host_security_attrs_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static void
+fwupd_client_get_device_by_id_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->device = fwupd_client_get_device_by_id_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_device_by_id:
+ * @self: A #FwupdClient
+ * @device_id: the device ID, e.g. `usb:00:01:03:03`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets a device by it's device ID.
+ *
+ * Returns: (transfer full): a #FwupdDevice or %NULL
+ *
+ * Since: 0.9.3
+ **/
+FwupdDevice *
+fwupd_client_get_device_by_id (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (device_id != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_device_by_id_async (self, device_id, cancellable,
+ fwupd_client_get_device_by_id_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->device == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->device);
+}
+
+static void
+fwupd_client_get_devices_by_guid_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_devices_by_guid_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_devices_by_guid:
+ * @self: A #FwupdClient
+ * @guid: the GUID, e.g. `e22c4520-43dc-5bb3-8245-5787fead9b63`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets any devices that provide a specific GUID. An error is returned if no
+ * devices contains this GUID.
+ *
+ * Returns: (element-type FwupdDevice) (transfer container): devices or %NULL
+ *
+ * Since: 1.4.1
+ **/
+GPtrArray *
+fwupd_client_get_devices_by_guid (FwupdClient *self, const gchar *guid,
+ GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (guid != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_devices_by_guid_async (self, guid, cancellable,
+ fwupd_client_get_devices_by_guid_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+#ifdef HAVE_GIO_UNIX
+static void
+fwupd_client_install_fd_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_install_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+#endif
+
+/**
+ * fwupd_client_install:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @filename: the filename to install
+ * @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Install a file onto a specific device.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+fwupd_client_install (FwupdClient *self,
+ const gchar *device_id,
+ const gchar *filename,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+#ifdef HAVE_GIO_UNIX
+ g_autoptr(GUnixInputStream) istr = NULL;
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* move to a thread if this ever takes more than a few ms */
+ istr = fwupd_unix_input_stream_from_fn (filename, error);
+ if (istr == NULL)
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_install_stream_async (self, device_id, istr, filename,
+ install_flags, cancellable,
+ fwupd_client_install_fd_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+#else
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
+ return FALSE;
+#endif
+}
+
+static void
+fwupd_client_install_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_install_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_install_bytes:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @bytes: #GBytes
+ * @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Install firmware onto a specific device.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.5
+ **/
+gboolean
+fwupd_client_install_bytes (FwupdClient *self,
+ const gchar *device_id,
+ GBytes *bytes,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (bytes != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_install_bytes_async (self, device_id, bytes, install_flags,
+ cancellable,
+ fwupd_client_install_bytes_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+static void
+fwupd_client_install_release_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_install_release_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_install_release2:
+ * @self: A #FwupdClient
+ * @device: A #FwupdDevice
+ * @release: A #FwupdRelease
+ * @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
+ * @download_flags: the #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_NONE
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Installs a new release on a device, downloading the firmware if required.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fwupd_client_install_release2 (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ FwupdClientDownloadFlags download_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (FWUPD_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (FWUPD_IS_RELEASE (release), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_install_release2_async (self, device, release,
+ install_flags, download_flags,
+ cancellable,
+ fwupd_client_install_release_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * fwupd_client_install_release:
+ * @self: A #FwupdClient
+ * @device: A #FwupdDevice
+ * @release: A #FwupdRelease
+ * @install_flags: the #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_REINSTALL
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Installs a new release on a device, downloading the firmware if required.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.5
+ * Deprecated: 1.5.6
+ **/
+gboolean
+fwupd_client_install_release (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return fwupd_client_install_release2 (self, device, release, install_flags,
+ FWUPD_CLIENT_DOWNLOAD_FLAG_NONE,
+ cancellable, error);
+}
+
+#ifdef HAVE_GIO_UNIX
+static void
+fwupd_client_update_metadata_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_update_metadata_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+#endif
+
+/**
+ * fwupd_client_update_metadata:
+ * @self: A #FwupdClient
+ * @remote_id: the remote ID, e.g. `lvfs-testing`
+ * @metadata_fn: the XML metadata filename
+ * @signature_fn: the GPG signature file
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Updates the metadata. This allows a session process to download the metadata
+ * and metadata signing file to be passed into the daemon to be checked and
+ * parsed.
+ *
+ * The @remote_id allows the firmware to be tagged so that the remote can be
+ * matched when the firmware is downloaded.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.0.0
+ **/
+gboolean
+fwupd_client_update_metadata (FwupdClient *self,
+ const gchar *remote_id,
+ const gchar *metadata_fn,
+ const gchar *signature_fn,
+ GCancellable *cancellable,
+ GError **error)
+{
+#ifdef HAVE_GIO_UNIX
+ g_autoptr(GUnixInputStream) istr = NULL;
+ g_autoptr(GUnixInputStream) istr_sig = NULL;
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (remote_id != NULL, FALSE);
+ g_return_val_if_fail (metadata_fn != NULL, FALSE);
+ g_return_val_if_fail (signature_fn != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ istr = fwupd_unix_input_stream_from_fn (metadata_fn, error);
+ if (istr == NULL)
+ return FALSE;
+ istr_sig = fwupd_unix_input_stream_from_fn (signature_fn, error);
+ if (istr_sig == NULL)
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_update_metadata_stream_async (self, remote_id, istr, istr_sig, cancellable,
+ fwupd_client_update_metadata_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+#else
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "Not supported as is unavailable");
+ return FALSE;
+#endif
+}
+
+static void
+fwupd_client_update_metadata_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_update_metadata_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_update_metadata_bytes:
+ * @self: A #FwupdClient
+ * @remote_id: remote ID, e.g. `lvfs-testing`
+ * @metadata: XML metadata data
+ * @signature: signature data
+ * @cancellable: #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Updates the metadata. This allows a session process to download the metadata
+ * and metadata signing file to be passed into the daemon to be checked and
+ * parsed.
+ *
+ * The @remote_id allows the firmware to be tagged so that the remote can be
+ * matched when the firmware is downloaded.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.5
+ **/
+gboolean
+fwupd_client_update_metadata_bytes (FwupdClient *self,
+ const gchar *remote_id,
+ GBytes *metadata,
+ GBytes *signature,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (remote_id != NULL, FALSE);
+ g_return_val_if_fail (metadata != NULL, FALSE);
+ g_return_val_if_fail (signature != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_update_metadata_bytes_async (self, remote_id, metadata, signature,
+ cancellable,
+ fwupd_client_update_metadata_bytes_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_refresh_remote_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_refresh_remote_finish (FWUPD_CLIENT (source),
+ res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_refresh_remote:
+ * @self: A #FwupdClient
+ * @remote: A #FwupdRemote
+ * @cancellable: A #GCancellable, or %NULL
+ * @error: A #GError, or %NULL
+ *
+ * Refreshes a remote by downloading new metadata.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.5
+ **/
+gboolean
+fwupd_client_refresh_remote (FwupdClient *self,
+ FwupdRemote *remote,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (FWUPD_IS_REMOTE (remote), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_refresh_remote_async (self, remote, cancellable,
+ fwupd_client_refresh_remote_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_modify_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_modify_remote_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_modify_remote:
+ * @self: A #FwupdClient
+ * @remote_id: the remote ID, e.g. `lvfs-testing`
+ * @key: the key, e.g. `Enabled`
+ * @value: the key, e.g. `true`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Modifies a system remote in a specific way.
+ *
+ * NOTE: User authentication may be required to complete this action.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.9.8
+ **/
+gboolean
+fwupd_client_modify_remote (FwupdClient *self,
+ const gchar *remote_id,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (remote_id != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_modify_remote_async (self, remote_id, key, value,
+ cancellable,
+ fwupd_client_modify_remote_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_get_report_metadata_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->hash = fwupd_client_get_report_metadata_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_report_metadata:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets all the report metadata from the daemon.
+ *
+ * Returns: (transfer container): attributes
+ *
+ * Since: 1.5.0
+ **/
+GHashTable *
+fwupd_client_get_report_metadata (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_report_metadata_async (self, cancellable,
+ fwupd_client_get_report_metadata_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->hash == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->hash);
+}
+
+static void
+fwupd_client_modify_device_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_modify_device_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_modify_device:
+ * @self: A #FwupdClient
+ * @device_id: the device ID
+ * @key: the key, e.g. `Flags`
+ * @value: the key, e.g. `reported`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Modifies a device in a specific way. Not all properties on the #FwupdDevice
+ * are settable by the client, and some may have other restrictions on @value.
+ *
+ * NOTE: User authentication may be required to complete this action.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.0.4
+ **/
+gboolean
+fwupd_client_modify_device (FwupdClient *self,
+ const gchar *device_id,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (device_id != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_modify_device_async (self, device_id, key, value,
+ cancellable,
+ fwupd_client_modify_device_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_get_remotes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_remotes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_remotes:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets the list of remotes that have been configured for the system.
+ *
+ * Returns: (element-type FwupdRemote) (transfer container): list of remotes, or %NULL
+ *
+ * Since: 0.9.3
+ **/
+GPtrArray *
+fwupd_client_get_remotes (FwupdClient *self, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_remotes_async (self, cancellable,
+ fwupd_client_get_remotes_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->array);
+}
+
+static FwupdRemote *
+fwupd_client_get_remote_by_id_noref (GPtrArray *remotes, const gchar *remote_id)
+{
+ for (guint i = 0; i < remotes->len; i++) {
+ FwupdRemote *remote = g_ptr_array_index (remotes, i);
+ if (g_strcmp0 (remote_id, fwupd_remote_get_id (remote)) == 0)
+ return remote;
+ }
+ return NULL;
+}
+
+/**
+ * fwupd_client_get_remote_by_id:
+ * @self: A #FwupdClient
+ * @remote_id: the remote ID, e.g. `lvfs-testing`
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets a specific remote that has been configured for the system.
+ *
+ * Returns: (transfer full): a #FwupdRemote, or %NULL if not found
+ *
+ * Since: 0.9.3
+ **/
+FwupdRemote *
+fwupd_client_get_remote_by_id (FwupdClient *self,
+ const gchar *remote_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ FwupdRemote *remote;
+ g_autoptr(GPtrArray) remotes = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (remote_id != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* find remote in list */
+ remotes = fwupd_client_get_remotes (self, cancellable, error);
+ if (remotes == NULL)
+ return NULL;
+ remote = fwupd_client_get_remote_by_id_noref (remotes, remote_id);
+ if (remote == NULL) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "No remote '%s' found in search paths",
+ remote_id);
+ return NULL;
+ }
+
+ /* success */
+ return g_object_ref (remote);
+}
+
+static void
+fwupd_client_get_approved_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_approved_firmware_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_approved_firmware:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets the list of approved firmware.
+ *
+ * Returns: (transfer full): checksums, or %NULL for error
+ *
+ * Since: 1.2.6
+ **/
+gchar **
+fwupd_client_get_approved_firmware (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+ gchar **argv;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_approved_firmware_async (self, cancellable,
+ fwupd_client_get_approved_firmware_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ argv = g_new0 (gchar *, helper->array->len + 1);
+ for (guint i = 0; i < helper->array->len; i++) {
+ const gchar *tmp = g_ptr_array_index (helper->array, i);
+ argv[i] = g_strdup (tmp);
+ }
+ return argv;
+}
+
+static void
+fwupd_client_set_approved_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_set_approved_firmware_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_set_approved_firmware:
+ * @self: A #FwupdClient
+ * @checksums: Array of checksums
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Sets the list of approved firmware.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.2.6
+ **/
+gboolean
+fwupd_client_set_approved_firmware (FwupdClient *self,
+ gchar **checksums,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+ g_autoptr(GPtrArray) array = g_ptr_array_new_with_free_func (g_free);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* convert */
+ for (guint i = 0; checksums[i] != NULL; i++)
+ g_ptr_array_add (array, g_strdup (checksums[i]));
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_set_approved_firmware_async (self, array, cancellable,
+ fwupd_client_set_approved_firmware_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_get_blocked_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->array = fwupd_client_get_blocked_firmware_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_get_blocked_firmware:
+ * @self: A #FwupdClient
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Gets the list of blocked firmware.
+ *
+ * Returns: (transfer full): checksums, or %NULL for error
+ *
+ * Since: 1.4.6
+ **/
+gchar **
+fwupd_client_get_blocked_firmware (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+ gchar **argv;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_get_blocked_firmware_async (self, cancellable,
+ fwupd_client_get_blocked_firmware_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->array == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ argv = g_new0 (gchar *, helper->array->len + 1);
+ for (guint i = 0; i < helper->array->len; i++) {
+ const gchar *tmp = g_ptr_array_index (helper->array, i);
+ argv[i] = g_strdup (tmp);
+ }
+ return argv;
+}
+
+static void
+fwupd_client_set_blocked_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_set_blocked_firmware_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_set_blocked_firmware:
+ * @self: A #FwupdClient
+ * @checksums: Array of checksums
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Sets the list of approved firmware.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.6
+ **/
+gboolean
+fwupd_client_set_blocked_firmware (FwupdClient *self,
+ gchar **checksums,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+ g_autoptr(GPtrArray) array = g_ptr_array_new_with_free_func (g_free);
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (checksums != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ for (guint i = 0; checksums[i] != NULL; i++)
+ g_ptr_array_add (array, g_strdup (checksums[i]));
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_set_blocked_firmware_async (self, array, cancellable,
+ fwupd_client_set_blocked_firmware_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_set_feature_flags_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->ret = fwupd_client_set_feature_flags_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_set_feature_flags:
+ * @self: A #FwupdClient
+ * @feature_flags: #FwupdFeatureFlags, e.g. %FWUPD_FEATURE_FLAG_UPDATE_TEXT
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Sets the features the client supports. This allows firmware to depend on
+ * specific front-end features, for instance showing the user an image on
+ * how to detach the hardware.
+ *
+ * Clients can call this none or multiple times.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.5
+ **/
+gboolean
+fwupd_client_set_feature_flags (FwupdClient *self,
+ FwupdFeatureFlags feature_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return FALSE;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_set_feature_flags_async (self, feature_flags, cancellable,
+ fwupd_client_set_feature_flags_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (!helper->ret) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fwupd_client_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->str = fwupd_client_self_sign_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_self_sign:
+ * @self: A #FwupdClient
+ * @value: A string to sign, typically a JSON blob
+ * @flags: #FwupdSelfSignFlags, e.g. %FWUPD_SELF_SIGN_FLAG_ADD_TIMESTAMP
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Signs the data using the client self-signed certificate.
+ *
+ * Returns: a signature, or %NULL for failure
+ *
+ * Since: 1.2.6
+ **/
+gchar *
+fwupd_client_self_sign (FwupdClient *self,
+ const gchar *value,
+ FwupdSelfSignFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (value != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_self_sign_async (self, value, flags, cancellable,
+ fwupd_client_self_sign_cb,
+ helper);
+ g_main_loop_run (helper->loop);
+ if (helper->str == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->str);
+}
+
+static void
+fwupd_client_download_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->bytes = fwupd_client_download_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_download_bytes:
+ * @self: A #FwupdClient
+ * @url: the remote URL
+ * @flags: #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_NONE
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Downloads data from a remote server. The fwupd_client_set_user_agent() function
+ * should be called before this method is used.
+ *
+ * Returns: (transfer full): downloaded data, or %NULL for error
+ *
+ * Since: 1.4.5
+ **/
+GBytes *
+fwupd_client_download_bytes (FwupdClient *self,
+ const gchar *url,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (url != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (fwupd_client_get_user_agent (self) != NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_download_bytes_async (self, url, flags, cancellable,
+ fwupd_client_download_bytes_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->bytes == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->bytes);
+}
+
+/**
+ * fwupd_client_download_file:
+ * @self: A #FwupdClient
+ * @url: the remote URL
+ * @file: a #GFile
+ * @flags: #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_NONE
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Downloads data from a remote server. The fwupd_client_set_user_agent() function
+ * should be called before this method is used.
+ *
+ * Returns: %TRUE if the file was written, or %NULL for error
+ *
+ * Since: 1.5.2
+ **/
+gboolean
+fwupd_client_download_file (FwupdClient *self,
+ const gchar *url,
+ GFile *file,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gssize size;
+ g_autoptr(GBytes) bytes = NULL;
+ g_autoptr(GOutputStream) ostream = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), FALSE);
+ g_return_val_if_fail (url != NULL, FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (fwupd_client_get_user_agent (self) != NULL, FALSE);
+
+ /* download then write */
+ bytes = fwupd_client_download_bytes (self, url, flags, cancellable, error);
+ if (bytes == NULL)
+ return FALSE;
+ ostream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
+ G_FILE_CREATE_NONE, NULL, error));
+ if (ostream == NULL)
+ return FALSE;
+ size = g_output_stream_write_bytes (ostream, bytes, NULL, error);
+ if (size < 0)
+ return FALSE;
+
+ /* success */
+ return TRUE;
+}
+
+static void
+fwupd_client_upload_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ FwupdClientHelper *helper = (FwupdClientHelper *) user_data;
+ helper->bytes = fwupd_client_upload_bytes_finish (FWUPD_CLIENT (source), res, &helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+/**
+ * fwupd_client_upload_bytes:
+ * @self: A #FwupdClient
+ * @url: the remote URL
+ * @payload: payload string
+ * @signature: (nullable): signature string
+ * @flags: #FwupdClientDownloadFlags, e.g. %FWUPD_CLIENT_DOWNLOAD_FLAG_NONE
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Uploads data to a remote server. The fwupd_client_set_user_agent() function
+ * should be called before this method is used.
+ *
+ * Returns: (transfer full): response data, or %NULL for error
+ *
+ * Since: 1.4.5
+ **/
+GBytes *
+fwupd_client_upload_bytes (FwupdClient *self,
+ const gchar *url,
+ const gchar *payload,
+ const gchar *signature,
+ FwupdClientUploadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FwupdClientHelper) helper = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (self), NULL);
+ g_return_val_if_fail (url != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* connect */
+ if (!fwupd_client_connect (self, cancellable, error))
+ return NULL;
+
+ /* call async version and run loop until complete */
+ helper = fwupd_client_helper_new (self);
+ fwupd_client_upload_bytes_async (self, url, payload, signature, flags, cancellable,
+ fwupd_client_upload_bytes_cb, helper);
+ g_main_loop_run (helper->loop);
+ if (helper->bytes == NULL) {
+ g_propagate_error (error, g_steal_pointer (&helper->error));
+ return NULL;
+ }
+ return g_steal_pointer (&helper->bytes);
+}
diff -Nru fwupd-1.4.5/libfwupd/fwupd-client-sync.h fwupd-1.5.8/libfwupd/fwupd-client-sync.h
--- fwupd-1.4.5/libfwupd/fwupd-client-sync.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-client-sync.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2016 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fwupd-client.h"
+
+G_BEGIN_DECLS
+
+gboolean fwupd_client_connect (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_devices (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_plugins (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_history (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_releases (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_downgrades (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_upgrades (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_details (FwupdClient *self,
+ const gchar *filename,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_details_bytes (FwupdClient *self,
+ GBytes *bytes,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_verify (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_verify_update (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_unlock (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_modify_config (FwupdClient *self,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_activate (FwupdClient *self,
+ GCancellable *cancellable,
+ const gchar *device_id,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_clear_results (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FwupdDevice *fwupd_client_get_results (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_host_security_attrs (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FwupdDevice *fwupd_client_get_device_by_id (FwupdClient *self,
+ const gchar *device_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_devices_by_guid (FwupdClient *self,
+ const gchar *guid,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_install (FwupdClient *self,
+ const gchar *device_id,
+ const gchar *filename,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_install_bytes (FwupdClient *self,
+ const gchar *device_id,
+ GBytes *bytes,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_install_release (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT
+G_DEPRECATED_FOR(fwupd_client_install_release2);
+gboolean fwupd_client_install_release2 (FwupdClient *self,
+ FwupdDevice *device,
+ FwupdRelease *release,
+ FwupdInstallFlags install_flags,
+ FwupdClientDownloadFlags download_flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_update_metadata (FwupdClient *self,
+ const gchar *remote_id,
+ const gchar *metadata_fn,
+ const gchar *signature_fn,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_update_metadata_bytes (FwupdClient *self,
+ const gchar *remote_id,
+ GBytes *metadata,
+ GBytes *signature,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_refresh_remote (FwupdClient *self,
+ FwupdRemote *remote,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_modify_remote (FwupdClient *self,
+ const gchar *remote_id,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_modify_device (FwupdClient *self,
+ const gchar *device_id,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GHashTable *fwupd_client_get_report_metadata (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fwupd_client_get_remotes (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FwupdRemote *fwupd_client_get_remote_by_id (FwupdClient *self,
+ const gchar *remote_id,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gchar **fwupd_client_get_approved_firmware (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_set_approved_firmware (FwupdClient *self,
+ gchar **checksums,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gchar **fwupd_client_get_blocked_firmware (FwupdClient *self,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_set_blocked_firmware (FwupdClient *self,
+ gchar **checksums,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gchar *fwupd_client_self_sign (FwupdClient *self,
+ const gchar *value,
+ FwupdSelfSignFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_set_feature_flags (FwupdClient *self,
+ FwupdFeatureFlags feature_flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GBytes *fwupd_client_download_bytes (FwupdClient *self,
+ const gchar *url,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fwupd_client_download_file (FwupdClient *self,
+ const gchar *url,
+ GFile *file,
+ FwupdClientDownloadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GBytes *fwupd_client_upload_bytes (FwupdClient *self,
+ const gchar *url,
+ const gchar *payload,
+ const gchar *signature,
+ FwupdClientUploadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+G_END_DECLS
diff -Nru fwupd-1.4.5/libfwupd/fwupd-common.c fwupd-1.5.8/libfwupd/fwupd-common.c
--- fwupd-1.4.5/libfwupd/fwupd-common.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-common.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -158,6 +158,8 @@
g_autofree gchar *buf = NULL;
g_auto(GStrv) lines = NULL;
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
/* TODO: Read the Windows version */
#ifdef _WIN32
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
@@ -169,7 +171,6 @@
/* 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;
@@ -349,6 +350,9 @@
g_autoptr(GChecksum) csum = NULL;
gsize sz = 0;
+ g_return_val_if_fail (salt != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
/* one of these has to exist */
fns[0] = g_build_filename (FWUPD_SYSCONFDIR, "machine-id", NULL);
fns[1] = g_build_filename (FWUPD_LOCALSTATEDIR, "lib", "dbus", "machine-id", NULL);
@@ -530,6 +534,9 @@
g_autoptr(JsonGenerator) json_generator = NULL;
g_autoptr(JsonNode) json_root = NULL;
+ g_return_val_if_fail (devices != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
/* get a hash that represents the machine */
machine_id = fwupd_build_machine_id ("fwupd", error);
if (machine_id == NULL)
@@ -613,19 +620,19 @@
/* mixed is bizaar, but specified as the DCE encoding */
if (flags & FWUPD_GUID_FLAG_MIXED_ENDIAN) {
return g_strdup_printf ("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- GUINT32_FROM_LE(gnat.a),
- GUINT16_FROM_LE(gnat.b),
- GUINT16_FROM_LE(gnat.c),
- GUINT16_FROM_BE(gnat.d),
+ (guint) GUINT32_FROM_LE(gnat.a),
+ (guint) GUINT16_FROM_LE(gnat.b),
+ (guint) GUINT16_FROM_LE(gnat.c),
+ (guint) GUINT16_FROM_BE(gnat.d),
gnat.e[0], gnat.e[1],
gnat.e[2], gnat.e[3],
gnat.e[4], gnat.e[5]);
}
return g_strdup_printf ("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- GUINT32_FROM_BE(gnat.a),
- GUINT16_FROM_BE(gnat.b),
- GUINT16_FROM_BE(gnat.c),
- GUINT16_FROM_BE(gnat.d),
+ (guint) GUINT32_FROM_BE(gnat.a),
+ (guint) GUINT16_FROM_BE(gnat.b),
+ (guint) GUINT16_FROM_BE(gnat.c),
+ (guint) GUINT16_FROM_BE(gnat.d),
gnat.e[0], gnat.e[1],
gnat.e[2], gnat.e[3],
gnat.e[4], gnat.e[5]);
@@ -723,6 +730,7 @@
g_auto(GStrv) split = NULL;
g_return_val_if_fail (guidstr != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* split into sections */
if (strlen (guidstr) != 36) {
@@ -941,6 +949,96 @@
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):
@@ -948,6 +1046,7 @@
GUnixInputStream *
fwupd_unix_input_stream_from_bytes (GBytes *bytes, GError **error)
{
+#ifdef HAVE_MEMFD_CREATE
gint fd;
gssize rc;
@@ -975,6 +1074,13 @@
return NULL;
}
return G_UNIX_INPUT_STREAM (g_unix_input_stream_new (fd, TRUE));
+#else
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "memfd_create() not available");
+ return NULL;
+#endif
}
/**
diff -Nru fwupd-1.4.5/libfwupd/fwupd-common.h fwupd-1.5.8/libfwupd/fwupd-common.h
--- fwupd-1.4.5/libfwupd/fwupd-common.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-common.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
diff -Nru fwupd-1.4.5/libfwupd/fwupd-common-private.h fwupd-1.5.8/libfwupd/fwupd-common-private.h
--- fwupd-1.4.5/libfwupd/fwupd-common-private.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-common-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -6,7 +6,7 @@
#pragma once
-#include
+#include
#ifdef HAVE_GIO_UNIX
#include
@@ -21,11 +21,22 @@
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)
+ G_GNUC_WARN_UNUSED_RESULT;
+
#ifdef HAVE_GIO_UNIX
GUnixInputStream *fwupd_unix_input_stream_from_bytes (GBytes *bytes,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GUnixInputStream *fwupd_unix_input_stream_from_fn (const gchar *fn,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
#endif
G_END_DECLS
diff -Nru fwupd-1.4.5/libfwupd/fwupd-context-test.c fwupd-1.5.8/libfwupd/fwupd-context-test.c
--- fwupd-1.4.5/libfwupd/fwupd-context-test.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-context-test.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 Philip Withnall
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include
+
+typedef struct {
+ GApplication *app;
+ FwupdClient *client;
+ GThread *main_thread;
+ GThread *worker_thread;
+} FuThreadTestSelf;
+
+static gboolean
+fwupd_thread_test_exit_idle_cb (gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_application_release (self->app);
+ return G_SOURCE_REMOVE;
+}
+
+static gpointer
+fwupd_thread_test_thread_cb (gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_autoptr(GError) error_local = NULL;
+ g_autoptr(GMainContext) context = g_main_context_new ();
+ g_autoptr(GMainContextPusher) pusher = g_main_context_pusher_new (context);
+
+ g_assert (pusher != NULL);
+ g_message ("Calling fwupd_client_get_devices() in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+ if (!fwupd_client_connect (self->client, NULL, &error_local))
+ g_warning ("%s", error_local->message);
+ g_idle_add (fwupd_thread_test_exit_idle_cb, self);
+ return NULL;
+}
+
+static gboolean
+fwupd_thread_test_idle_cb (gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_message ("fwupd_thread_test_idle_cb() in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+ self->worker_thread = g_thread_new ("worker00",
+ fwupd_thread_test_thread_cb,
+ self);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+fwupd_thread_test_activate_cb (GApplication *app, gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_application_hold (self->app);
+ g_idle_add (fwupd_thread_test_idle_cb, self);
+}
+
+static void
+fwupd_thread_test_notify_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_message ("fwupd_thread_test_notify_cb() in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+ g_assert (g_thread_self () == self->main_thread);
+ g_assert (g_main_context_get_thread_default () == NULL);
+}
+
+static gboolean
+fwupd_thread_test_has_system_bus (void)
+{
+ g_autoptr(GDBusConnection) conn = NULL;
+ conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+ return conn != NULL;
+}
+
+int
+main (void)
+{
+ gint retval;
+ g_autoptr(FwupdClient) client = fwupd_client_new ();
+ g_autoptr(GApplication) app = g_application_new ("org.fwupd.ContextTest", G_APPLICATION_FLAGS_NONE);
+ g_autoptr(GThread) worker_thread = NULL;
+ FuThreadTestSelf self = {
+ .app = app,
+ .client = client,
+ .worker_thread = worker_thread,
+ .main_thread = g_thread_self (),
+ };
+
+ /* only some of the CI targets have a DBus daemon */
+ if (!fwupd_thread_test_has_system_bus ()) {
+ g_message ("D-Bus system bus unavailable, skipping tests.");
+ return 0;
+ }
+ g_message ("Created FwupdClient in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+ g_signal_connect (client, "notify::status",
+ G_CALLBACK (fwupd_thread_test_notify_cb), &self);
+ g_signal_connect (app, "activate",
+ G_CALLBACK (fwupd_thread_test_activate_cb), &self);
+ retval = g_application_run (app, 0, NULL);
+ if (self.worker_thread != NULL)
+ g_thread_join (g_steal_pointer (&self.worker_thread));
+
+ return retval;
+}
diff -Nru fwupd-1.4.5/libfwupd/fwupd-device.c fwupd-1.5.8/libfwupd/fwupd-device.c
--- fwupd-1.4.5/libfwupd/fwupd-device.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-device.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -34,14 +34,17 @@
guint64 modified;
guint64 flags;
GPtrArray *guids;
+ GPtrArray *vendor_ids;
+ GPtrArray *protocols;
GPtrArray *instance_ids;
GPtrArray *icons;
gchar *name;
gchar *serial;
gchar *summary;
+ gchar *branch;
gchar *description;
gchar *vendor;
- gchar *vendor_id;
+ gchar *vendor_id; /* for compat only */
gchar *homepage;
gchar *plugin;
gchar *protocol;
@@ -62,7 +65,7 @@
gchar *update_image;
FwupdStatus status;
GPtrArray *releases;
- FwupdDevice *parent;
+ FwupdDevice *parent; /* noref */
} FwupdDevicePrivate;
enum {
@@ -71,6 +74,8 @@
PROP_FLAGS,
PROP_PROTOCOL,
PROP_STATUS,
+ PROP_PARENT,
+ PROP_UPDATE_STATE,
PROP_LAST
};
@@ -168,11 +173,57 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->summary, summary) == 0)
+ return;
+
g_free (priv->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));
+
+ /* not changed */
+ if (g_strcmp0 (priv->branch, branch) == 0)
+ return;
+
+ g_free (priv->branch);
+ priv->branch = g_strdup (branch);
+}
+
+/**
* fwupd_device_get_serial:
* @device: A #FwupdDevice
*
@@ -204,6 +255,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->serial, serial) == 0)
+ return;
+
g_free (priv->serial);
priv->serial = g_strdup (serial);
}
@@ -240,6 +296,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->id, id) == 0)
+ return;
+
g_free (priv->id);
priv->id = g_strdup (id);
}
@@ -276,6 +337,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->parent_id, parent_id) == 0)
+ return;
+
g_free (priv->parent_id);
priv->parent_id = g_strdup (parent_id);
}
@@ -311,10 +377,56 @@
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);
+}
+
+static void
+fwupd_device_child_finalized_cb (gpointer data, GObject *where_the_object_was)
+{
+ FwupdDevice *device = FWUPD_DEVICE (data);
+ g_critical ("FuDevice child %p was finalized while still having parent %s [%s]!",
+ where_the_object_was,
+ fwupd_device_get_name (device),
+ fwupd_device_get_id (device));
+}
+
+/**
+ * fwupd_device_add_child:
+ * @device: A #FwupdDevice
+ * @child: Another #FwupdDevice
+ *
+ * Adds a child device. An child device is logically linked to the primary
+ * device in some way.
+ *
+ * NOTE: You should never call this function from user code, it is for daemon
+ * use only. Only use fwupd_device_set_parent() to set up a logical tree.
+ *
+ * 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_object_weak_ref (G_OBJECT (child),
+ fwupd_device_child_finalized_cb,
+ device);
+ g_ptr_array_add (priv->children, g_object_ref (child));
}
/**
@@ -547,6 +659,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->name, name) == 0)
+ return;
+
g_free (priv->name);
priv->name = g_strdup (name);
}
@@ -583,6 +700,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->vendor, vendor) == 0)
+ return;
+
g_free (priv->vendor);
priv->vendor = g_strdup (vendor);
}
@@ -591,11 +713,13 @@
* fwupd_device_get_vendor_id:
* @device: A #FwupdDevice
*
- * Gets the device vendor ID.
+ * Gets the combined device vendor ID.
*
- * Returns: the device vendor, e.g. 'USB:0x1234', or %NULL if unset
+ * Returns: the device vendor, e.g. 'USB:0x1234|PCI:0x5678', or %NULL if unset
*
* Since: 0.9.4
+ *
+ * Deprecated: 1.5.5: Use fwupd_device_get_vendor_ids() instead.
**/
const gchar *
fwupd_device_get_vendor_id (FwupdDevice *device)
@@ -608,19 +732,103 @@
/**
* fwupd_device_set_vendor_id:
* @device: A #FwupdDevice
- * @vendor_id: the ID, e.g. 'USB:0x1234'
+ * @vendor_id: the ID, e.g. 'USB:0x1234' or 'USB:0x1234|PCI:0x5678'
*
* Sets the device vendor ID.
*
* Since: 0.9.4
+ *
+ * Deprecated: 1.5.5: Use fwupd_device_add_vendor_id() instead.
**/
void
fwupd_device_set_vendor_id (FwupdDevice *device, const gchar *vendor_id)
{
+ g_auto(GStrv) vendor_ids = NULL;
+
+ g_return_if_fail (FWUPD_IS_DEVICE (device));
+ g_return_if_fail (vendor_id != NULL);
+
+ /* add all */
+ vendor_ids = g_strsplit (vendor_id, "|", -1);
+ for (guint i = 0; vendor_ids[i] != NULL; i++)
+ fwupd_device_add_vendor_id (device, vendor_ids[i]);
+}
+
+/**
+ * fwupd_device_get_vendor_ids:
+ * @device: A #FwupdDevice
+ *
+ * Gets the device vendor ID.
+ *
+ * Returns: (element-type utf8) (transfer none): the device vendor ID
+ *
+ * Since: 1.5.5
+ **/
+GPtrArray *
+fwupd_device_get_vendor_ids (FwupdDevice *device)
+{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
+ g_return_val_if_fail (FWUPD_IS_DEVICE (device), NULL);
+ return priv->vendor_ids;
+}
+
+/**
+ * fwupd_device_has_vendor_id:
+ * @device: A #FwupdDevice
+ * @vendor_id: the ID, e.g. 'USB:0x1234'
+ *
+ * Finds out if the device has this specific vendor ID.
+ *
+ * Returns: %TRUE if the ID is found
+ *
+ * Since: 1.5.5
+ **/
+gboolean
+fwupd_device_has_vendor_id (FwupdDevice *device, const gchar *vendor_id)
+{
+ FwupdDevicePrivate *priv = GET_PRIVATE (device);
+
+ g_return_val_if_fail (FWUPD_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (vendor_id != NULL, FALSE);
+
+ for (guint i = 0; i < priv->vendor_ids->len; i++) {
+ const gchar *vendor_id_tmp = g_ptr_array_index (priv->vendor_ids, i);
+ if (g_strcmp0 (vendor_id, vendor_id_tmp) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * fwupd_device_add_vendor_id:
+ * @device: A #FwupdDevice
+ * @vendor_id: the ID, e.g. 'USB:0x1234'
+ *
+ * Adds a device vendor ID.
+ *
+ * Since: 1.5.5
+ **/
+void
+fwupd_device_add_vendor_id (FwupdDevice *device, const gchar *vendor_id)
+{
+ FwupdDevicePrivate *priv = GET_PRIVATE (device);
+ g_auto(GStrv) vendor_ids_tmp = NULL;
+
g_return_if_fail (FWUPD_IS_DEVICE (device));
+ g_return_if_fail (vendor_id != NULL);
+
+ if (fwupd_device_has_vendor_id (device, vendor_id))
+ return;
+ g_ptr_array_add (priv->vendor_ids, g_strdup (vendor_id));
+
+ /* build for compatibility */
+ vendor_ids_tmp = g_new0 (gchar *, priv->vendor_ids->len + 1);
+ for (guint i = 0; i < priv->vendor_ids->len; i++) {
+ const gchar *vendor_id_tmp = g_ptr_array_index (priv->vendor_ids, i);
+ vendor_ids_tmp[i] = g_strdup (vendor_id_tmp);
+ }
g_free (priv->vendor_id);
- priv->vendor_id = g_strdup (vendor_id);
+ priv->vendor_id = g_strjoinv ("|", vendor_ids_tmp);
}
/**
@@ -655,6 +863,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->description, description) == 0)
+ return;
+
g_free (priv->description);
priv->description = g_strdup (description);
}
@@ -691,6 +904,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->version, version) == 0)
+ return;
+
g_free (priv->version);
priv->version = g_strdup (version);
}
@@ -727,6 +945,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->version_lowest, version_lowest) == 0)
+ return;
+
g_free (priv->version_lowest);
priv->version_lowest = g_strdup (version_lowest);
}
@@ -798,6 +1021,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->version_bootloader, version_bootloader) == 0)
+ return;
+
g_free (priv->version_bootloader);
priv->version_bootloader = g_strdup (version_bootloader);
}
@@ -939,6 +1167,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->plugin, plugin) == 0)
+ return;
+
g_free (priv->plugin);
priv->plugin = g_strdup (plugin);
}
@@ -952,6 +1185,8 @@
* Returns: the protocol name, or %NULL if unset
*
* Since: 1.3.6
+ *
+ * Deprecated: 1.5.8: Use fwupd_device_get_protocols() instead.
**/
const gchar *
fwupd_device_get_protocol (FwupdDevice *device)
@@ -969,14 +1204,98 @@
* Sets the protocol that is used to update the device.
*
* Since: 1.3.6
+ *
+ * Deprecated: 1.5.8: Use fwupd_device_add_protocol() instead.
**/
void
fwupd_device_set_protocol (FwupdDevice *device, const gchar *protocol)
{
+ g_auto(GStrv) protocols = NULL;
+
+ g_return_if_fail (FWUPD_IS_DEVICE (device));
+ g_return_if_fail (protocol != NULL);
+
+ /* add all */
+ protocols = g_strsplit (protocol, "|", -1);
+ for (guint i = 0; protocols[i] != NULL; i++)
+ fwupd_device_add_protocol (device, protocols[i]);
+}
+
+/**
+ * fwupd_device_get_protocols:
+ * @device: A #FwupdDevice
+ *
+ * Gets the device protocol.
+ *
+ * Returns: (element-type utf8) (transfer none): the device protocol
+ *
+ * Since: 1.5.8
+ **/
+GPtrArray *
+fwupd_device_get_protocols (FwupdDevice *device)
+{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
+ g_return_val_if_fail (FWUPD_IS_DEVICE (device), NULL);
+ return priv->protocols;
+}
+
+/**
+ * fwupd_device_has_protocol:
+ * @device: A #FwupdDevice
+ * @protocol: the ID, e.g. 'USB:0x1234'
+ *
+ * Finds out if the device has this specific protocol.
+ *
+ * Returns: %TRUE if the ID is found
+ *
+ * Since: 1.5.8
+ **/
+gboolean
+fwupd_device_has_protocol (FwupdDevice *device, const gchar *protocol)
+{
+ FwupdDevicePrivate *priv = GET_PRIVATE (device);
+
+ g_return_val_if_fail (FWUPD_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (protocol != NULL, FALSE);
+
+ for (guint i = 0; i < priv->protocols->len; i++) {
+ const gchar *protocol_tmp = g_ptr_array_index (priv->protocols, i);
+ if (g_strcmp0 (protocol, protocol_tmp) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * fwupd_device_add_protocol:
+ * @device: A #FwupdDevice
+ * @protocol: the ID, e.g. 'USB:0x1234'
+ *
+ * Adds a device protocol.
+ *
+ * Since: 1.5.8
+ **/
+void
+fwupd_device_add_protocol (FwupdDevice *device, const gchar *protocol)
+{
+ FwupdDevicePrivate *priv = GET_PRIVATE (device);
+ g_auto(GStrv) protocols_tmp = NULL;
+
g_return_if_fail (FWUPD_IS_DEVICE (device));
+ g_return_if_fail (protocol != NULL);
+
+ if (fwupd_device_has_protocol (device, protocol))
+ return;
+ g_ptr_array_add (priv->protocols, g_strdup (protocol));
+
+ /* build for compatibility */
+ protocols_tmp = g_new0 (gchar *, priv->protocols->len + 1);
+ for (guint i = 0; i < priv->protocols->len; i++) {
+ const gchar *protocol_tmp = g_ptr_array_index (priv->protocols, i);
+ protocols_tmp[i] = g_strdup (protocol_tmp);
+ }
g_free (priv->protocol);
- priv->protocol = g_strdup (protocol);
+ priv->protocol = g_strjoinv ("|", protocols_tmp);
}
/**
@@ -1033,7 +1352,7 @@
g_return_if_fail (FWUPD_IS_DEVICE (device));
if (flag == 0)
return;
- if ((priv->flags & flag) > 0)
+ if ((priv->flags | flag) == priv->flags)
return;
priv->flags |= flag;
g_object_notify (G_OBJECT (device), "flags");
@@ -1098,7 +1417,6 @@
return priv->created;
}
-
/**
* fwupd_device_set_created:
* @device: A #FwupdDevice
@@ -1166,8 +1484,7 @@
FwupdDevicePrivate *priv = GET_PRIVATE (self);
FwupdDevicePrivate *priv_donor = GET_PRIVATE (donor);
- if (priv->flags == 0)
- fwupd_device_add_flag (self, priv_donor->flags);
+ fwupd_device_add_flag (self, priv_donor->flags);
if (priv->created == 0)
fwupd_device_set_created (self, priv_donor->created);
if (priv->modified == 0)
@@ -1190,14 +1507,20 @@
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)
- fwupd_device_set_vendor_id (self, priv_donor->vendor_id);
+ for (guint i = 0; i < priv_donor->vendor_ids->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv_donor->vendor_ids, i);
+ fwupd_device_add_vendor_id (self, tmp);
+ }
if (priv->plugin == NULL)
fwupd_device_set_plugin (self, priv_donor->plugin);
- if (priv->protocol == NULL)
- fwupd_device_set_protocol (self, priv_donor->protocol);
+ for (guint i = 0; i < priv_donor->protocols->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv_donor->protocols, i);
+ fwupd_device_add_protocol (self, tmp);
+ }
if (priv->update_error == NULL)
fwupd_device_set_update_error (self, priv_donor->update_error);
if (priv->update_message == NULL)
@@ -1294,10 +1617,17 @@
FWUPD_RESULT_KEY_VENDOR,
g_variant_new_string (priv->vendor));
}
- if (priv->vendor_id != NULL) {
+ if (priv->vendor_ids->len > 0) {
+ g_autoptr(GString) str = g_string_new (NULL);
+ for (guint i = 0; i < priv->vendor_ids->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv->vendor_ids, i);
+ g_string_append_printf (str, "%s|", tmp);
+ }
+ if (str->len > 0)
+ g_string_truncate (str, str->len - 1);
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_VENDOR_ID,
- g_variant_new_string (priv->vendor_id));
+ g_variant_new_string (str->str));
}
if (priv->flags > 0) {
g_variant_builder_add (&builder, "{sv}",
@@ -1325,6 +1655,11 @@
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++) {
@@ -1342,10 +1677,17 @@
FWUPD_RESULT_KEY_PLUGIN,
g_variant_new_string (priv->plugin));
}
- if (priv->protocol != NULL) {
+ if (priv->protocols->len > 0) {
+ g_autoptr(GString) str = g_string_new (NULL);
+ for (guint i = 0; i < priv->protocols->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv->protocols, i);
+ g_string_append_printf (str, "%s|", tmp);
+ }
+ if (str->len > 0)
+ g_string_truncate (str, str->len - 1);
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_PROTOCOL,
- g_variant_new_string (priv->protocol));
+ g_variant_new_string (str->str));
}
if (priv->version != NULL) {
g_variant_builder_add (&builder, "{sv}",
@@ -1526,7 +1868,10 @@
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_VENDOR_ID) == 0) {
- fwupd_device_set_vendor_id (device, g_variant_get_string (value, NULL));
+ g_auto(GStrv) vendor_ids = NULL;
+ vendor_ids = g_strsplit (g_variant_get_string (value, NULL), "|", -1);
+ for (guint i = 0; vendor_ids[i] != NULL; i++)
+ fwupd_device_add_vendor_id (device, vendor_ids[i]);
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_SERIAL) == 0) {
@@ -1537,6 +1882,10 @@
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;
@@ -1555,7 +1904,10 @@
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_PROTOCOL) == 0) {
- fwupd_device_set_protocol (device, g_variant_get_string (value, NULL));
+ g_auto(GStrv) protocols = NULL;
+ protocols = g_strsplit (g_variant_get_string (value, NULL), "|", -1);
+ for (guint i = 0; protocols[i] != NULL; i++)
+ fwupd_device_add_protocol (device, protocols[i]);
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_VERSION) == 0) {
@@ -1705,7 +2057,10 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+ if (priv->update_state == update_state)
+ return;
priv->update_state = update_state;
+ g_object_notify (G_OBJECT (device), "update-state");
}
/**
@@ -1810,6 +2165,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->update_message, update_message) == 0)
+ return;
+
g_free (priv->update_message);
priv->update_message = g_strdup (update_message);
}
@@ -1846,6 +2206,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->update_image, update_image) == 0)
+ return;
+
g_free (priv->update_image);
priv->update_image = g_strdup (update_image);
}
@@ -1882,6 +2247,11 @@
{
FwupdDevicePrivate *priv = GET_PRIVATE (device);
g_return_if_fail (FWUPD_IS_DEVICE (device));
+
+ /* not changed */
+ if (g_strcmp0 (priv->update_error, update_error) == 0)
+ return;
+
g_free (priv->update_error);
priv->update_error = g_strdup (update_error);
}
@@ -2037,8 +2407,18 @@
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->protocols->len > 1) { /* --> 0 when bumping API */
+ json_builder_set_member_name (builder, "VendorIds");
+ json_builder_begin_array (builder);
+ for (guint i = 0; i < priv->protocols->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv->protocols, i);
+ json_builder_add_string_value (builder, tmp);
+ }
+ json_builder_end_array (builder);
+ }
if (priv->flags != FWUPD_DEVICE_FLAG_NONE) {
json_builder_set_member_name (builder, FWUPD_RESULT_KEY_FLAGS);
json_builder_begin_array (builder);
@@ -2062,6 +2442,15 @@
}
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_VENDOR_ID, priv->vendor_id);
+ if (priv->vendor_ids->len > 1) { /* --> 0 when bumping API */
+ json_builder_set_member_name (builder, "VendorIds");
+ json_builder_begin_array (builder);
+ for (guint i = 0; i < priv->vendor_ids->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv->vendor_ids, i);
+ json_builder_add_string_value (builder, tmp);
+ }
+ json_builder_end_array (builder);
+ }
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_VERSION, priv->version);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_VERSION_LOWEST, priv->version_lowest);
fwupd_device_json_add_string (builder, FWUPD_RESULT_KEY_VERSION_BOOTLOADER, priv->version_bootloader);
@@ -2173,8 +2562,12 @@
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);
+ for (guint i = 0; i < priv->protocols->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv->protocols, i);
+ fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_PROTOCOL, tmp);
+ }
fwupd_pad_kv_dfl (str, FWUPD_RESULT_KEY_FLAGS, priv->flags);
for (guint i = 0; i < priv->checksums->len; i++) {
const gchar *checksum = g_ptr_array_index (priv->checksums, i);
@@ -2182,7 +2575,10 @@
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_CHECKSUM, checksum_display);
}
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
- fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VENDOR_ID, priv->vendor_id);
+ for (guint i = 0; i < priv->vendor_ids->len; i++) {
+ const gchar *tmp = g_ptr_array_index (priv->vendor_ids, i);
+ fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VENDOR_ID, tmp);
+ }
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VERSION, priv->version);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VERSION_LOWEST, priv->version_lowest);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_VERSION_BOOTLOADER, priv->version_bootloader);
@@ -2248,6 +2644,12 @@
case PROP_STATUS:
g_value_set_uint (value, priv->status);
break;
+ case PROP_PARENT:
+ g_value_set_object (value, priv->parent);
+ break;
+ case PROP_UPDATE_STATE:
+ g_value_set_uint (value, priv->update_state);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2267,11 +2669,17 @@
fwupd_device_set_flags (self, g_value_get_uint64 (value));
break;
case PROP_PROTOCOL:
- fwupd_device_set_protocol (self, g_value_get_string (value));
+ fwupd_device_add_protocol (self, g_value_get_string (value));
break;
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;
+ case PROP_UPDATE_STATE:
+ fwupd_device_set_update_state (self, g_value_get_uint (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2316,6 +2724,21 @@
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);
+
+ pspec = g_param_spec_uint ("update-state", NULL, NULL,
+ FWUPD_UPDATE_STATE_UNKNOWN,
+ FWUPD_UPDATE_STATE_LAST,
+ FWUPD_UPDATE_STATE_UNKNOWN,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME);
+ g_object_class_install_property (object_class, PROP_UPDATE_STATE, pspec);
}
static void
@@ -2326,6 +2749,8 @@
priv->instance_ids = g_ptr_array_new_with_free_func (g_free);
priv->icons = g_ptr_array_new_with_free_func (g_free);
priv->checksums = g_ptr_array_new_with_free_func (g_free);
+ priv->vendor_ids = g_ptr_array_new_with_free_func (g_free);
+ priv->protocols = g_ptr_array_new_with_free_func (g_free);
priv->children = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
priv->releases = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
}
@@ -2337,13 +2762,21 @@
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);
+ for (guint i = 0; i < priv->children->len; i++) {
+ FwupdDevice *child = g_ptr_array_index (priv->children, i);
+ g_object_weak_unref (G_OBJECT (child),
+ fwupd_device_child_finalized_cb,
+ device);
+ }
+
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);
@@ -2355,6 +2788,8 @@
g_free (priv->version_lowest);
g_free (priv->version_bootloader);
g_ptr_array_unref (priv->guids);
+ g_ptr_array_unref (priv->vendor_ids);
+ g_ptr_array_unref (priv->protocols);
g_ptr_array_unref (priv->instance_ids);
g_ptr_array_unref (priv->icons);
g_ptr_array_unref (priv->checksums);
diff -Nru fwupd-1.4.5/libfwupd/fwupd-device.h fwupd-1.5.8/libfwupd/fwupd-device.h
--- fwupd-1.4.5/libfwupd/fwupd-device.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-device.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -41,6 +41,8 @@
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 @@
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);
@@ -102,15 +107,29 @@
const gchar *fwupd_device_get_plugin (FwupdDevice *device);
void fwupd_device_set_plugin (FwupdDevice *device,
const gchar *plugin);
+G_DEPRECATED_FOR(fwupd_device_get_protocols)
const gchar *fwupd_device_get_protocol (FwupdDevice *device);
+G_DEPRECATED_FOR(fwupd_device_add_protocol)
void fwupd_device_set_protocol (FwupdDevice *device,
const gchar *protocol);
+void fwupd_device_add_protocol (FwupdDevice *device,
+ const gchar *protocol);
+gboolean fwupd_device_has_protocol (FwupdDevice *device,
+ const gchar *protocol);
+GPtrArray *fwupd_device_get_protocols (FwupdDevice *device);
const gchar *fwupd_device_get_vendor (FwupdDevice *device);
void fwupd_device_set_vendor (FwupdDevice *device,
const gchar *vendor);
+G_DEPRECATED_FOR(fwupd_device_get_vendor_ids)
const gchar *fwupd_device_get_vendor_id (FwupdDevice *device);
+G_DEPRECATED_FOR(fwupd_device_add_vendor_id)
void fwupd_device_set_vendor_id (FwupdDevice *device,
const gchar *vendor_id);
+void fwupd_device_add_vendor_id (FwupdDevice *device,
+ const gchar *vendor_id);
+gboolean fwupd_device_has_vendor_id (FwupdDevice *device,
+ const gchar *vendor_id);
+GPtrArray *fwupd_device_get_vendor_ids (FwupdDevice *device);
void fwupd_device_add_guid (FwupdDevice *device,
const gchar *guid);
gboolean fwupd_device_has_guid (FwupdDevice *device,
diff -Nru fwupd-1.4.5/libfwupd/fwupd-enums.c fwupd-1.5.8/libfwupd/fwupd-enums.c
--- fwupd-1.4.5/libfwupd/fwupd-enums.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-enums.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -189,6 +189,8 @@
return "md-set-name-category";
if (device_flag == FWUPD_DEVICE_FLAG_MD_SET_VERFMT)
return "md-set-verfmt";
+ if (device_flag == FWUPD_DEVICE_FLAG_MD_SET_ICON)
+ return "md-set-icon";
if (device_flag == FWUPD_DEVICE_FLAG_ADD_COUNTERPART_GUIDS)
return "add-counterpart-guids";
if (device_flag == FWUPD_DEVICE_FLAG_NO_GUID_MATCHING)
@@ -197,6 +199,10 @@
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;
@@ -287,6 +293,8 @@
return FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY;
if (g_strcmp0 (device_flag, "md-set-verfmt") == 0)
return FWUPD_DEVICE_FLAG_MD_SET_VERFMT;
+ if (g_strcmp0 (device_flag, "md-set-icon") == 0)
+ return FWUPD_DEVICE_FLAG_MD_SET_ICON;
if (g_strcmp0 (device_flag, "add-counterpart-guids") == 0)
return FWUPD_DEVICE_FLAG_ADD_COUNTERPART_GUIDS;
if (g_strcmp0 (device_flag, "no-guid-matching") == 0)
@@ -295,6 +303,92 @@
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_PLUGIN_FLAG_REQUIRE_HWID)
+ return "require-hwid";
+ 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;
+ if (g_strcmp0 (plugin_flag, "require-hwid") == 0)
+ return FWUPD_PLUGIN_FLAG_REQUIRE_HWID;
return FWUPD_DEVICE_FLAG_UNKNOWN;
}
@@ -419,6 +513,8 @@
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 +539,8 @@
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 +619,8 @@
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 +649,8 @@
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 +680,7 @@
/**
* 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.
*
diff -Nru fwupd-1.4.5/libfwupd/fwupd-enums.h fwupd-1.5.8/libfwupd/fwupd-enums.h
--- fwupd-1.4.5/libfwupd/fwupd-enums.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-enums.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -70,6 +70,7 @@
* @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 @@
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 @@
* @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
@@ -104,11 +106,11 @@
* @FWUPD_DEVICE_FLAG_TRUSTED: Extra metadata can be exposed about this device
* @FWUPD_DEVICE_FLAG_NEEDS_SHUTDOWN: Requires system shutdown to apply firmware
* @FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED: Requires the update to be retried with a new plugin
- * @FWUPD_DEVICE_FLAG_NO_AUTO_INSTANCE_IDS: Do not add instance IDs from the device baseclass
+ * @FWUPD_DEVICE_FLAG_NO_AUTO_INSTANCE_IDS: Deprecated, no not use
* @FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION: Device update needs to be separately activated
* @FWUPD_DEVICE_FLAG_HISTORICAL Device is for historical data only
- * @FWUPD_DEVICE_FLAG_ENSURE_SEMVER: Ensure the version is a valid semantic version, e.g. numbers separated with dots
- * @FWUPD_DEVICE_FLAG_ONLY_SUPPORTED: Only devices supported in the metadata will be opened
+ * @FWUPD_DEVICE_FLAG_ENSURE_SEMVER: Deprecated, no not use
+ * @FWUPD_DEVICE_FLAG_ONLY_SUPPORTED: Deprecated, no not use
* @FWUPD_DEVICE_FLAG_WILL_DISAPPEAR: Device will disappear after update and can't be verified
* @FWUPD_DEVICE_FLAG_CAN_VERIFY: Device checksums can be compared against metadata
* @FWUPD_DEVICE_FLAG_CAN_VERIFY_IMAGE: Image can be dumped from device for verification
@@ -117,13 +119,16 @@
* @FWUPD_DEVICE_FLAG_USABLE_DURING_UPDATE: Device remains usable while fwupd flashes or schedules the update
* @FWUPD_DEVICE_FLAG_VERSION_CHECK_REQUIRED: All firmware updates for this device require a firmware version check
* @FWUPD_DEVICE_FLAG_INSTALL_ALL_RELEASES: Install each intermediate release rather than jumping direct to newest
- * @FWUPD_DEVICE_FLAG_MD_SET_NAME: Set the device name from the metadata if available
- * @FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY: Set the device name from the metadata if available
- * @FWUPD_DEVICE_FLAG_MD_SET_VERFMT: Set the device version format from the metadata if available
+ * @FWUPD_DEVICE_FLAG_MD_SET_NAME: Deprecated, no not use
+ * @FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY: Deprecated, no not use
+ * @FWUPD_DEVICE_FLAG_MD_SET_VERFMT: Deprecated, no not use
* @FWUPD_DEVICE_FLAG_ADD_COUNTERPART_GUIDS: Add counterpart GUIDs from an alternate mode like bootloader
- * @FWUPD_DEVICE_FLAG_NO_GUID_MATCHING: Force an explicit ID match when adding devices to the device list
+ * @FWUPD_DEVICE_FLAG_NO_GUID_MATCHING: Deprecated, no not use
* @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
+ * @FWUPD_DEVICE_FLAG_MD_SET_ICON: Deprecated, no not use
*
* The device flags.
**/
@@ -147,11 +152,11 @@
#define FWUPD_DEVICE_FLAG_TRUSTED (1u << 16) /* Since: 1.1.2 */
#define FWUPD_DEVICE_FLAG_NEEDS_SHUTDOWN (1u << 17) /* Since: 1.2.4 */
#define FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED (1u << 18) /* Since: 1.2.5 */
-#define FWUPD_DEVICE_FLAG_NO_AUTO_INSTANCE_IDS (1u << 19) /* Since: 1.2.5 */
+#define FWUPD_DEVICE_FLAG_NO_AUTO_INSTANCE_IDS (1u << 19) /* Since: 1.2.5; Deprecated: 1.5.5 */
#define FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION (1u << 20) /* Since: 1.2.6 */
-#define FWUPD_DEVICE_FLAG_ENSURE_SEMVER (1u << 21) /* Since: 1.2.9 */
+#define FWUPD_DEVICE_FLAG_ENSURE_SEMVER (1u << 21) /* Since: 1.2.9; Deprecated: 1.5.5 */
#define FWUPD_DEVICE_FLAG_HISTORICAL (1u << 22) /* Since: 1.3.2 */
-#define FWUPD_DEVICE_FLAG_ONLY_SUPPORTED (1u << 23) /* Since: 1.3.3 */
+#define FWUPD_DEVICE_FLAG_ONLY_SUPPORTED (1u << 23) /* Since: 1.3.3; Deprecated: 1.5.5 */
#define FWUPD_DEVICE_FLAG_WILL_DISAPPEAR (1u << 24) /* Since: 1.3.3 */
#define FWUPD_DEVICE_FLAG_CAN_VERIFY (1u << 25) /* Since: 1.3.3 */
#define FWUPD_DEVICE_FLAG_CAN_VERIFY_IMAGE (1u << 26) /* Since: 1.3.3 */
@@ -160,13 +165,16 @@
#define FWUPD_DEVICE_FLAG_USABLE_DURING_UPDATE (1u << 29) /* Since: 1.3.3 */
#define FWUPD_DEVICE_FLAG_VERSION_CHECK_REQUIRED (1u << 30) /* Since: 1.3.7 */
#define FWUPD_DEVICE_FLAG_INSTALL_ALL_RELEASES (1u << 31) /* Since: 1.3.7 */
-#define FWUPD_DEVICE_FLAG_MD_SET_NAME (1llu << 32) /* Since: 1.4.0 */
-#define FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY (1llu << 33) /* Since: 1.4.0 */
-#define FWUPD_DEVICE_FLAG_MD_SET_VERFMT (1llu << 34) /* Since: 1.4.0 */
+#define FWUPD_DEVICE_FLAG_MD_SET_NAME (1llu << 32) /* Since: 1.4.0; Deprecated: 1.5.5 */
+#define FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY (1llu << 33) /* Since: 1.4.0; Deprecated: 1.5.5 */
+#define FWUPD_DEVICE_FLAG_MD_SET_VERFMT (1llu << 34) /* Since: 1.4.0; Deprecated: 1.5.5 */
#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_NO_GUID_MATCHING (1llu << 36) /* Since: 1.4.1; Deprecated: 1.5.8 */
#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_MD_SET_ICON (1llu << 41) /* Since: 1.5.2; Deprecated: 1.5.5 */
#define FWUPD_DEVICE_FLAG_UNKNOWN G_MAXUINT64 /* Since: 0.7.3 */
typedef guint64 FwupdDeviceFlags;
@@ -179,6 +187,7 @@
* @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 +198,7 @@
#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;
@@ -213,6 +223,38 @@
} 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)
+ * @FWUPD_PLUGIN_FLAG_REQUIRE_HWID: A specific HWID is required
+ *
+ * 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_REQUIRE_HWID (1u << 10) /* Since: 1.5.8 */
+#define FWUPD_PLUGIN_FLAG_UNKNOWN G_MAXUINT64 /* Since: 1.5.0 */
+typedef guint64 FwupdPluginFlags;
+
+/**
* FwupdInstallFlags:
* @FWUPD_INSTALL_FLAG_NONE: No flags set
* @FWUPD_INSTALL_FLAG_OFFLINE: Schedule this for next boot
@@ -220,8 +262,13 @@
* @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
+ * @FWUPD_INSTALL_FLAG_NO_SEARCH: Do not use heuristics when parsing the image
*
- * 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 +277,11 @@
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 */
+ FWUPD_INSTALL_FLAG_NO_SEARCH = 1 << 9, /* Since: 1.5.0 */
/*< private >*/
FWUPD_INSTALL_FLAG_LAST
} FwupdInstallFlags;
@@ -240,7 +292,7 @@
* @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 +387,8 @@
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);
diff -Nru fwupd-1.4.5/libfwupd/fwupd-enums-private.h fwupd-1.5.8/libfwupd/fwupd-enums-private.h
--- fwupd-1.4.5/libfwupd/fwupd-enums-private.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-enums-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,11 +1,13 @@
/*
- * Copyright (C) 2016-2018 Richard Hughes
+ * Copyright (C) 2016 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
+#include
+
G_BEGIN_DECLS
#define FWUPD_RESULT_KEY_APPSTREAM_ID "AppstreamId" /* s */
@@ -23,6 +25,8 @@
#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,12 +47,14 @@
#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 */
#define FWUPD_RESULT_KEY_UPDATE_ERROR "UpdateError" /* s */
#define FWUPD_RESULT_KEY_UPDATE_STATE "UpdateState" /* u */
#define FWUPD_RESULT_KEY_URI "Uri" /* s */
+#define FWUPD_RESULT_KEY_LOCATIONS "Locations" /* as */
#define FWUPD_RESULT_KEY_VENDOR_ID "VendorId" /* s */
#define FWUPD_RESULT_KEY_VENDOR "Vendor" /* s */
#define FWUPD_RESULT_KEY_VENDOR "Vendor" /* s */
diff -Nru fwupd-1.4.5/libfwupd/fwupd.h fwupd-1.5.8/libfwupd/fwupd.h
--- fwupd-1.4.5/libfwupd/fwupd.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd.h 2021-03-31 20:08:32.000000000 +0000
@@ -14,10 +14,13 @@
#define __FWUPD_H_INSIDE__
#include
+#include
#include
#include
+#include
#include
#include
+#include
#include
#include
#include
diff -Nru fwupd-1.4.5/libfwupd/fwupd.map fwupd-1.5.8/libfwupd/fwupd.map
--- fwupd-1.4.5/libfwupd/fwupd.map 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd.map 2021-03-31 20:08:32.000000000 +0000
@@ -468,3 +468,191 @@
fwupd_remote_load_signature_bytes;
local: *;
} LIBFWUPD_1.4.1;
+
+LIBFWUPD_1.4.6 {
+ global:
+ fwupd_client_get_blocked_firmware;
+ 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;
+
+LIBFWUPD_1.5.2 {
+ global:
+ fwupd_client_download_file;
+ fwupd_client_get_user_agent;
+ local: *;
+} LIBFWUPD_1.5.1;
+
+LIBFWUPD_1.5.3 {
+ global:
+ fwupd_client_get_main_context;
+ fwupd_client_set_main_context;
+ fwupd_remote_set_keyring_kind;
+ local: *;
+} LIBFWUPD_1.5.2;
+
+LIBFWUPD_1.5.5 {
+ global:
+ fwupd_device_add_vendor_id;
+ fwupd_device_get_vendor_ids;
+ fwupd_device_has_vendor_id;
+ local: *;
+} LIBFWUPD_1.5.3;
+
+LIBFWUPD_1.5.6 {
+ global:
+ fwupd_client_install_release2;
+ fwupd_client_install_release2_async;
+ fwupd_release_add_location;
+ fwupd_release_get_locations;
+ local: *;
+} LIBFWUPD_1.5.5;
+
+LIBFWUPD_1.5.8 {
+ global:
+ fwupd_device_add_protocol;
+ fwupd_device_get_protocols;
+ fwupd_device_has_protocol;
+ local: *;
+} LIBFWUPD_1.5.6;
diff -Nru fwupd-1.4.5/libfwupd/fwupd-plugin.c fwupd-1.5.8/libfwupd/fwupd-plugin.c
--- fwupd-1.4.5/libfwupd/fwupd-plugin.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-plugin.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#include
+
+#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);
+
+ /* not changed */
+ if (g_strcmp0 (priv->name, name) == 0)
+ return;
+
+ 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);
+}
diff -Nru fwupd-1.4.5/libfwupd/fwupd-plugin.h fwupd-1.5.8/libfwupd/fwupd-plugin.h
--- fwupd-1.4.5/libfwupd/fwupd-plugin.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-plugin.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include
+
+#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
diff -Nru fwupd-1.4.5/libfwupd/fwupd-plugin-private.h fwupd-1.5.8/libfwupd/fwupd-plugin-private.h
--- fwupd-1.4.5/libfwupd/fwupd-plugin-private.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-plugin-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include
+
+#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
+
diff -Nru fwupd-1.4.5/libfwupd/fwupd-release.c fwupd-1.5.8/libfwupd/fwupd-release.c
--- fwupd-1.4.5/libfwupd/fwupd-release.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-release.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -46,7 +46,8 @@
gchar *name;
gchar *name_variant_suffix;
gchar *summary;
- gchar *uri;
+ gchar *branch;
+ GPtrArray *locations;
gchar *vendor;
gchar *version;
gchar *remote_id;
@@ -98,6 +99,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->remote_id, remote_id) == 0)
+ return;
+
g_free (priv->remote_id);
priv->remote_id = g_strdup (remote_id);
}
@@ -134,6 +140,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->version, version) == 0)
+ return;
+
g_free (priv->version);
priv->version = g_strdup (version);
}
@@ -170,6 +181,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->filename, filename) == 0)
+ return;
+
g_free (priv->filename);
priv->filename = g_strdup (filename);
}
@@ -206,6 +222,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->update_message, update_message) == 0)
+ return;
+
g_free (priv->update_message);
priv->update_message = g_strdup (update_message);
}
@@ -242,6 +263,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->update_image, update_image) == 0)
+ return;
+
g_free (priv->update_image);
priv->update_image = g_strdup (update_image);
}
@@ -278,6 +304,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->protocol, protocol) == 0)
+ return;
+
g_free (priv->protocol);
priv->protocol = g_strdup (protocol);
}
@@ -544,18 +575,21 @@
* fwupd_release_get_uri:
* @release: A #FwupdRelease
*
- * Gets the update uri.
+ * Gets the default update URI.
*
- * Returns: the update uri, or %NULL if unset
+ * Returns: the update URI, or %NULL if unset
*
* Since: 0.9.3
+ * Deprecated: 1.5.6: Use fwupd_release_get_locations() instead.
**/
const gchar *
fwupd_release_get_uri (FwupdRelease *release)
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_val_if_fail (FWUPD_IS_RELEASE (release), NULL);
- return priv->uri;
+ if (priv->locations->len == 0)
+ return NULL;
+ return (const gchar *) g_ptr_array_index (priv->locations, 0);
}
/**
@@ -563,17 +597,62 @@
* @release: A #FwupdRelease
* @uri: the update URI
*
- * Sets the update uri, i.e. where you can download the firmware from.
+ * Sets the update URI, i.e. where you can download the firmware from.
*
* Since: 0.9.3
+ * Deprecated: 1.5.6: Use fwupd_release_add_location() instead.
**/
void
fwupd_release_set_uri (FwupdRelease *release, const gchar *uri)
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
- g_free (priv->uri);
- priv->uri = g_strdup (uri);
+ g_ptr_array_set_size (priv->locations, 0);
+ g_ptr_array_add (priv->locations, g_strdup (uri));
+}
+
+/**
+ * fwupd_release_get_locations:
+ * @release: A #FwupdRelease
+ *
+ * Gets the update URI, i.e. where you can download the firmware from.
+ *
+ * Typically the first URI will be the main HTTP mirror, but all URIs may not
+ * be valid HTTP URIs. For example, "ipns://QmSrPmba" is valid here.
+ *
+ * Returns: (element-type utf8) (transfer none): the URIs
+ *
+ * Since: 1.5.6
+ **/
+GPtrArray *
+fwupd_release_get_locations (FwupdRelease *release)
+{
+ FwupdReleasePrivate *priv = GET_PRIVATE (release);
+ g_return_val_if_fail (FWUPD_IS_RELEASE (release), NULL);
+ return priv->locations;
+}
+
+/**
+ * fwupd_release_add_location:
+ * @release: A #FwupdRelease
+ * @location: the update URI
+ *
+ * Adds an update URI, i.e. where you can download the firmware from.
+ *
+ * Since: 1.5.6
+ **/
+void
+fwupd_release_add_location (FwupdRelease *release, const gchar *location)
+{
+ FwupdReleasePrivate *priv = GET_PRIVATE (release);
+ g_return_if_fail (FWUPD_IS_RELEASE (release));
+ g_return_if_fail (location != NULL);
+ for (guint i = 0; i < priv->locations->len; i++) {
+ const gchar *location_tmp = g_ptr_array_index (priv->locations, i);
+ if (g_strcmp0 (location_tmp, location) == 0)
+ return;
+ }
+ g_ptr_array_add (priv->locations, g_strdup (location));
}
/**
@@ -608,6 +687,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->homepage, homepage) == 0)
+ return;
+
g_free (priv->homepage);
priv->homepage = g_strdup (homepage);
}
@@ -644,6 +728,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->details_url, details_url) == 0)
+ return;
+
g_free (priv->details_url);
priv->details_url = g_strdup (details_url);
}
@@ -680,6 +769,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->source_url, source_url) == 0)
+ return;
+
g_free (priv->source_url);
priv->source_url = g_strdup (source_url);
}
@@ -716,6 +810,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->description, description) == 0)
+ return;
+
g_free (priv->description);
priv->description = g_strdup (description);
}
@@ -752,6 +851,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->appstream_id, appstream_id) == 0)
+ return;
+
g_free (priv->appstream_id);
priv->appstream_id = g_strdup (appstream_id);
}
@@ -788,6 +892,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->detach_caption, detach_caption) == 0)
+ return;
+
g_free (priv->detach_caption);
priv->detach_caption = g_strdup (detach_caption);
}
@@ -824,6 +933,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->detach_image, detach_image) == 0)
+ return;
+
g_free (priv->detach_image);
priv->detach_image = g_strdup (detach_image);
}
@@ -930,11 +1044,57 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->summary, summary) == 0)
+ return;
+
g_free (priv->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));
+
+ /* not changed */
+ if (g_strcmp0 (priv->branch, branch) == 0)
+ return;
+
+ g_free (priv->branch);
+ priv->branch = g_strdup (branch);
+}
+
+/**
* fwupd_release_get_vendor:
* @release: A #FwupdRelease
*
@@ -966,6 +1126,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->vendor, vendor) == 0)
+ return;
+
g_free (priv->vendor);
priv->vendor = g_strdup (vendor);
}
@@ -1002,6 +1167,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->license, license) == 0)
+ return;
+
g_free (priv->license);
priv->license = g_strdup (license);
}
@@ -1038,6 +1208,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->name, name) == 0)
+ return;
+
g_free (priv->name);
priv->name = g_strdup (name);
}
@@ -1074,6 +1249,11 @@
{
FwupdReleasePrivate *priv = GET_PRIVATE (release);
g_return_if_fail (FWUPD_IS_RELEASE (release));
+
+ /* not changed */
+ if (g_strcmp0 (priv->name_variant_suffix, name_variant_suffix) == 0)
+ return;
+
g_free (priv->name_variant_suffix);
priv->name_variant_suffix = g_strdup (name_variant_suffix);
}
@@ -1354,6 +1534,11 @@
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,
@@ -1387,10 +1572,15 @@
FWUPD_RESULT_KEY_CHECKSUM,
g_variant_new_string (str->str));
}
- if (priv->uri != NULL) {
+ if (priv->locations->len > 0) {
+ g_variant_builder_add (&builder, "{sv}",
+ FWUPD_RESULT_KEY_LOCATIONS,
+ g_variant_new_strv ((const gchar * const*) priv->locations->pdata,
+ priv->locations->len));
+ /* for compatibilty */
g_variant_builder_add (&builder, "{sv}",
FWUPD_RESULT_KEY_URI,
- g_variant_new_string (priv->uri));
+ g_variant_new_string (g_ptr_array_index (priv->locations, 0)));
}
if (priv->homepage != NULL) {
g_variant_builder_add (&builder, "{sv}",
@@ -1492,6 +1682,10 @@
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;
@@ -1515,8 +1709,14 @@
fwupd_release_add_checksum (release, split[i]);
return;
}
+ if (g_strcmp0 (key, FWUPD_RESULT_KEY_LOCATIONS) == 0) {
+ g_autofree const gchar **strv = g_variant_get_strv (value, NULL);
+ for (guint i = 0; strv[i] != NULL; i++)
+ fwupd_release_add_location (release, strv[i]);
+ return;
+ }
if (g_strcmp0 (key, FWUPD_RESULT_KEY_URI) == 0) {
- fwupd_release_set_uri (release, g_variant_get_string (value, NULL));
+ fwupd_release_add_location (release, g_variant_get_string (value, NULL));
return;
}
if (g_strcmp0 (key, FWUPD_RESULT_KEY_HOMEPAGE) == 0) {
@@ -1675,6 +1875,7 @@
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);
@@ -1708,7 +1909,18 @@
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_LICENSE, priv->license);
fwupd_release_json_add_int (builder, FWUPD_RESULT_KEY_SIZE, priv->size);
fwupd_release_json_add_int (builder, FWUPD_RESULT_KEY_CREATED, priv->created);
- fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_URI, priv->uri);
+ if (priv->locations->len > 0) {
+ json_builder_set_member_name (builder, FWUPD_RESULT_KEY_LOCATIONS);
+ json_builder_begin_array (builder);
+ for (guint i = 0; i < priv->locations->len; i++) {
+ const gchar *location = g_ptr_array_index (priv->locations, i);
+ json_builder_add_string_value (builder, location);
+ }
+ json_builder_end_array (builder);
+ /* for compatibilty */
+ fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_URI,
+ (const gchar *) g_ptr_array_index (priv->locations, 0));
+ }
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_HOMEPAGE, priv->homepage);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_DETAILS_URL, priv->details_url);
fwupd_release_json_add_string (builder, FWUPD_RESULT_KEY_SOURCE_URL, priv->source_url);
@@ -1764,6 +1976,7 @@
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);
@@ -1783,7 +1996,10 @@
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_LICENSE, priv->license);
fwupd_pad_kv_siz (str, FWUPD_RESULT_KEY_SIZE, priv->size);
fwupd_pad_kv_unx (str, FWUPD_RESULT_KEY_CREATED, priv->created);
- fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_URI, priv->uri);
+ for (guint i = 0; i < priv->locations->len; i++) {
+ const gchar *location = g_ptr_array_index (priv->locations, i);
+ fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_URI, location);
+ }
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_HOMEPAGE, priv->homepage);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_DETAILS_URL, priv->details_url);
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_SOURCE_URL, priv->source_url);
@@ -1798,7 +2014,7 @@
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_DETACH_IMAGE, priv->detach_image);
if (priv->update_message != NULL)
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_UPDATE_MESSAGE, priv->update_message);
- if (priv->update_message != NULL)
+ if (priv->update_image != NULL)
fwupd_pad_kv_str (str, FWUPD_RESULT_KEY_UPDATE_IMAGE, priv->update_image);
/* metadata */
keys = g_hash_table_get_keys (priv->metadata);
@@ -1825,6 +2041,7 @@
priv->categories = g_ptr_array_new_with_free_func (g_free);
priv->issues = g_ptr_array_new_with_free_func (g_free);
priv->checksums = g_ptr_array_new_with_free_func (g_free);
+ priv->locations = g_ptr_array_new_with_free_func (g_free);
priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
@@ -1844,7 +2061,8 @@
g_free (priv->name);
g_free (priv->name_variant_suffix);
g_free (priv->summary);
- g_free (priv->uri);
+ g_free (priv->branch);
+ g_ptr_array_unref (priv->locations);
g_free (priv->homepage);
g_free (priv->details_url);
g_free (priv->source_url);
diff -Nru fwupd-1.4.5/libfwupd/fwupd-release.h fwupd-1.5.8/libfwupd/fwupd-release.h
--- fwupd-1.4.5/libfwupd/fwupd-release.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-release.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -34,9 +34,14 @@
const gchar *fwupd_release_get_version (FwupdRelease *release);
void fwupd_release_set_version (FwupdRelease *release,
const gchar *version);
+G_DEPRECATED_FOR(fwupd_release_get_locations)
const gchar *fwupd_release_get_uri (FwupdRelease *release);
+G_DEPRECATED_FOR(fwupd_release_add_location)
void fwupd_release_set_uri (FwupdRelease *release,
const gchar *uri);
+GPtrArray *fwupd_release_get_locations (FwupdRelease *release);
+void fwupd_release_add_location (FwupdRelease *release,
+ const gchar *location);
GPtrArray *fwupd_release_get_issues (FwupdRelease *release);
void fwupd_release_add_issue (FwupdRelease *release,
const gchar *issue);
@@ -90,6 +95,9 @@
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);
diff -Nru fwupd-1.4.5/libfwupd/fwupd-remote.c fwupd-1.5.8/libfwupd/fwupd-remote.c
--- fwupd-1.4.5/libfwupd/fwupd-remote.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-remote.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,12 +1,14 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
-#include
+#ifdef HAVE_LIBCURL
+#include
+#endif
#include
#include "fwupd-deprecated.h"
@@ -32,6 +34,7 @@
gchar *id;
gchar *firmware_base_uri;
gchar *report_uri;
+ gchar *security_report_uri;
gchar *metadata_uri;
gchar *metadata_uri_sig;
gchar *username;
@@ -50,6 +53,7 @@
gchar **order_before;
gchar *remotes_dir;
gboolean automatic_reports;
+ gboolean automatic_security_reports;
} FwupdRemotePrivate;
enum {
@@ -58,12 +62,19 @@
PROP_ENABLED,
PROP_APPROVAL_REQUIRED,
PROP_AUTOMATIC_REPORTS,
+ PROP_AUTOMATIC_SECURITY_REPORTS,
PROP_LAST
};
G_DEFINE_TYPE_WITH_PRIVATE (FwupdRemote, fwupd_remote, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fwupd_remote_get_instance_private (o))
+#ifdef HAVE_LIBCURL_7_62_0
+typedef gchar curlptr;
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(curlptr, curl_free)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURLU, curl_url_cleanup)
+#endif
+
static void
fwupd_remote_set_username (FwupdRemote *self, const gchar *username)
{
@@ -77,6 +88,11 @@
fwupd_remote_set_title (FwupdRemote *self, const gchar *title)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->title, title) == 0)
+ return;
+
g_free (priv->title);
priv->title = g_strdup (title);
}
@@ -94,6 +110,11 @@
fwupd_remote_set_agreement (FwupdRemote *self, const gchar *agreement)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->agreement, agreement) == 0)
+ return;
+
g_free (priv->agreement);
priv->agreement = g_strdup (agreement);
}
@@ -102,6 +123,11 @@
fwupd_remote_set_checksum (FwupdRemote *self, const gchar *checksum)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->checksum, checksum) == 0)
+ return;
+
g_free (priv->checksum);
priv->checksum = g_strdup (checksum);
}
@@ -110,8 +136,14 @@
fwupd_remote_set_password (FwupdRemote *self, const gchar *password)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->password, password) == 0)
+ return;
+
if (password != NULL && password[0] == '\0')
password = NULL;
+ g_free (priv->password);
priv->password = g_strdup (password);
}
@@ -122,7 +154,16 @@
priv->kind = kind;
}
-static void
+/**
+ * fwupd_remote_set_keyring_kind:
+ * @self: A #FwupdRemote
+ * @keyring_kind: #FwupdKeyringKind e.g. #FWUPD_KEYRING_KIND_PKCS7
+ *
+ * Sets the keyring kind
+ *
+ * Since: 1.5.3
+ **/
+void
fwupd_remote_set_keyring_kind (FwupdRemote *self, FwupdKeyringKind keyring_kind)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
@@ -134,6 +175,11 @@
fwupd_remote_set_id (FwupdRemote *self, const gchar *id)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+
+ /* not changed */
+ if (g_strcmp0 (priv->id, id) == 0)
+ return;
+
g_free (priv->id);
priv->id = g_strdup (id);
g_strdelimit (priv->id, ".", '\0');
@@ -143,64 +189,71 @@
fwupd_remote_set_filename_source (FwupdRemote *self, const gchar *filename_source)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+ if (priv->filename_source == filename_source)
+ return;
g_free (priv->filename_source);
priv->filename_source = g_strdup (filename_source);
}
-static SoupURI *
+static const gchar *
+fwupd_remote_get_suffix_for_keyring_kind (FwupdKeyringKind keyring_kind)
+{
+ if (keyring_kind == FWUPD_KEYRING_KIND_JCAT)
+ return ".jcat";
+ if (keyring_kind == FWUPD_KEYRING_KIND_GPG)
+ return ".asc";
+ if (keyring_kind == FWUPD_KEYRING_KIND_PKCS7)
+ return ".p7b";
+ return NULL;
+}
+
+static gchar *
fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
- SoupURI *uri;
-
- g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
- g_return_val_if_fail (url != NULL, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+#ifdef HAVE_LIBCURL_7_62_0
+ g_autoptr(curlptr) tmp_uri = NULL;
+ g_autoptr(CURLU) uri = curl_url ();
/* create URI, substituting if required */
if (priv->firmware_base_uri != NULL) {
- g_autoptr(SoupURI) uri_tmp = NULL;
g_autofree gchar *basename = NULL;
- g_autofree gchar *url2 = NULL;
- uri_tmp = soup_uri_new (url);
- if (uri_tmp == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "Failed to parse URI '%s'", url);
- return NULL;
- }
- basename = g_path_get_basename (soup_uri_get_path (uri_tmp));
- url2 = g_build_filename (priv->firmware_base_uri, basename, NULL);
- uri = soup_uri_new (url2);
- if (uri == NULL) {
+ g_autofree gchar *path_new = NULL;
+ g_autoptr(curlptr) path = NULL;
+ g_autoptr(CURLU) uri_tmp = curl_url ();
+ if (curl_url_set (uri_tmp, CURLUPART_URL, url, 0) != CURLUE_OK) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
- "Failed to parse URI '%s'", url2);
+ "Failed to parse url '%s'", url);
return NULL;
}
+ curl_url_get (uri_tmp, CURLUPART_PATH, &path, 0);
+ basename = g_path_get_basename (path);
+ path_new = g_build_filename (priv->firmware_base_uri, basename, NULL);
+ curl_url_set (uri, CURLUPART_URL, path_new, 0);
/* use the base URI of the metadata to build the full path */
} else if (g_strstr_len (url, -1, "/") == NULL) {
g_autofree gchar *basename = NULL;
- g_autofree gchar *path = NULL;
- uri = soup_uri_new (priv->metadata_uri);
- if (uri == NULL) {
+ g_autofree gchar *path_new = NULL;
+ g_autoptr(curlptr) path = NULL;
+ if (curl_url_set (uri, CURLUPART_URL, priv->metadata_uri, 0) != CURLUE_OK) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
- "Failed to parse metadata URI '%s'", url);
+ "Failed to parse url '%s'",
+ priv->metadata_uri);
return NULL;
}
- basename = g_path_get_dirname (soup_uri_get_path (uri));
- path = g_build_filename (basename, url, NULL);
- soup_uri_set_path (uri, path);
+ curl_url_get (uri, CURLUPART_PATH, &path, 0);
+ basename = g_path_get_dirname (path);
+ path_new = g_build_filename (basename, url, NULL);
+ curl_url_set (uri, CURLUPART_URL, path_new, 0);
/* a normal URI */
} else {
- uri = soup_uri_new (url);
- if (uri == NULL) {
+ if (curl_url_set (uri, CURLUPART_URL, url, 0) != CURLUE_OK) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
@@ -211,10 +264,22 @@
/* set the username and password */
if (priv->username != NULL)
- soup_uri_set_user (uri, priv->username);
+ curl_url_set (uri, CURLUPART_USER, priv->username, 0);
if (priv->password != NULL)
- soup_uri_set_password (uri, priv->password);
- return uri;
+ curl_url_set (uri, CURLUPART_PASSWORD, priv->password, 0);
+ curl_url_get (uri, CURLUPART_URL, &tmp_uri, 0);
+ return g_strdup (tmp_uri);
+#else
+ if (priv->firmware_base_uri != NULL) {
+ g_autofree gchar *basename = g_path_get_basename (url);
+ return g_build_filename (priv->firmware_base_uri, basename, NULL);
+ }
+ if (g_strstr_len (url, -1, "/") == NULL) {
+ g_autofree gchar *basename = g_path_get_dirname (priv->metadata_uri);
+ return g_build_filename (basename, url, NULL);
+ }
+ return g_strdup (url);
+#endif
}
/* note, this has to be set before username and password */
@@ -222,19 +287,15 @@
fwupd_remote_set_metadata_uri (FwupdRemote *self, const gchar *metadata_uri)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
- g_autoptr(SoupURI) uri = NULL;
-
- /* build the URI */
- uri = soup_uri_new (metadata_uri);
- if (uri == NULL)
- return;
+ const gchar *suffix;
/* save this so we can export the object as a GVariant */
priv->metadata_uri = g_strdup (metadata_uri);
/* generate the signature URI too */
- if (priv->keyring_kind == FWUPD_KEYRING_KIND_JCAT)
- priv->metadata_uri_sig = g_strconcat (metadata_uri, ".jcat", NULL);
+ suffix = fwupd_remote_get_suffix_for_keyring_kind (priv->keyring_kind);
+ if (suffix != NULL)
+ priv->metadata_uri_sig = g_strconcat (metadata_uri, suffix, NULL);
}
/* note, this has to be set after MetadataURI */
@@ -252,6 +313,13 @@
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`
@@ -300,16 +368,22 @@
fwupd_remote_set_filename_cache (FwupdRemote *self, const gchar *filename)
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
+ const gchar *suffix;
g_return_if_fail (FWUPD_IS_REMOTE (self));
+ /* not changed */
+ if (g_strcmp0 (priv->filename_cache, filename) == 0)
+ return;
+
g_free (priv->filename_cache);
priv->filename_cache = g_strdup (filename);
/* create for all remote types */
- if (priv->keyring_kind == FWUPD_KEYRING_KIND_JCAT) {
+ suffix = fwupd_remote_get_suffix_for_keyring_kind (priv->keyring_kind);
+ if (suffix != NULL) {
g_free (priv->filename_cache_sig);
- priv->filename_cache_sig = g_strconcat (filename, ".jcat", NULL);
+ priv->filename_cache_sig = g_strconcat (filename, suffix, NULL);
}
}
@@ -343,6 +417,7 @@
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);
@@ -373,11 +448,6 @@
keyring_kind);
return FALSE;
}
- if (priv->keyring_kind == FWUPD_KEYRING_KIND_GPG ||
- priv->keyring_kind == FWUPD_KEYRING_KIND_PKCS7) {
- g_debug ("converting Keyring value to Jcat");
- priv->keyring_kind = FWUPD_KEYRING_KIND_JCAT;
- }
}
/* all remotes need a URI, even if it's file:// to the cache */
@@ -394,7 +464,9 @@
else
priv->kind = FWUPD_REMOTE_KIND_LOCAL;
} else if (g_str_has_prefix (metadata_uri, "http://") ||
- g_str_has_prefix (metadata_uri, "https://")) {
+ g_str_has_prefix (metadata_uri, "https://") ||
+ g_str_has_prefix (metadata_uri, "ipfs://") ||
+ g_str_has_prefix (metadata_uri, "ipns://")) {
priv->kind = FWUPD_REMOTE_KIND_DOWNLOAD;
} else {
g_set_error (error,
@@ -415,8 +487,14 @@
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) {
@@ -693,6 +771,11 @@
{
FwupdRemotePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FWUPD_IS_REMOTE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->remotes_dir, directory) == 0)
+ return;
+
g_free (priv->remotes_dir);
priv->remotes_dir = g_strdup (directory);
}
@@ -855,10 +938,10 @@
gchar *
fwupd_remote_build_firmware_uri (FwupdRemote *self, const gchar *url, GError **error)
{
- g_autoptr(SoupURI) uri = fwupd_remote_build_uri (self, url, error);
- if (uri == NULL)
- return NULL;
- return soup_uri_to_string (uri, FALSE);
+ g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
+ g_return_val_if_fail (url != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return fwupd_remote_build_uri (self, url, error);
}
/**
@@ -880,6 +963,24 @@
}
/**
+ * 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
*
@@ -948,6 +1049,9 @@
*
* Parses the signature, updating the metadata URI as appropriate.
*
+ * This can only be called for remotes with `Keyring=jcat` which is
+ * the default for most remotes.
+ *
* Returns: %TRUE for success
*
* Since: 1.4.5
@@ -955,6 +1059,7 @@
gboolean
fwupd_remote_load_signature_bytes (FwupdRemote *self, GBytes *bytes, GError **error)
{
+ FwupdRemotePrivate *priv = GET_PRIVATE (self);
g_autoptr(GInputStream) istr = NULL;
g_autoptr(JcatFile) jcat_file = jcat_file_new ();
@@ -962,6 +1067,15 @@
g_return_val_if_fail (bytes != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ /* sanity check */
+ if (priv->keyring_kind != FWUPD_KEYRING_KIND_JCAT) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "only supported for JCat remotes");
+ return FALSE;
+ }
+
istr = g_memory_input_stream_new_from_bytes (bytes);
if (!jcat_file_import_stream (jcat_file, istr, JCAT_IMPORT_FLAG_NONE, NULL, error))
return FALSE;
@@ -1070,6 +1184,24 @@
}
/**
+ * 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 +1265,8 @@
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 +1291,8 @@
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 +1349,10 @@
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 +1391,8 @@
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 +1416,9 @@
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 +1445,9 @@
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 +1508,17 @@
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 +1537,7 @@
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);
diff -Nru fwupd-1.4.5/libfwupd/fwupd-remote.h fwupd-1.5.8/libfwupd/fwupd-remote.h
--- fwupd-1.4.5/libfwupd/fwupd-remote.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-remote.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -60,24 +60,29 @@
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);
FwupdKeyringKind fwupd_remote_get_keyring_kind (FwupdRemote *self);
gchar *fwupd_remote_build_firmware_uri (FwupdRemote *self,
const gchar *url,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fwupd_remote_load_signature (FwupdRemote *self,
const gchar *filename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fwupd_remote_load_signature_bytes (FwupdRemote *self,
GBytes *bytes,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FwupdRemote *fwupd_remote_from_variant (GVariant *value);
GPtrArray *fwupd_remote_array_from_variant (GVariant *value);
diff -Nru fwupd-1.4.5/libfwupd/fwupd-remote-private.h fwupd-1.5.8/libfwupd/fwupd-remote-private.h
--- fwupd-1.4.5/libfwupd/fwupd-remote-private.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-remote-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -26,4 +26,7 @@
void fwupd_remote_set_remotes_dir (FwupdRemote *self,
const gchar *directory);
+void fwupd_remote_set_keyring_kind (FwupdRemote *self,
+ FwupdKeyringKind keyring_kind);
+
G_END_DECLS
diff -Nru fwupd-1.4.5/libfwupd/fwupd-security-attr.c fwupd-1.5.8/libfwupd/fwupd-security-attr.c
--- fwupd-1.4.5/libfwupd/fwupd-security-attr.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-security-attr.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,936 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#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));
+
+ /* not changed */
+ if (g_strcmp0 (priv->appstream_id, appstream_id) == 0)
+ return;
+
+ /* 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));
+
+ /* not changed */
+ if (g_strcmp0 (priv->name, name) == 0)
+ return;
+
+ 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));
+
+ /* not changed */
+ if (g_strcmp0 (priv->plugin, plugin) == 0)
+ return;
+
+ 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));
+
+ /* not changed */
+ if (g_strcmp0 (priv->url, url) == 0)
+ return;
+
+ 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);
+}
diff -Nru fwupd-1.4.5/libfwupd/fwupd-security-attr.h fwupd-1.5.8/libfwupd/fwupd-security-attr.h
--- fwupd-1.4.5/libfwupd/fwupd-security-attr.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-security-attr.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include
+
+#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
diff -Nru fwupd-1.4.5/libfwupd/fwupd-security-attr-private.h fwupd-1.5.8/libfwupd/fwupd-security-attr-private.h
--- fwupd-1.4.5/libfwupd/fwupd-security-attr-private.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-security-attr-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include
+#include
+
+#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 */
+#define FWUPD_SECURITY_ATTR_ID_UEFI_PK "org.fwupd.hsi.Uefi.Pk" /* Since: 1.5.5 */
+
+GVariant *fwupd_security_attr_to_variant (FwupdSecurityAttr *self);
+void fwupd_security_attr_to_json (FwupdSecurityAttr *self,
+ JsonBuilder *builder);
+
+G_END_DECLS
+
diff -Nru fwupd-1.4.5/libfwupd/fwupd-self-test.c fwupd-1.5.8/libfwupd/fwupd-self-test.c
--- fwupd-1.4.5/libfwupd/fwupd-self-test.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-self-test.c 2021-03-31 20:08:32.000000000 +0000
@@ -7,11 +7,13 @@
#include "config.h"
#include
+#include
#ifdef HAVE_FNMATCH_H
#include
#endif
#include "fwupd-client.h"
+#include "fwupd-client-sync.h"
#include "fwupd-common.h"
#include "fwupd-enums.h"
#include "fwupd-error.h"
@@ -147,6 +149,12 @@
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
@@ -322,7 +330,7 @@
dev = fwupd_device_new ();
fwupd_device_add_checksum (dev, "beefdead");
fwupd_device_set_created (dev, 1);
- fwupd_device_set_flags (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
+ fwupd_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
fwupd_device_set_id (dev, "USB:foo");
fwupd_device_set_modified (dev, 60 * 60 * 24);
fwupd_device_set_name (dev, "ColorHug2");
@@ -330,7 +338,11 @@
fwupd_device_add_guid (dev, "00000000-0000-0000-0000-000000000000");
fwupd_device_add_icon (dev, "input-gaming");
fwupd_device_add_icon (dev, "input-mouse");
- fwupd_device_add_flag (dev, FWUPD_DEVICE_FLAG_REQUIRE_AC);
+ fwupd_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE |
+ FWUPD_DEVICE_FLAG_REQUIRE_AC);
+ g_assert_true (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_REQUIRE_AC));
+ g_assert_true (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE));
+ g_assert_false (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_HISTORICAL));
rel = fwupd_release_new ();
fwupd_release_add_flag (rel, FWUPD_RELEASE_FLAG_TRUSTED_PAYLOAD);
fwupd_release_add_checksum (rel, "deadbeef");
@@ -338,7 +350,8 @@
fwupd_release_set_filename (rel, "firmware.bin");
fwupd_release_set_appstream_id (rel, "org.dave.ColorHug.firmware");
fwupd_release_set_size (rel, 1024);
- fwupd_release_set_uri (rel, "http://foo.com");
+ fwupd_release_add_location (rel, "http://foo.com");
+ fwupd_release_add_location (rel, "ftp://foo.com");
fwupd_release_set_version (rel, "1.2.3");
fwupd_device_add_release (dev, rel);
str = fwupd_device_to_string (dev);
@@ -372,6 +385,7 @@
" Checksum: SHA1(deadbeef)\n"
" Size: 1.0 kB\n"
" Uri: http://foo.com\n"
+ " Uri: ftp://foo.com\n"
" Flags: trusted-payload\n", &error);
g_assert_no_error (error);
g_assert (ret);
@@ -418,6 +432,10 @@
" \"deadbeef\"\n"
" ],\n"
" \"Size\" : 1024,\n"
+ " \"Locations\" : [\n"
+ " \"http://foo.com\",\n"
+ " \"ftp://foo.com\"\n"
+ " ],\n"
" \"Uri\" : \"http://foo.com\",\n"
" \"Flags\" : [\n"
" \"trusted-payload\"\n"
@@ -532,7 +550,6 @@
g_assert_no_error (error);
g_assert (remote2 != NULL);
g_assert_cmpstr (fwupd_remote_get_id (remote2), ==, "lvfs");
- g_assert (fwupd_remote_get_enabled (remote2));
g_assert (fwupd_remote_get_metadata_uri (remote2) != NULL);
/* check we set an error when unfound */
diff -Nru fwupd-1.4.5/libfwupd/fwupd-thread-test.c fwupd-1.5.8/libfwupd/fwupd-thread-test.c
--- fwupd-1.4.5/libfwupd/fwupd-thread-test.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupd/fwupd-thread-test.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2020 Philip Withnall
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include
+
+typedef struct {
+ GApplication *app;
+ FwupdClient *client;
+ GPtrArray *worker_threads;
+} FuThreadTestSelf;
+
+static gboolean
+fwupd_thread_test_exit_idle_cb (gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_application_release (self->app);
+ return G_SOURCE_REMOVE;
+}
+
+static gpointer
+fwupd_thread_test_thread_cb (gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_autoptr(GError) error_local = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GMainContext) context = g_main_context_new ();
+ g_autoptr(GMainContextPusher) pusher = g_main_context_pusher_new (context);
+
+ g_assert (pusher != NULL);
+ g_message ("Calling fwupd_client_get_devices() in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+ devices = fwupd_client_get_devices (self->client, NULL, &error_local);
+ if (devices == NULL)
+ g_warning ("%s", error_local->message);
+ g_idle_add (fwupd_thread_test_exit_idle_cb, self);
+ return NULL;
+}
+
+static gboolean
+fwupd_thread_test_idle_cb (gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+
+ g_message ("fwupd_thread_test_idle_cb() in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+
+ /* create 'n' threads with a small delay, and 'n-1' references on the app */
+ for (guint i = 0; i < 30; i++) {
+ g_autofree gchar *thread_str = g_strdup_printf ("worker%02u", i);
+ GThread *thread = g_thread_new (thread_str,
+ fwupd_thread_test_thread_cb,
+ self);
+ g_usleep (g_random_int_range (0, 1000));
+ g_ptr_array_add (self->worker_threads, thread);
+ if (i > 0)
+ g_application_hold (self->app);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+fwupd_thread_test_activate_cb (GApplication *app, gpointer user_data)
+{
+ FuThreadTestSelf *self = user_data;
+ g_application_hold (self->app);
+ g_idle_add (fwupd_thread_test_idle_cb, self);
+}
+
+static gboolean
+fwupd_thread_test_has_system_bus (void)
+{
+ g_autoptr(GDBusConnection) conn = NULL;
+ conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+ return conn != NULL;
+}
+
+int
+main (void)
+{
+ gint retval;
+ g_autoptr(FwupdClient) client = fwupd_client_new ();
+ g_autoptr(GApplication) app = g_application_new ("org.test.Test", G_APPLICATION_FLAGS_NONE);
+ g_autoptr(GPtrArray) worker_threads = g_ptr_array_new ();
+ FuThreadTestSelf self = { app, client, worker_threads };
+
+ /* only some of the CI targets have a DBus daemon */
+ if (!fwupd_thread_test_has_system_bus ()) {
+ g_message ("D-Bus system bus unavailable, skipping tests.");
+ return 0;
+ }
+
+ g_message ("Created FwupdClient in thread %p with main context %p",
+ g_thread_self (), g_main_context_get_thread_default ());
+ g_signal_connect (app, "activate",
+ G_CALLBACK (fwupd_thread_test_activate_cb), &self);
+ retval = g_application_run (app, 0, NULL);
+ for (guint i = 0; i < self.worker_threads->len; i++) {
+ GThread *thread = g_ptr_array_index (self.worker_threads, i);
+ g_thread_join (thread);
+ }
+
+ return retval;
+}
diff -Nru fwupd-1.4.5/libfwupd/meson.build fwupd-1.5.8/libfwupd/meson.build
--- fwupd-1.4.5/libfwupd/meson.build 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/meson.build 2021-03-31 20:08:32.000000000 +0000
@@ -1,7 +1,3 @@
-cargs = [
- '-DG_LOG_DOMAIN="Fwupd"',
-]
-
fwupd_version_h = configure_file(
input : 'fwupd-version.h.in',
output : 'fwupd-version.h',
@@ -15,41 +11,55 @@
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',
)
+libfwupd_deps = [
+ giounix,
+ gmodule,
+ libjcat,
+ libjsonglib,
+]
+
+if get_option('curl')
+ libfwupd_deps += libcurl
+endif
+
+libfwupd_src = [
+ 'fwupd-client.c',
+ 'fwupd-client-sync.c',
+ 'fwupd-common.c', # fuzzing
+ 'fwupd-device.c', # fuzzing
+ 'fwupd-enums.c', # fuzzing
+ 'fwupd-error.c', # fuzzing
+ 'fwupd-security-attr.c',
+ 'fwupd-release.c', # fuzzing
+ 'fwupd-plugin.c',
+ 'fwupd-remote.c',
+]
+
fwupd_mapfile = 'fwupd.map'
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), fwupd_mapfile)
-fwupd = shared_library(
+fwupd = library(
'fwupd',
- sources : [
- 'fwupd-client.c',
- 'fwupd-common.c',
- 'fwupd-device.c',
- 'fwupd-enums.c',
- 'fwupd-error.c',
- 'fwupd-release.c',
- 'fwupd-remote.c',
- ],
+ sources : libfwupd_src,
soversion : libfwupd_lt_current,
version : libfwupd_lt_version,
- dependencies : [
- giounix,
- soup,
- libjcat,
- libjsonglib,
- ],
+ dependencies : libfwupd_deps,
c_args : [
- cargs,
+ '-DG_LOG_DOMAIN="Fwupd"',
'-DLOCALSTATEDIR="' + localstatedir + '"',
],
include_directories : root_incdir,
@@ -58,9 +68,15 @@
install : true
)
+libfwupd_dep = declare_dependency(
+ link_with : fwupd,
+ include_directories : [root_incdir, include_directories('.')],
+ dependencies : libfwupd_deps
+)
+
pkgg = import('pkgconfig')
pkgg.generate(
- libraries : fwupd,
+ fwupd,
requires : [ 'gio-2.0' ],
subdirs : 'fwupd-1',
version : meson.project_version(),
@@ -70,10 +86,18 @@
)
if get_option('introspection')
+ fwupd_gir_deps = [
+ giounix,
+ ]
+ if get_option('curl')
+ fwupd_gir_deps += libcurl
+ endif
fwupd_gir = gnome.generate_gir(fwupd,
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 +109,15 @@
'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',
@@ -98,21 +128,17 @@
identifier_prefix : 'Fwupd',
export_packages : 'fwupd',
header : 'fwupd.h',
- dependencies : [
- giounix,
- soup,
- ],
+ dependencies : fwupd_gir_deps,
includes : [
'Gio-2.0',
'GObject-2.0',
- 'Soup-2.4',
],
install : true
)
gnome.generate_vapi('fwupd',
sources : fwupd_gir[0],
- packages : ['gio-2.0', 'libsoup-2.4'],
+ packages : ['gio-2.0'],
install : true,
)
@@ -155,13 +181,11 @@
root_incdir,
],
dependencies : [
- gio,
- soup,
- libjsonglib,
+ libfwupd_deps,
],
link_with : fwupd,
c_args : [
- cargs,
+ '-DG_LOG_DOMAIN="Fwupd"',
'-DLOCALSTATEDIR="' + localstatedir + '"',
'-DTESTDATADIR="' + testdatadir + '"',
'-DFU_SELF_TEST_REMOTES_DIR="' + testdatadir + '"',
@@ -169,6 +193,42 @@
],
)
test('fwupd-self-test', e, timeout: 60)
+ if gio.version().version_compare ('>= 2.64.0')
+ e = executable(
+ 'fwupd-thread-test',
+ sources : [
+ 'fwupd-thread-test.c'
+ ],
+ include_directories : [
+ root_incdir,
+ ],
+ dependencies : [
+ libfwupd_deps,
+ ],
+ link_with : fwupd,
+ c_args : [
+ '-DG_LOG_DOMAIN="Fwupd"',
+ ],
+ )
+ test('fwupd-thread-test', e, timeout: 60)
+ e = executable(
+ 'fwupd-context-test',
+ sources : [
+ 'fwupd-context-test.c'
+ ],
+ include_directories : [
+ root_incdir,
+ ],
+ dependencies : [
+ libfwupd_deps,
+ ],
+ link_with : fwupd,
+ c_args : [
+ '-DG_LOG_DOMAIN="Fwupd"',
+ ],
+ )
+ test('fwupd-context-test', e, timeout: 60)
+ endif
endif
fwupd_incdir = include_directories('.')
diff -Nru fwupd-1.4.5/libfwupd/README.md fwupd-1.5.8/libfwupd/README.md
--- fwupd-1.4.5/libfwupd/README.md 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupd/README.md 2021-03-31 20:08:32.000000000 +0000
@@ -1,3 +1,14 @@
+Planned API/ABI changes for next release
+========================================
+
+ * Typedef `FwupdFeatureFlags` to `guint64` so it's the same size on all platforms
+ * Remove the `soup-session` fallback property in `FwupdClient`.
+ * Remove fwupd_device_set_vendor_id() and fwupd_device_get_vendor_id()
+ * Remove the deprecated flags like `FWUPD_DEVICE_FLAG_MD_SET_ICON`
+ * Remove `fwupd_release_get_uri()` and `fwupd_release_set_uri()`
+ * Rename `fwupd_client_install_release2_async()` to `fwupd_client_install_release_async()`
+ * Remove fwupd_device_set_protocol() and fwupd_device_get_protocol()
+
Migration from Version 0.9.x
============================
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-archive.c fwupd-1.5.8/libfwupdplugin/fu-archive.c
--- fwupd-1.4.5/libfwupdplugin/fu-archive.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-archive.c 2021-03-31 20:08:32.000000000 +0000
@@ -9,10 +9,14 @@
#include "config.h"
#include
+
+#ifdef HAVE_LIBARCHIVE
#include
#include
+#endif
#include "fu-archive.h"
+#include "fwupd-error.h"
/**
* SECTION:fu-archive
@@ -106,6 +110,7 @@
g_return_val_if_fail (FU_IS_ARCHIVE (self), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_hash_table_iter_init (&iter, self->entries);
while (g_hash_table_iter_next (&iter, &key, &value)) {
@@ -115,6 +120,7 @@
return TRUE;
}
+#ifdef HAVE_LIBARCHIVE
/* workaround the struct types of libarchive */
typedef struct archive _archive_read_ctx;
@@ -126,10 +132,12 @@
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC(_archive_read_ctx, _archive_read_ctx_free)
+#endif
static gboolean
fu_archive_load (FuArchive *self, GBytes *blob, FuArchiveFlags flags, GError **error)
{
+#ifdef HAVE_LIBARCHIVE
int r;
g_autoptr(_archive_read_ctx) arch = NULL;
@@ -218,6 +226,13 @@
/* success */
return TRUE;
+#else
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "missing libarchive support");
+ return FALSE;
+#endif
}
/**
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-archive.h fwupd-1.5.8/libfwupdplugin/fu-archive.h
--- fwupd-1.4.5/libfwupdplugin/fu-archive.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-archive.h 2021-03-31 20:08:32.000000000 +0000
@@ -32,6 +32,7 @@
* @filename: A filename.
* @bytes: The blob referenced by @filename.
* @user_data: User data.
+ * @error: a #GError or NULL
*
* Specifies the type of archive iteration function.
*/
@@ -39,15 +40,19 @@
const gchar *filename,
GBytes *bytes,
gpointer user_data,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
-FuArchive *fu_archive_new (GBytes *data,
- FuArchiveFlags flags,
- GError **error);
-GBytes *fu_archive_lookup_by_fn (FuArchive *self,
- const gchar *fn,
- GError **error);
+FuArchive *fu_archive_new (GBytes *data,
+ FuArchiveFlags flags,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GBytes *fu_archive_lookup_by_fn (FuArchive *self,
+ const gchar *fn,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_archive_iterate (FuArchive *self,
FuArchiveIterateFunc callback,
gpointer user_data,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-bluez-device.c fwupd-1.5.8/libfwupdplugin/fu-bluez-device.c
--- fwupd-1.4.5/libfwupdplugin/fu-bluez-device.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-bluez-device.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2021 Ricardo Cañuelo
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#define G_LOG_DOMAIN "FuBluezDevice"
+
+#include "config.h"
+
+#include
+
+#include "fu-bluez-device.h"
+#include "fu-common.h"
+#include "fu-device-private.h"
+#include "fu-firmware-common.h"
+
+#define DEFAULT_PROXY_TIMEOUT 5000
+
+/**
+ * SECTION:fu-bluez-device
+ * @short_description: a BlueZ Bluetooth device
+ *
+ * An object that represents a BlueZ Bluetooth device.
+ *
+ * See also: #FuBluezDevice
+ */
+
+typedef struct {
+ FuBluezDevice parent_instance;
+ GDBusObjectManager *object_manager;
+ GDBusProxy *proxy;
+ GHashTable *uuids; /* utf8 : FuBluezDeviceUuidHelper */
+} FuBluezDevicePrivate;
+
+typedef struct {
+ FuBluezDevice *self;
+ gchar *uuid;
+ gchar *path;
+ gulong signal_id;
+ GDBusProxy *proxy;
+} FuBluezDeviceUuidHelper;
+
+enum {
+ PROP_0,
+ PROP_OBJECT_MANAGER,
+ PROP_PROXY,
+ PROP_LAST
+};
+
+enum {
+ SIGNAL_CHANGED,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (FuBluezDevice, fu_bluez_device, FU_TYPE_DEVICE)
+
+#define GET_PRIVATE(o) (fu_bluez_device_get_instance_private (o))
+
+static void
+fu_bluez_uuid_free (FuBluezDeviceUuidHelper *uuid_helper)
+{
+ if (uuid_helper->path != NULL)
+ g_free (uuid_helper->path);
+ if (uuid_helper->proxy != NULL)
+ g_object_unref (uuid_helper->proxy);
+ g_free (uuid_helper->uuid);
+ g_object_unref (uuid_helper->self);
+ g_free (uuid_helper);
+}
+
+/*
+ * Looks up a UUID in the FuBluezDevice uuids table.
+ */
+static FuBluezDeviceUuidHelper *
+fu_bluez_device_get_uuid_helper (FuBluezDevice *self,
+ const gchar *uuid,
+ GError **error)
+{
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ FuBluezDeviceUuidHelper *uuid_helper;
+
+ uuid_helper = g_hash_table_lookup (priv->uuids, uuid);
+ if (uuid_helper == NULL) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "UUID %s not supported", uuid);
+ return NULL;
+ }
+
+ return uuid_helper;
+}
+
+static void
+fu_bluez_device_signal_cb (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ FuBluezDeviceUuidHelper *uuid_helper)
+{
+ g_signal_emit (uuid_helper->self, signals[SIGNAL_CHANGED], 0, uuid_helper->uuid);
+}
+
+/*
+ * Builds the GDBusProxy of the BlueZ object identified by a UUID
+ * string. If the object doesn't have a dedicated proxy yet, this
+ * creates it and saves it in the FuBluezDeviceUuidHelper object.
+ *
+ * NOTE: Currently limited to GATT characteristics.
+ */
+static gboolean
+fu_bluez_device_ensure_uuid_helper_proxy (FuBluezDeviceUuidHelper *uuid_helper,
+ GError **error)
+{
+ if (uuid_helper->proxy != NULL)
+ return TRUE;
+ uuid_helper->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.bluez",
+ uuid_helper->path,
+ "org.bluez.GattCharacteristic1",
+ NULL, error);
+ if (uuid_helper->proxy == NULL) {
+ g_prefix_error (error, "Failed to create GDBusProxy for uuid_helper: ");
+ return FALSE;
+ }
+ g_dbus_proxy_set_default_timeout (uuid_helper->proxy, DEFAULT_PROXY_TIMEOUT);
+ uuid_helper->signal_id = g_signal_connect (uuid_helper->proxy,
+ "g-properties-changed",
+ G_CALLBACK (fu_bluez_device_signal_cb),
+ uuid_helper);
+ if (uuid_helper->signal_id <= 0) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "cannot connect to signal of UUID %s",
+ uuid_helper->uuid);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+fu_bluez_device_add_uuid_path (FuBluezDevice *self, const gchar *uuid, const gchar *path)
+{
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ FuBluezDeviceUuidHelper *uuid_helper;
+ g_return_if_fail (FU_IS_BLUEZ_DEVICE (self));
+ g_return_if_fail (uuid != NULL);
+ g_return_if_fail (path != NULL);
+
+ uuid_helper = g_new0 (FuBluezDeviceUuidHelper, 1);
+ uuid_helper->self = g_object_ref (self);
+ uuid_helper->uuid = g_strdup (uuid);
+ uuid_helper->path = g_strdup (path);
+ g_hash_table_insert (priv->uuids, g_strdup (uuid), uuid_helper);
+}
+
+static void
+fu_bluez_device_set_modalias (FuBluezDevice *self, const gchar *modalias)
+{
+ gsize modaliaslen = strlen (modalias);
+ guint16 vid = 0x0;
+ guint16 pid = 0x0;
+ guint16 rev = 0x0;
+
+ g_return_if_fail (modalias != NULL);
+
+ /* usb:v0461p4EEFd0001 */
+ if (g_str_has_prefix (modalias, "usb:")) {
+ fu_firmware_strparse_uint16_safe (modalias, modaliaslen, 5, &vid, NULL);
+ fu_firmware_strparse_uint16_safe (modalias, modaliaslen, 10, &pid, NULL);
+ fu_firmware_strparse_uint16_safe (modalias, modaliaslen, 15, &rev, NULL);
+
+ /* bluetooth:v000ApFFFFdFFFF */
+ } else if (g_str_has_prefix (modalias, "bluetooth:")) {
+ fu_firmware_strparse_uint16_safe (modalias, modaliaslen, 11, &vid, NULL);
+ fu_firmware_strparse_uint16_safe (modalias, modaliaslen, 16, &pid, NULL);
+ fu_firmware_strparse_uint16_safe (modalias, modaliaslen, 21, &rev, NULL);
+ }
+
+ if (vid != 0x0 && pid != 0x0 && rev != 0x0) {
+ g_autofree gchar *devid = NULL;
+ devid = g_strdup_printf ("BLUETOOTH\\VID_%04X&PID_%04X&REV_%04X",
+ vid, pid, rev);
+ fu_device_add_instance_id (FU_DEVICE (self), devid);
+ }
+ if (vid != 0x0 && pid != 0x0) {
+ g_autofree gchar *devid = NULL;
+ devid = g_strdup_printf ("BLUETOOTH\\VID_%04X&PID_%04X", vid, pid);
+ fu_device_add_instance_id (FU_DEVICE (self), devid);
+ }
+ if (vid != 0x0) {
+ g_autofree gchar *devid = NULL;
+ g_autofree gchar *vendor_id = NULL;
+ devid = g_strdup_printf ("BLUETOOTH\\VID_%04X", vid);
+ fu_device_add_instance_id_full (FU_DEVICE (self), devid,
+ FU_DEVICE_INSTANCE_FLAG_ONLY_QUIRKS);
+ vendor_id = g_strdup_printf ("BLUETOOTH:%04X", vid);
+ fu_device_add_vendor_id (FU_DEVICE (self), vendor_id);
+ }
+}
+
+static void
+fu_bluez_device_to_string (FuDevice *device, guint idt, GString *str)
+{
+ FuBluezDevice *self = FU_BLUEZ_DEVICE (device);
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+
+ if (priv->uuids != NULL) {
+ GHashTableIter iter;
+ gpointer key, value;
+ g_hash_table_iter_init (&iter, priv->uuids);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ FuBluezDeviceUuidHelper *uuid_helper = (FuBluezDeviceUuidHelper *) value;
+ fu_common_string_append_kv (str, idt + 1,
+ (const gchar *) key,
+ uuid_helper->path);
+ }
+ }
+}
+
+/*
+ * Returns the value of a property of an object specified by its path as
+ * a GVariant, or NULL if the property wasn't found.
+ */
+static GVariant *
+fu_bluez_device_get_ble_property (const gchar *obj_path,
+ const gchar *iface,
+ const gchar *prop_name,
+ GError **error)
+{
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.bluez",
+ obj_path, iface, NULL, error);
+ if (proxy == NULL) {
+ g_prefix_error (error, "failed to connect to %s: ", iface);
+ return NULL;
+ }
+ g_dbus_proxy_set_default_timeout (proxy, DEFAULT_PROXY_TIMEOUT);
+ val = g_dbus_proxy_get_cached_property (proxy, prop_name);
+ if (val == NULL) {
+ g_prefix_error (error, "property %s not found in %s: ",
+ prop_name, obj_path);
+ return NULL;
+ }
+
+ return g_steal_pointer (&val);
+}
+
+/*
+ * Returns the value of the string property of an object specified by
+ * its path, or NULL if the property wasn't found.
+ *
+ * The returned string must be freed using g_free().
+ */
+static gchar *
+fu_bluez_device_get_ble_string_property (const gchar *obj_path,
+ const gchar *iface,
+ const gchar *prop_name,
+ GError **error)
+{
+ g_autoptr(GVariant) val = NULL;
+ val = fu_bluez_device_get_ble_property (obj_path, iface, prop_name, error);
+ if (val == NULL)
+ return NULL;
+ return g_variant_dup_string (val, NULL);
+}
+
+/*
+ * Populates the {uuid_helper : object_path} entries of a device for all its
+ * characteristics.
+ *
+ * TODO: Extend to services and descriptors too?
+ */
+static void
+fu_bluez_device_add_device_uuids (FuBluezDevice *self)
+{
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ g_autolist(GDBusObject) obj_list = NULL;
+
+ obj_list = g_dbus_object_manager_get_objects (priv->object_manager);
+ for (GList *l = obj_list; l != NULL; l = l->next) {
+ GDBusObject *obj = G_DBUS_OBJECT (l->data);
+ g_autoptr(GDBusInterface) iface = NULL;
+ g_autoptr(GError) error_local = NULL;
+ g_autofree gchar *obj_uuid = NULL;
+ const gchar *obj_path = g_dbus_object_get_object_path (obj);
+
+ /* not us */
+ if (!g_str_has_prefix (g_dbus_object_get_object_path (obj),
+ g_dbus_proxy_get_object_path (priv->proxy)))
+ continue;
+
+ /*
+ * TODO: Currently restricted to getting UUIDs for
+ * characteristics only, as the only use case we're
+ * going to need for now is reading/writing
+ * characteristics.
+ */
+ iface = g_dbus_object_get_interface (obj, "org.bluez.GattCharacteristic1");
+ if (iface == NULL)
+ continue;
+ obj_uuid = fu_bluez_device_get_ble_string_property (obj_path,
+ "org.bluez.GattCharacteristic1",
+ "UUID",
+ &error_local);
+ if (obj_uuid == NULL) {
+ g_debug ("failed to get property: %s", error_local->message);
+ continue;
+ }
+ fu_bluez_device_add_uuid_path (self, obj_uuid, obj_path);
+ }
+}
+
+static gboolean
+fu_bluez_device_setup (FuDevice *device, GError **error)
+{
+ FuBluezDevice *self = FU_BLUEZ_DEVICE (device);
+
+ fu_bluez_device_add_device_uuids (self);
+
+ return TRUE;
+}
+
+static gboolean
+fu_bluez_device_probe (FuDevice *device, GError **error)
+{
+ FuBluezDevice *self = FU_BLUEZ_DEVICE (device);
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ g_autoptr(GVariant) val_adapter = NULL;
+ g_autoptr(GVariant) val_address = NULL;
+ g_autoptr(GVariant) val_icon = NULL;
+ g_autoptr(GVariant) val_modalias = NULL;
+ g_autoptr(GVariant) val_name = NULL;
+
+ val_address = g_dbus_proxy_get_cached_property (priv->proxy, "Address");
+ if (val_address == NULL) {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "No required BLE address");
+ return FALSE;
+ }
+ fu_device_set_logical_id (device, g_variant_get_string (val_address, NULL));
+ val_adapter = g_dbus_proxy_get_cached_property (priv->proxy, "Adapter");
+ if (val_adapter != NULL)
+ fu_device_set_physical_id (device, g_variant_get_string (val_adapter, NULL));
+ val_name = g_dbus_proxy_get_cached_property (priv->proxy, "Name");
+ if (val_name != NULL)
+ fu_device_set_name (device, g_variant_get_string (val_name, NULL));
+ val_icon = g_dbus_proxy_get_cached_property (priv->proxy, "Icon");
+ if (val_icon != NULL)
+ fu_device_add_icon (device, g_variant_get_string (val_name, NULL));
+ val_modalias = g_dbus_proxy_get_cached_property (priv->proxy, "Modalias");
+ if (val_modalias != NULL)
+ fu_bluez_device_set_modalias (self, g_variant_get_string (val_modalias, NULL));
+
+ /* success */
+ return TRUE;
+}
+
+/**
+ * fu_bluez_device_read:
+ * @self: A #FuBluezDevice
+ * @uuid: The UUID, e.g. `00cde35c-7062-11eb-9439-0242ac130002`
+ * @error: A #GError, or %NULL
+ *
+ * Reads from a UUID on the device.
+ *
+ * Returns: (transfer full): data, or %NULL for error
+ *
+ * Since: 1.5.7
+ **/
+GByteArray *
+fu_bluez_device_read (FuBluezDevice *self, const gchar *uuid, GError **error)
+{
+ FuBluezDeviceUuidHelper *uuid_helper;
+ guint8 byte;
+ g_autoptr(GByteArray) buf = g_byte_array_new ();
+ g_autoptr(GVariantBuilder) builder = NULL;
+ g_autoptr(GVariantIter) iter = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ uuid_helper = fu_bluez_device_get_uuid_helper (self, uuid, error);
+ if (uuid_helper == NULL)
+ return NULL;
+ if (!fu_bluez_device_ensure_uuid_helper_proxy (uuid_helper, error))
+ return NULL;
+
+ /*
+ * Call the "ReadValue" method through the proxy synchronously.
+ *
+ * The method takes one argument: an array of dicts of
+ * {string:value} specifing the options (here the option is
+ * "offset":0.
+ * The result is a byte array.
+ */
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (builder, "{sv}", "offset",
+ g_variant_new("q", 0));
+
+ val = g_dbus_proxy_call_sync (uuid_helper->proxy,
+ "ReadValue",
+ g_variant_new ("(a{sv})", builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, error);
+ if (val == NULL) {
+ g_prefix_error (error, "Failed to read GattCharacteristic1: ");
+ return NULL;
+ }
+ g_variant_get(val, "(ay)", &iter);
+ while (g_variant_iter_loop (iter, "y", &byte))
+ g_byte_array_append (buf, &byte, 1);
+
+ /* success */
+ return g_steal_pointer (&buf);
+}
+
+/**
+ * fu_bluez_device_read_string:
+ * @self: A #FuBluezDevice
+ * @uuid: The UUID, e.g. `00cde35c-7062-11eb-9439-0242ac130002`
+ * @error: A #GError, or %NULL
+ *
+ * Reads a string from a UUID on the device.
+ *
+ * Returns: (transfer full): data, or %NULL for error
+ *
+ * Since: 1.5.7
+ **/
+gchar *
+fu_bluez_device_read_string (FuBluezDevice *self, const gchar *uuid, GError **error)
+{
+ GByteArray *buf = fu_bluez_device_read (self, uuid, error);
+ if (buf == NULL)
+ return NULL;
+ return (gchar *) g_byte_array_free (buf, FALSE);
+}
+
+/**
+ * fu_bluez_device_write:
+ * @self: A #FuBluezDevice
+ * @uuid: The UUID, e.g. `00cde35c-7062-11eb-9439-0242ac130002`
+ * @error: A #GError, or %NULL
+ *
+ * Writes to a UUID on the device.
+ *
+ * Returns: %TRUE if all the data was written
+ *
+ * Since: 1.5.7
+ **/
+gboolean
+fu_bluez_device_write (FuBluezDevice *self,
+ const gchar *uuid,
+ GByteArray *buf,
+ GError **error)
+{
+ FuBluezDeviceUuidHelper *uuid_helper;
+ g_autoptr(GVariantBuilder) opt_builder = NULL;
+ g_autoptr(GVariantBuilder) val_builder = NULL;
+ g_autoptr(GVariant) ret = NULL;
+ GVariant *opt_variant = NULL;
+ GVariant *val_variant = NULL;
+
+ uuid_helper = fu_bluez_device_get_uuid_helper (self, uuid, error);
+ if (uuid_helper == NULL)
+ return FALSE;
+ if (!fu_bluez_device_ensure_uuid_helper_proxy (uuid_helper, error))
+ return FALSE;
+
+ /* build the value variant */
+ val_builder = g_variant_builder_new (G_VARIANT_TYPE ("ay"));
+ for (gsize i = 0; i < buf->len; i++)
+ g_variant_builder_add (val_builder, "y", buf->data[i]);
+ val_variant = g_variant_new ("ay", val_builder);
+
+ /* build the options variant (offset = 0) */
+ opt_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+ g_variant_builder_add (opt_builder, "{sv}", "offset",
+ g_variant_new_uint16 (0));
+ opt_variant = g_variant_new("a{sv}", opt_builder);
+
+ ret = g_dbus_proxy_call_sync (uuid_helper->proxy,
+ "WriteValue",
+ g_variant_new ("(@ay@a{sv})",
+ val_variant,
+ opt_variant),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, error);
+ if (ret == NULL) {
+ g_prefix_error (error, "Failed to write GattCharacteristic1: ");
+ return FALSE;
+ }
+
+ /* success */
+ return TRUE;
+}
+
+/**
+ * fu_bluez_device_notify_start:
+ * @uuid: The UUID, e.g. `00cde35c-7062-11eb-9439-0242ac130002`
+ * @error: A #GError, or %NULL
+ *
+ * Enables notifications for property changes in a UUID (StartNotify
+ * method).
+ *
+ * Returns: %TRUE if the method call completed successfully.
+ *
+ * Since: 1.5.8
+ **/
+gboolean
+fu_bluez_device_notify_start (FuBluezDevice *self, const gchar *uuid, GError **error)
+{
+ FuBluezDeviceUuidHelper *uuid_helper;
+ g_autoptr(GVariant) retval = NULL;
+
+ uuid_helper = fu_bluez_device_get_uuid_helper (self, uuid, error);
+ if (uuid_helper == NULL)
+ return FALSE;
+ if (!fu_bluez_device_ensure_uuid_helper_proxy (uuid_helper, error))
+ return FALSE;
+ retval = g_dbus_proxy_call_sync (uuid_helper->proxy,
+ "StartNotify",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, error);
+ if (retval == NULL) {
+ g_prefix_error (error, "Failed to enable notifications: ");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * fu_bluez_device_notify_stop:
+ * @uuid: The UUID, e.g. `00cde35c-7062-11eb-9439-0242ac130002`
+ * @error: A #GError, or %NULL
+ *
+ * Disables notifications for property changes in a UUID (StopNotify
+ * method).
+ *
+ * Returns: %TRUE if the method call completed successfully.
+ *
+ * Since: 1.5.8
+ **/
+gboolean
+fu_bluez_device_notify_stop (FuBluezDevice *self, const gchar *uuid, GError **error)
+{
+ FuBluezDeviceUuidHelper *uuid_helper;
+ g_autoptr(GVariant) retval = NULL;
+
+ uuid_helper = fu_bluez_device_get_uuid_helper (self, uuid, error);
+ if (uuid_helper == NULL)
+ return FALSE;
+ if (!fu_bluez_device_ensure_uuid_helper_proxy (uuid_helper, error))
+ return FALSE;
+ retval = g_dbus_proxy_call_sync (uuid_helper->proxy,
+ "StopNotify",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, error);
+ if (retval == NULL) {
+ g_prefix_error (error, "Failed to enable notifications: ");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+fu_bluez_device_incorporate (FuDevice *self, FuDevice *donor)
+{
+ FuBluezDevice *uself = FU_BLUEZ_DEVICE (self);
+ FuBluezDevice *udonor = FU_BLUEZ_DEVICE (donor);
+ FuBluezDevicePrivate *priv = GET_PRIVATE (uself);
+ FuBluezDevicePrivate *privdonor = GET_PRIVATE (udonor);
+
+ if (g_hash_table_size (priv->uuids) == 0) {
+ GHashTableIter iter;
+ gpointer key, value;
+ g_hash_table_iter_init (&iter, privdonor->uuids);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ FuBluezDeviceUuidHelper *uuid_helper = (FuBluezDeviceUuidHelper *) value;
+ fu_bluez_device_add_uuid_path (uself,
+ (const gchar *) key,
+ uuid_helper->path);
+ }
+ }
+ if (priv->object_manager == NULL)
+ priv->object_manager = g_object_ref (privdonor->object_manager);
+ if (priv->proxy == NULL)
+ priv->proxy = g_object_ref (privdonor->proxy);
+}
+
+static void
+fu_bluez_device_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ FuBluezDevice *self = FU_BLUEZ_DEVICE (object);
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ switch (prop_id) {
+ case PROP_OBJECT_MANAGER:
+ g_value_set_object (value, priv->object_manager);
+ break;
+ case PROP_PROXY:
+ g_value_set_object (value, priv->proxy);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+fu_bluez_device_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ FuBluezDevice *self = FU_BLUEZ_DEVICE (object);
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ switch (prop_id) {
+ case PROP_OBJECT_MANAGER:
+ priv->object_manager = g_value_dup_object (value);
+ break;
+ case PROP_PROXY:
+ priv->proxy = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+fu_bluez_device_finalize (GObject *object)
+{
+ FuBluezDevice *self = FU_BLUEZ_DEVICE (object);
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+
+ g_hash_table_unref (priv->uuids);
+ g_object_unref (priv->proxy);
+ g_object_unref (priv->object_manager);
+ G_OBJECT_CLASS (fu_bluez_device_parent_class)->finalize (object);
+}
+
+static void
+fu_bluez_device_init (FuBluezDevice *self)
+{
+ FuBluezDevicePrivate *priv = GET_PRIVATE (self);
+ priv->uuids = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) fu_bluez_uuid_free);
+}
+
+static void
+fu_bluez_device_class_init (FuBluezDeviceClass *klass)
+{
+ FuDeviceClass *device_class = FU_DEVICE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ object_class->get_property = fu_bluez_device_get_property;
+ object_class->set_property = fu_bluez_device_set_property;
+ object_class->finalize = fu_bluez_device_finalize;
+ device_class->probe = fu_bluez_device_probe;
+ device_class->setup = fu_bluez_device_setup;
+ device_class->to_string = fu_bluez_device_to_string;
+ device_class->incorporate = fu_bluez_device_incorporate;
+
+ signals[SIGNAL_CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ pspec = g_param_spec_object ("object-manager", NULL, NULL,
+ G_TYPE_DBUS_OBJECT_MANAGER,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME);
+ g_object_class_install_property (object_class, PROP_OBJECT_MANAGER, pspec);
+
+ pspec = g_param_spec_object ("proxy", NULL, NULL,
+ G_TYPE_DBUS_PROXY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME);
+ g_object_class_install_property (object_class, PROP_PROXY, pspec);
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-bluez-device.h fwupd-1.5.8/libfwupdplugin/fu-bluez-device.h
--- fwupd-1.4.5/libfwupdplugin/fu-bluez-device.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-bluez-device.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 Ricardo Cañuelo
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fu-device.h"
+
+#define FU_TYPE_BLUEZ_DEVICE (fu_bluez_device_get_type ())
+G_DECLARE_DERIVABLE_TYPE (FuBluezDevice, fu_bluez_device, FU, BLUEZ_DEVICE, FuDevice)
+
+struct _FuBluezDeviceClass
+{
+ FuDeviceClass parent_class;
+ gpointer __reserved[31];
+};
+
+GByteArray *fu_bluez_device_read (FuBluezDevice *self,
+ const gchar *uuid,
+ GError **error);
+gchar *fu_bluez_device_read_string (FuBluezDevice *self,
+ const gchar *uuid,
+ GError **error);
+gboolean fu_bluez_device_write (FuBluezDevice *self,
+ const gchar *uuid,
+ GByteArray *buf,
+ GError **error);
+gboolean fu_bluez_device_notify_start (FuBluezDevice *self,
+ const gchar *uuid,
+ GError **error);
+gboolean fu_bluez_device_notify_stop (FuBluezDevice *self,
+ const gchar *uuid,
+ GError **error);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-cabinet.c fwupd-1.5.8/libfwupdplugin/fu-cabinet.c
--- fwupd-1.4.5/libfwupdplugin/fu-cabinet.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-cabinet.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2020 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -341,8 +341,11 @@
/* 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;
@@ -361,10 +364,8 @@
g_autoptr(XbBuilderNode) bn_info = xb_builder_node_new ("info");
/* indicate the metainfo file was signed */
- if (release_flags & FWUPD_RELEASE_FLAG_TRUSTED_METADATA) {
- g_autoptr(XbBuilderNode) bn_trust = NULL;
+ if (release_flags & FWUPD_RELEASE_FLAG_TRUSTED_METADATA)
xb_builder_node_insert (bn_info, "metadata_trust", NULL);
- }
xb_builder_source_set_info (source, bn_info);
/* rewrite to be under a components root */
@@ -485,7 +486,7 @@
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 +505,6 @@
/* 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;
}
@@ -674,7 +674,9 @@
return FALSE;
/* sanity check */
- components = xb_silo_query (self->silo, "components/component", 0, &error_local);
+ components = xb_silo_query (self->silo,
+ "components/component[@type='firmware']",
+ 0, &error_local);
if (components == NULL) {
g_set_error (error,
FWUPD_ERROR,
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-cabinet.h fwupd-1.5.8/libfwupdplugin/fu-cabinet.h
--- fwupd-1.4.5/libfwupdplugin/fu-cabinet.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-cabinet.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2020 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -34,5 +34,6 @@
gboolean fu_cabinet_parse (FuCabinet *self,
GBytes *data,
FuCabinetParseFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
XbSilo *fu_cabinet_get_silo (FuCabinet *self);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-chunk.c fwupd-1.5.8/libfwupdplugin/fu-chunk.c
--- fwupd-1.4.5/libfwupdplugin/fu-chunk.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-chunk.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -10,7 +10,8 @@
#include
-#include "fu-chunk.h"
+#include "fu-chunk-private.h"
+#include "fu-common.h"
/**
* SECTION:fu-chunk
@@ -20,8 +21,230 @@
*
*/
+struct _FuChunk {
+ GObject parent_instance;
+ guint32 idx;
+ guint32 page;
+ guint32 address;
+ const guint8 *data;
+ guint32 data_sz;
+ gboolean is_mutable;
+ GBytes *bytes;
+};
+
+G_DEFINE_TYPE (FuChunk, fu_chunk, G_TYPE_OBJECT)
+
+/**
+ * fu_chunk_set_idx:
+ * @self: a #FuChunk
+ * @idx: index, starting at 0
+ *
+ * Sets the index of the chunk.
+ *
+ * Since: 1.5.6
+ **/
+void
+fu_chunk_set_idx (FuChunk *self, guint32 idx)
+{
+ g_return_if_fail (FU_IS_CHUNK (self));
+ self->idx = idx;
+}
+
+/**
+ * fu_chunk_get_idx:
+ * @self: a #FuChunk
+ *
+ * Gets the index of the chunk.
+ *
+ * Return value: index
+ *
+ * Since: 1.5.6
+ **/
+guint32
+fu_chunk_get_idx (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), G_MAXUINT32);
+ return self->idx;
+}
+
+/**
+ * fu_chunk_set_page:
+ * @self: a #FuChunk
+ * @page: page number, starting at 0
+ *
+ * Sets the page of the chunk.
+ *
+ * Since: 1.5.6
+ **/
+void
+fu_chunk_set_page (FuChunk *self, guint32 page)
+{
+ g_return_if_fail (FU_IS_CHUNK (self));
+ self->page = page;
+}
+
+/**
+ * fu_chunk_get_page:
+ * @self: a #FuChunk
+ *
+ * Gets the page of the chunk.
+ *
+ * Return value: page
+ *
+ * Since: 1.5.6
+ **/
+guint32
+fu_chunk_get_page (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), G_MAXUINT32);
+ return self->page;
+}
+
+/**
+ * fu_chunk_set_address:
+ * @self: a #FuChunk
+ * @address: memory address
+ *
+ * Sets the address of the chunk.
+ *
+ * Since: 1.5.6
+ **/
+void
+fu_chunk_set_address (FuChunk *self, guint32 address)
+{
+ g_return_if_fail (FU_IS_CHUNK (self));
+ self->address = address;
+}
+
+/**
+ * fu_chunk_get_address:
+ * @self: a #FuChunk
+ *
+ * Gets the address of the chunk.
+ *
+ * Return value: address
+ *
+ * Since: 1.5.6
+ **/
+guint32
+fu_chunk_get_address (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), G_MAXUINT32);
+ return self->address;
+}
+
+/**
+ * fu_chunk_get_data:
+ * @self: a #FuChunk
+ *
+ * Gets the data of the chunk.
+ *
+ * Return value: bytes
+ *
+ * Since: 1.5.6
+ **/
+const guint8 *
+fu_chunk_get_data (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), NULL);
+ return self->data;
+}
+
+/**
+ * fu_chunk_get_data_out:
+ * @self: a #FuChunk
+ *
+ * Gets the mutable data of the chunk.
+ *
+ * WARNING: At the moment fu_chunk_get_data_out() returns the same data as
+ * fu_chunk_get_data() in all cases. The caller should verify the data passed to
+ * fu_chunk_array_new() is also writable (i.e. not `const` or `mmap`) before
+ * using this function.
+ *
+ * Return value: (transfer none): bytes
+ *
+ * Since: 1.5.6
+ **/
+guint8 *
+fu_chunk_get_data_out (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), NULL);
+
+ /* warn, but allow to proceed */
+ if (!self->is_mutable) {
+ g_critical ("calling fu_chunk_get_data_out() from immutable chunk");
+ self->is_mutable = TRUE;
+ }
+ return (guint8 *) self->data;
+}
+
+/**
+ * fu_chunk_get_data_sz:
+ * @self: a #FuChunk
+ *
+ * Gets the data size of the chunk.
+ *
+ * Return value: size in bytes
+ *
+ * Since: 1.5.6
+ **/
+guint32
+fu_chunk_get_data_sz (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), G_MAXUINT32);
+ return self->data_sz;
+}
+
/**
- * fu_chunk_new: (skip):
+ * fu_chunk_set_bytes:
+ * @self: a #FuChunk
+ * @bytes: (nullable): a #GBytes, or %NULL
+ *
+ * Sets the GBytes blob
+ *
+ * Since: 1.5.6
+ **/
+void
+fu_chunk_set_bytes (FuChunk *self, GBytes *bytes)
+{
+ g_return_if_fail (FU_IS_CHUNK (self));
+
+ /* not changed */
+ if (self->bytes == bytes)
+ return;
+
+ if (self->bytes != NULL) {
+ g_bytes_unref (self->bytes);
+ self->bytes = NULL;
+ }
+ if (bytes != NULL) {
+ self->bytes = g_bytes_ref (bytes);
+ self->data = g_bytes_get_data (bytes, NULL);
+ self->data_sz = g_bytes_get_size (bytes);
+ }
+}
+
+/**
+ * fu_chunk_get_bytes:
+ * @self: a #FuChunk
+ *
+ * Gets the data as bytes of the chunk.
+ *
+ * Return value: (transfer full): a #GBytes
+ *
+ * Since: 1.5.6
+ **/
+GBytes *
+fu_chunk_get_bytes (FuChunk *self)
+{
+ g_return_val_if_fail (FU_IS_CHUNK (self), NULL);
+ if (self->bytes != NULL)
+ return g_bytes_ref (self->bytes);
+ return g_bytes_new_static (self->data, self->data_sz);
+}
+
+/**
+ * fu_chunk_new:
* @idx: the packet number
* @page: the hardware memory page
* @address: the address *within* the page
@@ -41,18 +264,52 @@
const guint8 *data,
guint32 data_sz)
{
- FuChunk *item = g_new0 (FuChunk, 1);
- item->idx = idx;
- item->page = page;
- item->address = address;
- item->data = data;
- item->data_sz = data_sz;
- return item;
+ FuChunk *self = g_object_new (FU_TYPE_CHUNK, NULL);
+ self->idx = idx;
+ self->page = page;
+ self->address = address;
+ self->data = data;
+ self->data_sz = data_sz;
+ return self;
+}
+
+/**
+ * fu_chunk_bytes_new:
+ * @bytes: (nullable): a #GBytes
+ *
+ * Creates a new packet of data.
+ *
+ * Return value: (transfer full): a #FuChunk
+ *
+ * Since: 1.5.6
+ **/
+FuChunk *
+fu_chunk_bytes_new (GBytes *bytes)
+{
+ FuChunk *self = g_object_new (FU_TYPE_CHUNK, NULL);
+ fu_chunk_set_bytes (self, bytes);
+ return self;
+}
+
+void
+fu_chunk_add_string (FuChunk *self, guint idt, GString *str)
+{
+ fu_common_string_append_kv (str, idt, G_OBJECT_TYPE_NAME (self), NULL);
+ fu_common_string_append_kx (str, idt + 1, "Index", self->idx);
+ fu_common_string_append_kx (str, idt + 1, "Page", self->page);
+ fu_common_string_append_kx (str, idt + 1, "Address", self->address);
+ if (self->data != NULL) {
+ g_autofree gchar *datastr = NULL;
+ datastr = fu_common_strsafe ((const gchar *) self->data, MIN (self->data_sz, 16));
+ if (datastr != NULL)
+ fu_common_string_append_kv (str, idt + 1, "Data", datastr);
+ }
+ fu_common_string_append_kx (str, idt + 1, "DataSz", self->data_sz);
}
/**
* fu_chunk_to_string:
- * @item: a #FuChunk
+ * @self: a #FuChunk
*
* Converts the chunked packet to a string representation.
*
@@ -61,24 +318,11 @@
* Since: 1.1.2
**/
gchar *
-fu_chunk_to_string (FuChunk *item)
+fu_chunk_to_string (FuChunk *self)
{
- g_autoptr(GString) str = g_string_new (NULL);
- if (item->data != NULL) {
- for (guint32 i = 0; i < item->data_sz; i++) {
- gchar tmp = (gchar) item->data[i];
- if (tmp == 0x00)
- break;
- g_string_append_c (str, g_ascii_isalnum (tmp) ? tmp : '?');
- }
- }
- return g_strdup_printf ("#%02" G_GUINT32_FORMAT ": page:%02x "
- "addr:%04x len:%02" G_GUINT32_FORMAT " %s",
- item->idx,
- (guint) item->page,
- (guint) item->address,
- item->data_sz,
- str->str);
+ GString *str = g_string_new (NULL);
+ fu_chunk_add_string (self, 0, str);
+ return g_string_free (str, FALSE);
}
/**
@@ -96,15 +340,54 @@
{
GString *str = g_string_new (NULL);
for (guint i = 0; i < chunks->len; i++) {
- FuChunk *item = g_ptr_array_index (chunks, i);
- g_autofree gchar *tmp = fu_chunk_to_string (item);
+ FuChunk *chk = g_ptr_array_index (chunks, i);
+ g_autofree gchar *tmp = fu_chunk_to_string (chk);
g_string_append_printf (str, "%s\n", tmp);
}
+ if (str->len > 0)
+ g_string_truncate (str, str->len - 1);
return g_string_free (str, FALSE);
}
/**
- * fu_chunk_array_new: (skip):
+ * fu_chunk_array_mutable_new:
+ * @data: a mutable blob of memory
+ * @data_sz: size of @data_sz
+ * @addr_start: the hardware address offset, or 0
+ * @page_sz: the hardware page size, or 0
+ * @packet_sz: the transfer size, or 0
+ *
+ * Chunks a mutable blob of memory into packets, ensuring each packet does not
+ * cross a package boundary and is less that a specific transfer size.
+ *
+ * Return value: (transfer container) (element-type FuChunk): array of packets
+ *
+ * Since: 1.5.6
+ **/
+GPtrArray *
+fu_chunk_array_mutable_new (guint8 *data,
+ guint32 data_sz,
+ guint32 addr_start,
+ guint32 page_sz,
+ guint32 packet_sz)
+{
+ GPtrArray *chunks;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (data_sz > 0, NULL);
+
+ chunks = fu_chunk_array_new (data, data_sz, addr_start, page_sz, packet_sz);
+ if (chunks == NULL)
+ return NULL;
+ for (guint i = 0; i < chunks->len; i++) {
+ FuChunk *chk = g_ptr_array_index (chunks, i);
+ chk->is_mutable = TRUE;
+ }
+ return chunks;
+}
+
+/**
+ * fu_chunk_array_new:
* @data: a linear blob of memory, or %NULL
* @data_sz: size of @data_sz
* @addr_start: the hardware address offset, or 0
@@ -125,14 +408,14 @@
guint32 page_sz,
guint32 packet_sz)
{
- GPtrArray *segments = NULL;
+ GPtrArray *chunks = NULL;
guint32 page_old = G_MAXUINT32;
guint32 idx;
guint32 last_flush = 0;
g_return_val_if_fail (data_sz > 0, NULL);
- segments = g_ptr_array_new_with_free_func (g_free);
+ chunks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
for (idx = 1; idx < data_sz; idx++) {
guint32 page = 0;
if (page_sz > 0)
@@ -144,8 +427,8 @@
guint32 address_offset = addr_start + last_flush;
if (page_sz > 0)
address_offset %= page_sz;
- g_ptr_array_add (segments,
- fu_chunk_new (segments->len,
+ g_ptr_array_add (chunks,
+ fu_chunk_new (chunks->len,
page_old,
address_offset,
data_offset,
@@ -159,8 +442,8 @@
guint32 address_offset = addr_start + last_flush;
if (page_sz > 0)
address_offset %= page_sz;
- g_ptr_array_add (segments,
- fu_chunk_new (segments->len,
+ g_ptr_array_add (chunks,
+ fu_chunk_new (chunks->len,
page,
address_offset,
data_offset,
@@ -177,18 +460,18 @@
address_offset %= page_sz;
page = (addr_start + (idx - 1)) / page_sz;
}
- g_ptr_array_add (segments,
- fu_chunk_new (segments->len,
+ g_ptr_array_add (chunks,
+ fu_chunk_new (chunks->len,
page,
address_offset,
data_offset,
data_sz - last_flush));
}
- return segments;
+ return chunks;
}
/**
- * fu_chunk_array_new_from_bytes: (skip):
+ * fu_chunk_array_new_from_bytes:
* @blob: a #GBytes
* @addr_start: the hardware address offset, or 0
* @page_sz: the hardware page size, or 0
@@ -207,8 +490,77 @@
guint32 page_sz,
guint32 packet_sz)
{
+ GPtrArray *chunks;
gsize sz;
const guint8 *data = g_bytes_get_data (blob, &sz);
- return fu_chunk_array_new (data, (guint32) sz,
- addr_start, page_sz, packet_sz);
+
+ chunks = fu_chunk_array_new (data, (guint32) sz, addr_start, page_sz, packet_sz);
+ for (guint i = 0; i < chunks->len; i++) {
+ FuChunk *chk = g_ptr_array_index (chunks, i);
+ chk->bytes = fu_common_bytes_new_offset (blob,
+ chk->data - data,
+ chk->data_sz,
+ NULL);
+ }
+ return chunks;
+}
+
+/* private */
+gboolean
+fu_chunk_build (FuChunk *self, XbNode *n, GError **error)
+{
+ guint64 tmp;
+ g_autoptr(XbNode) data = NULL;
+
+ g_return_val_if_fail (FU_IS_CHUNK (self), FALSE);
+ g_return_val_if_fail (XB_IS_NODE (n), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* optional properties */
+ tmp = xb_node_query_text_as_uint (n, "idx", NULL);
+ if (tmp != G_MAXUINT64)
+ self->idx = tmp;
+ tmp = xb_node_query_text_as_uint (n, "page", NULL);
+ if (tmp != G_MAXUINT64)
+ self->page = tmp;
+ tmp = xb_node_query_text_as_uint (n, "addr", NULL);
+ if (tmp != G_MAXUINT64)
+ self->address = tmp;
+ data = xb_node_query_first (n, "data", NULL);
+ if (data != NULL && xb_node_get_text (data) != NULL) {
+ gsize bufsz = 0;
+ g_autofree guchar *buf = NULL;
+ g_autoptr(GBytes) blob = NULL;
+ buf = g_base64_decode (xb_node_get_text (data), &bufsz);
+ blob = g_bytes_new (buf, bufsz);
+ fu_chunk_set_bytes (self, blob);
+ } else if (data != NULL) {
+ g_autoptr(GBytes) blob = NULL;
+ blob = g_bytes_new (NULL, 0);
+ fu_chunk_set_bytes (self, blob);
+ }
+
+ /* success */
+ return TRUE;
+}
+
+static void
+fu_chunk_finalize (GObject *object)
+{
+ FuChunk *self = FU_CHUNK (object);
+ if (self->bytes != NULL)
+ g_bytes_unref (self->bytes);
+ G_OBJECT_CLASS (fu_chunk_parent_class)->finalize (object);
+}
+
+static void
+fu_chunk_class_init (FuChunkClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = fu_chunk_finalize;
+}
+
+static void
+fu_chunk_init (FuChunk *self)
+{
}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-chunk.h fwupd-1.5.8/libfwupdplugin/fu-chunk.h
--- fwupd-1.4.5/libfwupdplugin/fu-chunk.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-chunk.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,34 +1,51 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
-#include
-#include
+#include
-typedef struct {
- guint32 idx;
- guint32 page;
- guint32 address;
- const guint8 *data;
- guint32 data_sz;
-} FuChunk;
+#define FU_TYPE_CHUNK (fu_chunk_get_type ())
+
+G_DECLARE_FINAL_TYPE (FuChunk, fu_chunk, FU, CHUNK, GObject)
+
+FuChunk *fu_chunk_bytes_new (GBytes *bytes);
+void fu_chunk_set_idx (FuChunk *self,
+ guint32 idx);
+guint32 fu_chunk_get_idx (FuChunk *self);
+void fu_chunk_set_page (FuChunk *self,
+ guint32 page);
+guint32 fu_chunk_get_page (FuChunk *self);
+void fu_chunk_set_address (FuChunk *self,
+ guint32 address);
+guint32 fu_chunk_get_address (FuChunk *self);
+const guint8 *fu_chunk_get_data (FuChunk *self);
+guint8 *fu_chunk_get_data_out (FuChunk *self);
+guint32 fu_chunk_get_data_sz (FuChunk *self);
+void fu_chunk_set_bytes (FuChunk *self,
+ GBytes *bytes);
+GBytes *fu_chunk_get_bytes (FuChunk *self);
FuChunk *fu_chunk_new (guint32 idx,
guint32 page,
guint32 address,
const guint8 *data,
guint32 data_sz);
-gchar *fu_chunk_to_string (FuChunk *item);
+gchar *fu_chunk_to_string (FuChunk *self);
gchar *fu_chunk_array_to_string (GPtrArray *chunks);
GPtrArray *fu_chunk_array_new (const guint8 *data,
guint32 data_sz,
guint32 addr_start,
guint32 page_sz,
+ guint32 packet_sz);
+GPtrArray *fu_chunk_array_mutable_new (guint8 *data,
+ guint32 data_sz,
+ guint32 addr_start,
+ guint32 page_sz,
guint32 packet_sz);
GPtrArray *fu_chunk_array_new_from_bytes (GBytes *blob,
guint32 addr_start,
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-chunk-private.h fwupd-1.5.8/libfwupdplugin/fu-chunk-private.h
--- fwupd-1.4.5/libfwupdplugin/fu-chunk-private.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-chunk-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2017 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include
+
+#include "fu-chunk.h"
+
+void fu_chunk_add_string (FuChunk *self,
+ guint idt,
+ GString *str);
+gboolean fu_chunk_build (FuChunk *self,
+ XbNode *n,
+ GError **error);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common.c fwupd-1.5.8/libfwupdplugin/fu-common.c
--- fwupd-1.4.5/libfwupdplugin/fu-common.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common.c 2021-03-31 20:08:32.000000000 +0000
@@ -19,16 +19,35 @@
#include
#endif
+#ifdef _WIN32
+#include
+#endif
+
+#ifdef HAVE_CPUID_H
+#include
+#endif
+
+#ifdef HAVE_LIBARCHIVE
#include
#include
+#endif
#include
#include
#include
#include
+#include
#include "fwupd-error.h"
#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_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
@@ -56,6 +75,9 @@
const gchar *filename;
g_autoptr(GDir) dir = NULL;
+ g_return_val_if_fail (directory != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* try to open */
g_debug ("removing %s", directory);
dir = g_dir_open (directory, 0, error);
@@ -131,6 +153,10 @@
fu_common_get_files_recursive (const gchar *path, GError **error)
{
g_autoptr(GPtrArray) files = g_ptr_array_new_with_free_func (g_free);
+
+ g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
if (!fu_common_get_file_list_internal (files, path, error))
return NULL;
return g_steal_pointer (&files);
@@ -151,8 +177,12 @@
{
g_autofree gchar *parent = NULL;
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
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,
@@ -185,6 +215,10 @@
g_autoptr(GFile) file = NULL;
g_autoptr(GFile) file_parent = NULL;
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (bytes != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
file = g_file_new_for_path (filename);
file_parent = g_file_get_parent (file);
if (!g_file_query_exists (file_parent, NULL)) {
@@ -212,6 +246,10 @@
{
gchar *data = NULL;
gsize len = 0;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
if (!g_file_get_contents (filename, &data, &len, error))
return NULL;
g_debug ("reading %s with %" G_GSIZE_FORMAT " bytes", filename, len);
@@ -236,7 +274,8 @@
fu_common_get_contents_fd (gint fd, gsize count, GError **error)
{
#ifdef HAVE_GIO_UNIX
- g_autoptr(GBytes) blob = NULL;
+ guint8 tmp[0x8000] = { 0x0 };
+ g_autoptr(GByteArray) buf = g_byte_array_new ();
g_autoptr(GError) error_local = NULL;
g_autoptr(GInputStream) stream = NULL;
@@ -254,15 +293,31 @@
/* read the entire fd to a data blob */
stream = g_unix_input_stream_new (fd, TRUE);
- blob = g_input_stream_read_bytes (stream, count, NULL, &error_local);
- if (blob == NULL) {
- g_set_error_literal (error,
+
+ /* read from stream in 32kB chunks */
+ while (TRUE) {
+ gssize sz;
+ sz = g_input_stream_read (stream, tmp, sizeof(tmp), NULL, &error_local);
+ if (sz == 0)
+ break;
+ if (sz < 0) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ error_local->message);
+ return NULL;
+ }
+ g_byte_array_append (buf, tmp, sz);
+ if (buf->len > count) {
+ g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
- error_local->message);
- return NULL;
+ "cannot read from fd: 0x%x > 0x%x",
+ buf->len, (guint) count);
+ return NULL;
+ }
}
- return g_steal_pointer (&blob);
+ return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
#else
g_set_error_literal (error,
FWUPD_ERROR,
@@ -272,6 +327,7 @@
#endif
}
+#ifdef HAVE_LIBARCHIVE
static gboolean
fu_common_extract_archive_entry (struct archive_entry *entry, const gchar *dir)
{
@@ -288,6 +344,7 @@
archive_entry_update_pathname_utf8 (entry, buf);
return TRUE;
}
+#endif
/**
* fu_common_extract_archive:
@@ -304,11 +361,16 @@
gboolean
fu_common_extract_archive (GBytes *blob, const gchar *dir, GError **error)
{
+#ifdef HAVE_LIBARCHIVE
gboolean ret = TRUE;
int r;
struct archive *arch = NULL;
struct archive_entry *entry;
+ g_return_val_if_fail (blob != NULL, FALSE);
+ g_return_val_if_fail (dir != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* decompress anything matching either glob */
g_debug ("decompressing into %s", dir);
arch = archive_read_new ();
@@ -362,6 +424,13 @@
archive_read_free (arch);
}
return ret;
+#else
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "missing libarchive support");
+ return FALSE;
+#endif
}
static void
@@ -503,7 +572,7 @@
fu_common_add_argv (argv, "--die-with-parent");
fu_common_add_argv (argv, "--ro-bind /usr /usr");
fu_common_add_argv (argv, "--ro-bind /lib /lib");
- fu_common_add_argv (argv, "--ro-bind /lib64 /lib64");
+ fu_common_add_argv (argv, "--ro-bind-try /lib64 /lib64");
fu_common_add_argv (argv, "--ro-bind /bin /bin");
fu_common_add_argv (argv, "--ro-bind /sbin /sbin");
fu_common_add_argv (argv, "--dir /tmp");
@@ -689,6 +758,10 @@
g_autofree gchar *argv_str = NULL;
gulong cancellable_id = 0;
+ g_return_val_if_fail (argv != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* create subprocess */
argv_str = g_strjoinv (" ", (gchar **) argv);
g_debug ("running '%s'", argv_str);
@@ -781,6 +854,33 @@
}
/**
+ * fu_common_write_uint64:
+ * @buf: A writable buffer
+ * @val_native: a value in host byte-order
+ * @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
+ *
+ * Writes a value to a buffer using a specified endian.
+ *
+ * Since: 1.5.8
+ **/
+void
+fu_common_write_uint64 (guint8 *buf, guint64 val_native, FuEndianType endian)
+{
+ guint64 val_hw;
+ switch (endian) {
+ case G_BIG_ENDIAN:
+ val_hw = GUINT64_TO_BE(val_native);
+ break;
+ case G_LITTLE_ENDIAN:
+ val_hw = GUINT64_TO_LE(val_native);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ memcpy (buf, &val_hw, sizeof(val_hw));
+}
+
+/**
* fu_common_read_uint16:
* @buf: A readable buffer
* @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
@@ -839,6 +939,35 @@
}
/**
+ * fu_common_read_uint64:
+ * @buf: A readable buffer
+ * @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
+ *
+ * Read a value from a buffer using a specified endian.
+ *
+ * Returns: a value in host byte-order
+ *
+ * Since: 1.5.8
+ **/
+guint64
+fu_common_read_uint64 (const guint8 *buf, FuEndianType endian)
+{
+ guint64 val_hw, val_native;
+ memcpy (&val_hw, buf, sizeof(val_hw));
+ switch (endian) {
+ case G_BIG_ENDIAN:
+ val_native = GUINT64_FROM_BE(val_hw);
+ break;
+ case G_LITTLE_ENDIAN:
+ val_native = GUINT64_FROM_LE(val_hw);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ return val_native;
+}
+
+/**
* fu_common_strtoull:
* @str: A string, e.g. "0x1234"
*
@@ -1026,6 +1155,12 @@
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");
@@ -1050,6 +1185,12 @@
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");
@@ -1210,6 +1351,9 @@
{
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))
@@ -1235,7 +1379,7 @@
void
fu_common_string_append_kv (GString *str, guint idt, const gchar *key, const gchar *value)
{
- const guint align = 25;
+ const guint align = 24;
gsize keysz;
g_return_if_fail (idt * 2 < align);
@@ -1577,7 +1721,7 @@
* @bytes: a #GBytes
* @sz: the desired size in bytes
*
- * Pads a GBytes to a given @sz with `0xff`.
+ * Pads a GBytes to a minimum @sz with `0xff`.
*
* Return value: (transfer full): a #GBytes
*
@@ -1588,7 +1732,8 @@
{
gsize bytes_sz;
- g_return_val_if_fail (g_bytes_get_size (bytes) <= sz, NULL);
+ g_return_val_if_fail (bytes != NULL, NULL);
+ g_return_val_if_fail (sz != 0, NULL);
/* pad */
bytes_sz = g_bytes_get_size (bytes);
@@ -1600,11 +1745,48 @@
return g_bytes_new_take (data_new, sz);
}
- /* exactly right */
+ /* not required */
return g_bytes_ref (bytes);
}
/**
+ * fu_common_bytes_new_offset:
+ * @bytes: a #GBytes
+ * @offset: where subsection starts at
+ * @length: length of subsection
+ * @error: A #GError or %NULL
+ *
+ * Creates a #GBytes which is a subsection of another #GBytes.
+ *
+ * Return value: (transfer full): a #GBytes, or #NULL if range is invalid
+ *
+ * Since: 1.5.4
+ **/
+GBytes *
+fu_common_bytes_new_offset (GBytes *bytes,
+ gsize offset,
+ gsize length,
+ GError **error)
+{
+ g_return_val_if_fail (bytes != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* sanity check */
+ if (offset + length > g_bytes_get_size (bytes)) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "cannot create bytes @0x%02x for 0x%02x "
+ "as buffer only 0x%04x bytes in size",
+ (guint) offset,
+ (guint) length,
+ (guint) g_bytes_get_size (bytes));
+ return NULL;
+ }
+ return g_bytes_new_from_bytes (bytes, offset, length);
+}
+
+/**
* fu_common_realpath:
* @filename: a filename
* @error: A #GError or %NULL
@@ -1621,6 +1803,7 @@
char full_tmp[PATH_MAX];
g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
#ifdef HAVE_REALPATH
if (realpath (filename, full_tmp) == NULL) {
@@ -1672,6 +1855,55 @@
#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 = NULL;
+ g_autoptr(GPtrArray) files = g_ptr_array_new_with_free_func (g_free);
+
+ g_return_val_if_fail (directory != NULL, NULL);
+ g_return_val_if_fail (pattern != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ dir = g_dir_open (directory, 0, error);
+ 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
@@ -1699,6 +1931,75 @@
}
/**
+ * fu_common_strsafe:
+ * @str: (nullable): a string to make safe for printing
+ * @maxsz: maximum size of returned string
+ *
+ * Converts a string into something that can be safely printed.
+ *
+ * Return value: (transfer full): safe string, or %NULL if there was nothing valid
+ *
+ * Since: 1.5.5
+ **/
+gchar *
+fu_common_strsafe (const gchar *str, gsize maxsz)
+{
+ gboolean valid = FALSE;
+ g_autoptr(GString) tmp = NULL;
+
+ /* sanity check */
+ if (str == NULL || maxsz == 0)
+ return NULL;
+
+ /* replace non-printable chars with '.' */
+ tmp = g_string_sized_new (maxsz);
+ for (gsize i = 0; i < maxsz && str[i] != '\0'; i++) {
+ if (!g_ascii_isprint (str[i])) {
+ g_string_append_c (tmp, '.');
+ continue;
+ }
+ g_string_append_c (tmp, str[i]);
+ if (!g_ascii_isspace (str[i]))
+ valid = TRUE;
+ }
+
+ /* if just junk, don't return 'all dots' */
+ if (tmp->len == 0 || !valid)
+ return NULL;
+ return g_string_free (g_steal_pointer (&tmp), FALSE);
+}
+
+
+/**
+ * fu_common_strjoin_array:
+ * @separator: (nullable): string to insert between each of the strings, or %NULL
+ * @array: (element-type utf8): A #GPtrArray
+ *
+ * Joins an array of strings together to form one long string, with the optional
+ * separator inserted between each of them.
+ *
+ * If @array has no items, the return value will be an empty string.
+ * If @array contains a single item, separator will not appear in the resulting
+ * string.
+ *
+ * Returns: a string
+ *
+ * Since: 1.5.6
+ **/
+gchar *
+fu_common_strjoin_array (const gchar *separator, GPtrArray *array)
+{
+ g_autofree const gchar **strv = NULL;
+
+ g_return_val_if_fail (array != NULL, NULL);
+
+ strv = g_new0 (const gchar *, array->len + 1);
+ for (guint i = 0; i < array->len; i++)
+ strv[i] = g_ptr_array_index (array, i);
+ return g_strjoinv (separator, (gchar **) strv);
+}
+
+/**
* fu_memcpy_safe:
* @dst: destination buffer
* @dst_sz: maximum size of @dst, typically `sizeof(dst)`
@@ -1729,6 +2030,10 @@
const guint8 *src, gsize src_sz, gsize src_offset,
gsize n, GError **error)
{
+ g_return_val_if_fail (dst != NULL, FALSE);
+ g_return_val_if_fail (src != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
if (n == 0)
return TRUE;
@@ -1771,6 +2076,45 @@
}
/**
+ * fu_memdup_safe:
+ * @src: source buffer
+ * @n: number of bytes to copy from @src
+ * @error: A #GError or %NULL
+ *
+ * Duplicates some memory using memdup in a safe way.
+ *
+ * You don't need to use this function in "obviously correct" cases, nor should
+ * you use it when performance is a concern. Only us it when you're not sure if
+ * malicious data from a device or firmware could cause memory corruption.
+ *
+ * NOTE: This function intentionally limits allocation size to 1GB.
+ *
+ * Return value: (transfer full): block of allocated memory, or %NULL for an error.
+ *
+ * Since: 1.5.6
+ **/
+guint8 *
+fu_memdup_safe (const guint8 *src, gsize n, GError **error)
+{
+ /* sanity check */
+ if (n > 0x40000000) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "cannot allocate %uGB of memory",
+ (guint) (n / 0x40000000));
+ return NULL;
+ }
+
+#if GLIB_CHECK_VERSION(2,67,3)
+ /* linear block of memory */
+ return g_memdup2 (src, n);
+#else
+ return g_memdup (src, (guint) n);
+#endif
+}
+
+/**
* fu_common_read_uint8_safe:
* @buf: source buffer
* @bufsz: maximum size of @buf, typically `sizeof(buf)`
@@ -1796,6 +2140,10 @@
GError **error)
{
guint8 tmp;
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
if (!fu_memcpy_safe (&tmp, sizeof(tmp), 0x0, /* dst */
buf, bufsz, offset, /* src */
sizeof(tmp), error))
@@ -1833,6 +2181,10 @@
GError **error)
{
guint8 dst[2] = { 0x0 };
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
if (!fu_memcpy_safe (dst, sizeof(dst), 0x0, /* dst */
buf, bufsz, offset, /* src */
sizeof(dst), error))
@@ -1870,6 +2222,10 @@
GError **error)
{
guint8 dst[4] = { 0x0 };
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
if (!fu_memcpy_safe (dst, sizeof(dst), 0x0, /* dst */
buf, bufsz, offset, /* src */
sizeof(dst), error))
@@ -1880,34 +2236,222 @@
}
/**
- * fu_byte_array_append_uint8:
- * @array: A #GByteArray
- * @data: #guint8
+ * fu_common_read_uint64_safe:
+ * @buf: source buffer
+ * @bufsz: maximum size of @buf, typically `sizeof(buf)`
+ * @offset: offset in bytes into @buf to copy from
+ * @value: (out) (allow-none): the parsed value
+ * @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
+ * @error: A #GError or %NULL
*
- * Adds a 8 bit integer to a byte array
+ * Read a value from a buffer using a specified endian in a safe way.
*
- * Since: 1.3.1
+ * You don't need to use this function in "obviously correct" cases, nor should
+ * you use it when performance is a concern. Only us it when you're not sure if
+ * malicious data from a device or firmware could cause memory corruption.
+ *
+ * Return value: %TRUE if @value was set, %FALSE otherwise
+ *
+ * Since: 1.5.8
**/
-void
-fu_byte_array_append_uint8 (GByteArray *array, guint8 data)
+gboolean
+fu_common_read_uint64_safe (const guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint64 *value,
+ FuEndianType endian,
+ GError **error)
{
- g_byte_array_append (array, &data, sizeof(data));
+ guint8 dst[8] = { 0x0 };
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (!fu_memcpy_safe (dst, sizeof(dst), 0x0, /* dst */
+ buf, bufsz, offset, /* src */
+ sizeof(dst), error))
+ return FALSE;
+ if (value != NULL)
+ *value = fu_common_read_uint64 (dst, endian);
+ return TRUE;
}
/**
- * fu_byte_array_append_uint16:
- * @array: A #GByteArray
- * @data: #guint16
- * @endian: #FuEndianType
+ * fu_common_write_uint8_safe:
+ * @buf: source buffer
+ * @bufsz: maximum size of @buf, typically `sizeof(buf)`
+ * @offset: offset in bytes into @buf to write to
+ * @value: the value to write
+ * @error: A #GError or %NULL
*
- * Adds a 16 bit integer to a byte array
+ * Write a value to a buffer in a safe way.
*
- * Since: 1.3.1
+ * You don't need to use this function in "obviously correct" cases, nor should
+ * you use it when performance is a concern. Only us it when you're not sure if
+ * malicious data from a device or firmware could cause memory corruption.
+ *
+ * Return value: %TRUE if @value was written, %FALSE otherwise
+ *
+ * Since: 1.5.8
**/
-void
-fu_byte_array_append_uint16 (GByteArray *array, guint16 data, FuEndianType endian)
-{
- guint8 buf[2];
+gboolean
+fu_common_write_uint8_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint8 value,
+ GError **error)
+{
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ return fu_memcpy_safe (buf, bufsz, offset, /* dst */
+ &value, sizeof(value), 0x0, /* src */
+ sizeof(value), error);
+}
+
+/**
+ * fu_common_write_uint16_safe:
+ * @buf: source buffer
+ * @bufsz: maximum size of @buf, typically `sizeof(buf)`
+ * @offset: offset in bytes into @buf to write to
+ * @value: the value to write
+ * @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
+ * @error: A #GError or %NULL
+ *
+ * Write a value to a buffer using a specified endian in a safe way.
+ *
+ * You don't need to use this function in "obviously correct" cases, nor should
+ * you use it when performance is a concern. Only us it when you're not sure if
+ * malicious data from a device or firmware could cause memory corruption.
+ *
+ * Return value: %TRUE if @value was written, %FALSE otherwise
+ *
+ * Since: 1.5.8
+ **/
+gboolean
+fu_common_write_uint16_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint16 value,
+ FuEndianType endian,
+ GError **error)
+{
+ guint8 tmp[2] = { 0x0 };
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ fu_common_write_uint16 (tmp, value, endian);
+ return fu_memcpy_safe (buf, bufsz, offset, /* dst */
+ tmp, sizeof(tmp), 0x0, /* src */
+ sizeof(tmp), error);
+}
+
+/**
+ * fu_common_write_uint32_safe:
+ * @buf: source buffer
+ * @bufsz: maximum size of @buf, typically `sizeof(buf)`
+ * @offset: offset in bytes into @buf to write to
+ * @value: the value to write
+ * @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
+ * @error: A #GError or %NULL
+ *
+ * Write a value to a buffer using a specified endian in a safe way.
+ *
+ * You don't need to use this function in "obviously correct" cases, nor should
+ * you use it when performance is a concern. Only us it when you're not sure if
+ * malicious data from a device or firmware could cause memory corruption.
+ *
+ * Return value: %TRUE if @value was written, %FALSE otherwise
+ *
+ * Since: 1.5.8
+ **/
+gboolean
+fu_common_write_uint32_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint32 value,
+ FuEndianType endian,
+ GError **error)
+{
+ guint8 tmp[4] = { 0x0 };
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ fu_common_write_uint32 (tmp, value, endian);
+ return fu_memcpy_safe (buf, bufsz, offset, /* dst */
+ tmp, sizeof(tmp), 0x0, /* src */
+ sizeof(tmp), error);
+}
+
+/**
+ * fu_common_write_uint64_safe:
+ * @buf: source buffer
+ * @bufsz: maximum size of @buf, typically `sizeof(buf)`
+ * @offset: offset in bytes into @buf to write to
+ * @value: the value to write
+ * @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
+ * @error: A #GError or %NULL
+ *
+ * Write a value to a buffer using a specified endian in a safe way.
+ *
+ * You don't need to use this function in "obviously correct" cases, nor should
+ * you use it when performance is a concern. Only us it when you're not sure if
+ * malicious data from a device or firmware could cause memory corruption.
+ *
+ * Return value: %TRUE if @value was written, %FALSE otherwise
+ *
+ * Since: 1.5.8
+ **/
+gboolean
+fu_common_write_uint64_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint64 value,
+ FuEndianType endian,
+ GError **error)
+{
+ guint8 tmp[8] = { 0x0 };
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ fu_common_write_uint64 (tmp, value, endian);
+ return fu_memcpy_safe (buf, bufsz, offset, /* dst */
+ tmp, sizeof(tmp), 0x0, /* src */
+ sizeof(tmp), error);
+}
+
+/**
+ * fu_byte_array_append_uint8:
+ * @array: A #GByteArray
+ * @data: #guint8
+ *
+ * Adds a 8 bit integer to a byte array
+ *
+ * Since: 1.3.1
+ **/
+void
+fu_byte_array_append_uint8 (GByteArray *array, guint8 data)
+{
+ g_byte_array_append (array, &data, sizeof(data));
+}
+
+/**
+ * fu_byte_array_append_uint16:
+ * @array: A #GByteArray
+ * @data: #guint16
+ * @endian: #FuEndianType
+ *
+ * Adds a 16 bit integer to a byte array
+ *
+ * Since: 1.3.1
+ **/
+void
+fu_byte_array_append_uint16 (GByteArray *array, guint16 data, FuEndianType endian)
+{
+ guint8 buf[2];
fu_common_write_uint16 (buf, data, endian);
g_byte_array_append (array, buf, sizeof(buf));
}
@@ -1931,6 +2475,42 @@
}
/**
+ * fu_byte_array_append_uint64:
+ * @array: A #GByteArray
+ * @data: #guint64
+ * @endian: #FuEndianType
+ *
+ * Adds a 64 bit integer to a byte array
+ *
+ * Since: 1.5.8
+ **/
+void
+fu_byte_array_append_uint64 (GByteArray *array, guint64 data, FuEndianType endian)
+{
+ guint8 buf[8];
+ fu_common_write_uint64 (buf, data, endian);
+ 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:
*
* Determines if kernel lockdown in effect
@@ -1963,3 +2543,665 @@
return FALSE;
#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;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* 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 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.
+ * Deprecated: 1.5.5: Use fu_common_get_cpu_vendor() instead.
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_common_is_cpu_intel (void)
+{
+ return fu_common_get_cpu_vendor () == FU_CPU_VENDOR_INTEL;
+}
+
+/**
+ * fu_common_get_cpu_vendor:
+ *
+ * Uses CPUID to discover the CPU vendor.
+ *
+ * Return value: a #FuCpuVendor, e.g. %FU_CPU_VENDOR_AMD if the vendor was AMD.
+ *
+ * Since: 1.5.5
+ **/
+FuCpuVendor
+fu_common_get_cpu_vendor (void)
+{
+#ifdef HAVE_CPUID_H
+ guint ebx = 0;
+ guint ecx = 0;
+ guint edx = 0;
+
+ if (fu_common_cpuid (0x0, NULL, &ebx, &ecx, &edx, NULL)) {
+ if (ebx == signature_INTEL_ebx &&
+ edx == signature_INTEL_edx &&
+ ecx == signature_INTEL_ecx) {
+ return FU_CPU_VENDOR_INTEL;
+ }
+ if (ebx == signature_AMD_ebx &&
+ edx == signature_AMD_edx &&
+ ecx == signature_AMD_ecx) {
+ return FU_CPU_VENDOR_AMD;
+ }
+ }
+#endif
+
+ /* failed */
+ return FU_CPU_VENDOR_UNKNOWN;
+}
+
+/**
+ * fu_common_is_live_media:
+ *
+ * Checks if the user is running from a live media using various heuristics.
+ *
+ * Returns: %TRUE if live
+ *
+ * Since: 1.4.6
+ **/
+gboolean
+fu_common_is_live_media (void)
+{
+ gsize bufsz = 0;
+ g_autofree gchar *buf = NULL;
+ g_auto(GStrv) tokens = NULL;
+ const gchar *args[] = {
+ "rd.live.image",
+ "boot=live",
+ NULL, /* last entry */
+ };
+ if (g_file_test ("/cdrom/.disk/info", G_FILE_TEST_EXISTS))
+ return TRUE;
+ if (!g_file_get_contents ("/proc/cmdline", &buf, &bufsz, NULL))
+ return FALSE;
+ if (bufsz == 0)
+ return FALSE;
+ tokens = fu_common_strnsplit (buf, bufsz - 1, " ", -1);
+ for (guint i = 0; args[i] != NULL; i++) {
+ if (g_strv_contains ((const gchar * const *) tokens, args[i]))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * fu_common_get_memory_size:
+ *
+ * Returns the size of physical memory.
+ *
+ * Returns: bytes
+ *
+ * Since: 1.5.6
+ **/
+guint64
+fu_common_get_memory_size (void)
+{
+#ifdef _WIN32
+ MEMORYSTATUSEX status;
+ status.dwLength = sizeof(status);
+ GlobalMemoryStatusEx (&status);
+ return (guint64) status.ullTotalPhys;
+#else
+ return sysconf (_SC_PHYS_PAGES) * sysconf (_SC_PAGE_SIZE);
+#endif
+}
+
+static GPtrArray *
+fu_common_get_block_devices (GError **error)
+{
+ GVariantBuilder builder;
+ 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,
+ UDISKS_DBUS_PATH,
+ UDISKS_DBUS_MANAGER_INTERFACE,
+ NULL, error);
+ if (proxy == NULL) {
+ g_prefix_error (error, "failed to find %s: ", UDISKS_DBUS_SERVICE);
+ return NULL;
+ }
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ output = g_dbus_proxy_call_sync (proxy,
+ "GetBlockDevices",
+ g_variant_new ("(a{sv})", &builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, error);
+ 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 ((GDestroyNotify) g_object_unref);
+ g_variant_get (output, "(ao)", &iter);
+ 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);
+}
+
+static const gchar *
+fu_common_convert_to_gpt_type (const gchar *type)
+{
+ struct {
+ const gchar *mbr;
+ const gchar *gpt;
+ } typeguids[] = {
+ { "0xef", "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" }, /* esp */
+ { "0x0b", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" }, /* fat32 */
+ { NULL, NULL }
+ };
+ for (guint i = 0; typeguids[i].mbr != NULL; i++) {
+ if (g_strcmp0 (type, typeguids[i].mbr) == 0)
+ return typeguids[i].gpt;
+ }
+ return type;
+}
+
+/**
+ * fu_common_get_volumes_by_kind:
+ * @kind: A volume kind, typically a GUID
+ * @error: A #GError or NULL
+ *
+ * Finds all volumes of a specific partition type
+ *
+ * Returns: (transfer container) (element-type FuVolume): a #GPtrArray, or %NULL if the kind was not found
+ *
+ * Since: 1.4.6
+ **/
+GPtrArray *
+fu_common_get_volumes_by_kind (const gchar *kind, GError **error)
+{
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GPtrArray) volumes = NULL;
+
+ g_return_val_if_fail (kind != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ 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++) {
+ GDBusProxy *proxy_blk = g_ptr_array_index (devices, i);
+ const gchar *type_str;
+ g_autoptr(FuVolume) vol = NULL;
+ g_autoptr(GDBusProxy) proxy_part = NULL;
+ g_autoptr(GDBusProxy) proxy_fs = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ proxy_part = 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_PARTITION,
+ NULL, error);
+ if (proxy_part == NULL) {
+ 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);
+ 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;
+ }
+ vol = g_object_new (FU_TYPE_VOLUME,
+ "proxy-block", proxy_blk,
+ "proxy-filesystem", proxy_fs,
+ NULL);
+
+ /* convert MBR type to GPT type */
+ type_str = fu_common_convert_to_gpt_type (type_str);
+ g_debug ("device %s, type: %s, internal: %d, fs: %s",
+ g_dbus_proxy_get_object_path (proxy_blk), type_str,
+ fu_volume_is_internal (vol),
+ fu_volume_get_id_type (vol));
+ if (g_strcmp0 (type_str, kind) != 0)
+ continue;
+ g_ptr_array_add (volumes, g_steal_pointer (&vol));
+ }
+ if (volumes->len == 0) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "no volumes of type %s", kind);
+ return NULL;
+ }
+ 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;
+
+ g_return_val_if_fail (device != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, 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:
+ * @devnum: 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;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, 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
+ *
+ * Gets the platform default ESP
+ *
+ * Returns: (transfer full): a #FuVolume, or %NULL if the ESP was not found
+ *
+ * Since: 1.4.6
+ **/
+FuVolume *
+fu_common_get_esp_default (GError **error)
+{
+ const gchar *path_tmp;
+ gboolean has_internal = FALSE;
+ g_autoptr(GPtrArray) volumes_fstab = g_ptr_array_new ();
+ g_autoptr(GPtrArray) volumes_mtab = g_ptr_array_new ();
+ g_autoptr(GPtrArray) volumes_vfat = g_ptr_array_new ();
+ g_autoptr(GPtrArray) volumes = NULL;
+ g_autoptr(GError) error_local = NULL;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* for the test suite use local directory for ESP */
+ path_tmp = g_getenv ("FWUPD_UEFI_ESP_PATH");
+ if (path_tmp != NULL)
+ return fu_volume_new_from_mount_path (path_tmp);
+
+ volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, &error_local);
+ if (volumes == NULL) {
+ g_debug ("%s, falling back to %s", error_local->message, FU_VOLUME_KIND_BDP);
+ volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_BDP, error);
+ if (volumes == NULL) {
+ g_prefix_error (error, "%s: ", error_local->message);
+ return NULL;
+ }
+ }
+
+ /* are there _any_ internal vfat partitions?
+ * remember HintSystem is just that -- a hint! */
+ for (guint i = 0; i < volumes->len; i++) {
+ FuVolume *vol = g_ptr_array_index (volumes, i);
+ g_autofree gchar *type = fu_volume_get_id_type (vol);
+ if (g_strcmp0 (type, "vfat") == 0 &&
+ fu_volume_is_internal (vol)) {
+ has_internal = TRUE;
+ break;
+ }
+ }
+
+ /* filter to vfat partitions */
+ for (guint i = 0; i < volumes->len; i++) {
+ FuVolume *vol = g_ptr_array_index (volumes, i);
+ g_autofree gchar *type = fu_volume_get_id_type (vol);
+ if (type == NULL)
+ continue;
+ if (has_internal && !fu_volume_is_internal (vol))
+ continue;
+ if (g_strcmp0 (type, "vfat") == 0)
+ g_ptr_array_add (volumes_vfat, vol);
+ }
+ if (volumes_vfat->len == 0) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ "No ESP found");
+ return NULL;
+ }
+ for (guint i = 0; i < volumes_vfat->len; i++) {
+ FuVolume *vol = g_ptr_array_index (volumes_vfat, i);
+ g_ptr_array_add (fu_volume_is_mounted (vol) ? volumes_mtab : volumes_fstab, vol);
+ }
+ if (volumes_mtab->len == 1) {
+ FuVolume *vol = g_ptr_array_index (volumes_mtab, 0);
+ return g_object_ref (vol);
+ }
+ if (volumes_mtab->len == 0 && volumes_fstab->len == 1) {
+ FuVolume *vol = g_ptr_array_index (volumes_fstab, 0);
+ return g_object_ref (vol);
+ }
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ "More than one available ESP");
+ return NULL;
+}
+
+/**
+ * fu_common_get_esp_for_path:
+ * @esp_path: A path to the ESP
+ * @error: A #GError or NULL
+ *
+ * Gets the platform ESP using a UNIX or UDisks path
+ *
+ * Returns: (transfer full): a #FuVolume, or %NULL if the ESP was not found
+ *
+ * Since: 1.4.6
+ **/
+FuVolume *
+fu_common_get_esp_for_path (const gchar *esp_path, GError **error)
+{
+ g_autofree gchar *basename = NULL;
+ g_autoptr(GPtrArray) volumes = NULL;
+ g_autoptr(GError) error_local = NULL;
+
+ g_return_val_if_fail (esp_path != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, &error_local);
+ if (volumes == NULL) {
+ /* check if it's a valid directory already */
+ if (g_file_test (esp_path, G_FILE_TEST_IS_DIR))
+ return fu_volume_new_from_mount_path (esp_path);
+ g_propagate_error (error, g_steal_pointer (&error_local));
+ return NULL;
+ }
+ basename = g_path_get_basename (esp_path);
+ 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_mount_point (vol));
+ if (g_strcmp0 (basename, vol_basename) == 0)
+ return g_object_ref (vol);
+ }
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ "No ESP with path %s",
+ 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);
+}
+
+/**
+ * fu_common_uri_get_scheme:
+ * @uri: valid URI, e.g. `https://foo.bar/baz`
+ *
+ * Returns the USI scheme for the given URI.
+ *
+ * Returns: scheme value, or %NULL if invalid, e.g. `https`
+ *
+ * Since: 1.5.6
+ **/
+gchar *
+fu_common_uri_get_scheme (const gchar *uri)
+{
+ gchar *tmp;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ tmp = g_strstr_len (uri, -1, ":");
+ if (tmp == NULL || tmp[0] == '\0')
+ return NULL;
+ return g_utf8_strdown (uri, tmp - uri);
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common-cab.c fwupd-1.5.8/libfwupdplugin/fu-common-cab.c
--- fwupd-1.4.5/libfwupdplugin/fu-common-cab.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common-cab.c 2021-03-31 20:08:32.000000000 +0000
@@ -27,6 +27,10 @@
fu_common_cab_build_silo (GBytes *blob, guint64 size_max, GError **error)
{
g_autoptr(FuCabinet) cabinet = fu_cabinet_new ();
+
+ g_return_val_if_fail (blob != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
fu_cabinet_set_size_max (cabinet, size_max);
if (!fu_cabinet_parse (cabinet, blob, FU_CABINET_PARSE_FLAG_NONE, error))
return NULL;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common-cab.h fwupd-1.5.8/libfwupdplugin/fu-common-cab.h
--- fwupd-1.4.5/libfwupdplugin/fu-common-cab.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common-cab.h 2021-03-31 20:08:32.000000000 +0000
@@ -10,4 +10,5 @@
XbSilo *fu_common_cab_build_silo (GBytes *blob,
guint64 size_max,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common-guid.c fwupd-1.5.8/libfwupdplugin/fu-common-guid.c
--- fwupd-1.4.5/libfwupdplugin/fu-common-guid.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common-guid.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common-guid.h fwupd-1.5.8/libfwupdplugin/fu-common-guid.h
--- fwupd-1.4.5/libfwupdplugin/fu-common-guid.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common-guid.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common.h fwupd-1.5.8/libfwupdplugin/fu-common.h
--- fwupd-1.4.5/libfwupdplugin/fu-common.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common.h 2021-03-31 20:08:32.000000000 +0000
@@ -8,6 +8,8 @@
#include
+#include "fu-volume.h"
+
/**
* FuAppFlags:
* @FU_APP_FLAGS_NONE: No flags set
@@ -53,9 +55,11 @@
* @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
**/
@@ -71,13 +75,31 @@
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;
+/**
+ * FuCpuVendor:
+ * @FU_CPU_VENDOR_UNKNOWN: Unknown
+ * @FU_CPU_VENDOR_INTEL: Intel
+ * @FU_CPU_VENDOR_AMD: AMD
+ *
+ * The CPU vendor.
+ **/
+typedef enum {
+ FU_CPU_VENDOR_UNKNOWN,
+ FU_CPU_VENDOR_INTEL,
+ FU_CPU_VENDOR_AMD,
+ /*< private >*/
+ FU_CPU_VENDOR_LAST
+} FuCpuVendor;
+
typedef void (*FuOutputHandler) (const gchar *line,
gpointer user_data);
@@ -86,38 +108,53 @@
gpointer handler_user_data,
guint timeout_ms,
GCancellable *cancellable,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gchar *fu_common_get_path (FuPathKind path_kind);
gchar *fu_common_realpath (const gchar *filename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fu_common_filename_glob (const gchar *directory,
+ const gchar *pattern,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_fnmatch (const gchar *pattern,
const gchar *str);
gboolean fu_common_rmtree (const gchar *directory,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GPtrArray *fu_common_get_files_recursive (const gchar *path,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_mkdir_parent (const gchar *filename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_set_contents_bytes (const gchar *filename,
GBytes *bytes,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_common_get_contents_bytes (const gchar *filename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_common_get_contents_fd (gint fd,
gsize count,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_extract_archive (GBytes *blob,
const gchar *dir,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_common_firmware_builder (GBytes *bytes,
const gchar *script_fn,
const gchar *output_fn,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GError *fu_common_error_array_get_best (GPtrArray *errors);
guint64 fu_common_strtoull (const gchar *str);
gchar *fu_common_find_program_in_path (const gchar *basename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gchar *fu_common_strstrip (const gchar *str);
void fu_common_dump_raw (const gchar *log_domain,
const gchar *title,
@@ -138,15 +175,26 @@
gboolean fu_common_bytes_is_empty (GBytes *bytes);
gboolean fu_common_bytes_compare (GBytes *bytes1,
GBytes *bytes2,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_bytes_compare_raw (const guint8 *buf1,
gsize bufsz1,
const guint8 *buf2,
gsize bufsz2,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_common_bytes_pad (GBytes *bytes,
gsize sz);
+GBytes *fu_common_bytes_new_offset (GBytes *bytes,
+ gsize offset,
+ gsize length,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gsize fu_common_strwidth (const gchar *text);
+guint8 *fu_memdup_safe (const guint8 *src,
+ gsize n,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_memcpy_safe (guint8 *dst,
gsize dst_sz,
gsize dst_offset,
@@ -154,25 +202,65 @@
gsize src_sz,
gsize src_offset,
gsize n,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_read_uint8_safe (const guint8 *buf,
gsize bufsz,
gsize offset,
guint8 *value,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_read_uint16_safe (const guint8 *buf,
gsize bufsz,
gsize offset,
guint16 *value,
FuEndianType endian,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_read_uint32_safe (const guint8 *buf,
gsize bufsz,
gsize offset,
guint32 *value,
FuEndianType endian,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_common_read_uint64_safe (const guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint64 *value,
+ FuEndianType endian,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_common_write_uint8_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint8 value,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_common_write_uint16_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint16 value,
+ FuEndianType endian,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_common_write_uint32_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint32 value,
+ FuEndianType endian,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_common_write_uint64_safe (guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint64 value,
+ FuEndianType endian,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+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,
@@ -181,6 +269,9 @@
void fu_byte_array_append_uint32 (GByteArray *array,
guint32 data,
FuEndianType endian);
+void fu_byte_array_append_uint64 (GByteArray *array,
+ guint64 data,
+ FuEndianType endian);
void fu_common_write_uint16 (guint8 *buf,
guint16 val_native,
@@ -188,10 +279,15 @@
void fu_common_write_uint32 (guint8 *buf,
guint32 val_native,
FuEndianType endian);
+void fu_common_write_uint64 (guint8 *buf,
+ guint64 val_native,
+ FuEndianType endian);
guint16 fu_common_read_uint16 (const guint8 *buf,
FuEndianType endian);
guint32 fu_common_read_uint32 (const guint8 *buf,
FuEndianType endian);
+guint64 fu_common_read_uint64 (const guint8 *buf,
+ FuEndianType endian);
guint fu_common_string_replace (GString *string,
const gchar *search,
@@ -216,4 +312,46 @@
gsize sz,
const gchar *delimiter,
gint max_tokens);
+gchar *fu_common_strsafe (const gchar *str,
+ gsize maxsz);
+gchar *fu_common_strjoin_array (const gchar *separator,
+ GPtrArray *array);
gboolean fu_common_kernel_locked_down (void);
+gboolean fu_common_cpuid (guint32 leaf,
+ guint32 *eax,
+ guint32 *ebx,
+ guint32 *ecx,
+ guint32 *edx,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_common_is_cpu_intel (void)
+G_DEPRECATED_FOR(fu_common_get_cpu_vendor);
+FuCpuVendor fu_common_get_cpu_vendor (void);
+gboolean fu_common_is_live_media (void);
+guint64 fu_common_get_memory_size (void);
+GPtrArray *fu_common_get_volumes_by_kind (const gchar *kind,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FuVolume *fu_common_get_volume_by_device (const gchar *device,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FuVolume *fu_common_get_volume_by_devnum (guint32 devnum,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FuVolume *fu_common_get_esp_for_path (const gchar *esp_path,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+FuVolume *fu_common_get_esp_default (GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+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);
+gchar *fu_common_uri_get_scheme (const gchar *uri);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common-version.c fwupd-1.5.8/libfwupdplugin/fu-common-version.c
--- fwupd-1.4.5/libfwupdplugin/fu-common-version.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common-version.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -238,35 +238,57 @@
return TRUE;
}
-static gboolean
-fu_common_version_is_valid_semver_char (gchar c)
-{
- if (g_ascii_isdigit (c))
- return TRUE;
- if (c == '.')
- return TRUE;
- return FALSE;
-}
-
/**
* fu_common_version_ensure_semver:
* @version: A version number, e.g. ` V1.2.3 `
*
* Builds a semver from the possibly crazy version number.
*
- * Returns: A version number, e.g. "1.2.3"
+ * Returns: A version number, e.g. "1.2.3", or %NULL if the version was not valid
*
* Since: 1.2.9
*/
gchar *
fu_common_version_ensure_semver (const gchar *version)
{
- GString *version_safe = g_string_new (NULL);
+ gboolean dot_valid = FALSE;
+ guint digit_cnt = 0;
+ g_autoptr(GString) version_safe = g_string_new (NULL);
+
+ /* invalid */
+ if (version == NULL)
+ return NULL;
+
+ /* hex prefix */
+ if (g_str_has_prefix (version, "0x")) {
+ return fu_common_version_parse_from_format (version,
+ FWUPD_VERSION_FORMAT_TRIPLET);
+ }
+
+ /* make sane */
for (guint i = 0; version[i] != '\0'; i++) {
- if (fu_common_version_is_valid_semver_char (version[i]))
+ if (g_ascii_isdigit (version[i])) {
g_string_append_c (version_safe, version[i]);
+ digit_cnt++;
+ dot_valid = TRUE;
+ continue;
+ }
+ if (version[i] == '-' || version[i] == '~') {
+ g_string_append_c (version_safe, '.');
+ dot_valid = FALSE;
+ continue;
+ }
+ if (version[i] == '.' && dot_valid && version[i + 1] != '\0') {
+ g_string_append_c (version_safe, version[i]);
+ dot_valid = FALSE;
+ continue;
+ }
}
- return g_string_free (version_safe, FALSE);
+
+ /* found no digits */
+ if (digit_cnt == 0)
+ return NULL;
+ return g_string_free (g_steal_pointer (&version_safe), FALSE);
}
/**
@@ -439,15 +461,16 @@
FwupdVersionFormat fmt_base = fu_common_version_convert_base (fmt);
FwupdVersionFormat fmt_guess;
+ g_return_val_if_fail (version != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* don't touch */
if (fmt == FWUPD_VERSION_FORMAT_PLAIN)
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);
@@ -464,42 +487,8 @@
return TRUE;
}
-/**
- * fu_common_vercmp_full:
- * @version_a: the semver release version, e.g. 1.2.3
- * @version_b: the semver release version, e.g. 1.2.3.1
- * @fmt: a #FwupdVersionFormat, e.g. %FWUPD_VERSION_FORMAT_PLAIN
- *
- * Compares version numbers for sorting taking into account the version format
- * if required.
- *
- * Returns: -1 if a < b, +1 if a > b, 0 if they are equal, and %G_MAXINT on error
- *
- * Since: 1.3.9
- */
-gint
-fu_common_vercmp_full (const gchar *version_a,
- const gchar *version_b,
- FwupdVersionFormat fmt)
-{
- if (fmt == FWUPD_VERSION_FORMAT_PLAIN)
- return g_strcmp0 (version_a, version_b);
- return fu_common_vercmp (version_a, version_b);
-}
-
-/**
- * fu_common_vercmp:
- * @version_a: the semver release version, e.g. 1.2.3
- * @version_b: the semver release version, e.g. 1.2.3.1
- *
- * Compares version numbers for sorting.
- *
- * Returns: -1 if a < b, +1 if a > b, 0 if they are equal, and %G_MAXINT on error
- *
- * Since: 0.3.5
- */
-gint
-fu_common_vercmp (const gchar *version_a, const gchar *version_b)
+static gint
+fu_common_vercmp_safe (const gchar *version_a, const gchar *version_b)
{
guint longest_split;
g_auto(GStrv) split_a = NULL;
@@ -509,7 +498,7 @@
if (version_a == NULL || version_b == NULL)
return G_MAXINT;
- /* optimisation */
+ /* optimization */
if (g_strcmp0 (version_a, version_b) == 0)
return 0;
@@ -551,3 +540,50 @@
/* we really shouldn't get here */
return 0;
}
+
+/**
+ * fu_common_vercmp:
+ * @version_a: the semver release version, e.g. 1.2.3
+ * @version_b: the semver release version, e.g. 1.2.3.1
+ *
+ * Compares version numbers for sorting.
+ *
+ * Returns: -1 if a < b, +1 if a > b, 0 if they are equal, and %G_MAXINT on error
+ *
+ * Since: 0.3.5
+ */
+gint
+fu_common_vercmp (const gchar *version_a, const gchar *version_b)
+{
+ return fu_common_vercmp_safe (version_a, version_b);
+}
+
+/**
+ * fu_common_vercmp_full:
+ * @version_a: the semver release version, e.g. 1.2.3
+ * @version_b: the semver release version, e.g. 1.2.3.1
+ * @fmt: a #FwupdVersionFormat, e.g. %FWUPD_VERSION_FORMAT_PLAIN
+ *
+ * Compares version numbers for sorting taking into account the version format
+ * if required.
+ *
+ * Returns: -1 if a < b, +1 if a > b, 0 if they are equal, and %G_MAXINT on error
+ *
+ * Since: 1.3.9
+ */
+gint
+fu_common_vercmp_full (const gchar *version_a,
+ const gchar *version_b,
+ FwupdVersionFormat fmt)
+{
+ 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_safe (hex_a, hex_b);
+ }
+ return fu_common_vercmp_safe (version_a, version_b);
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-common-version.h fwupd-1.5.8/libfwupdplugin/fu-common-version.h
--- fwupd-1.4.5/libfwupdplugin/fu-common-version.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-common-version.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -29,4 +29,5 @@
FwupdVersionFormat fu_common_version_guess_format (const gchar *version);
gboolean fu_common_version_verify_format (const gchar *version,
FwupdVersionFormat fmt,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-device.c fwupd-1.5.8/libfwupdplugin/fu-device.c
--- fwupd-1.4.5/libfwupdplugin/fu-device.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-device.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -20,6 +20,9 @@
#include "fwupd-common.h"
#include "fwupd-device-private.h"
+#define FU_DEVICE_RETRY_OPEN_COUNT 5
+#define FU_DEVICE_RETRY_OPEN_DELAY 500 /* ms */
+
/**
* SECTION:fu-device
* @short_description: a physical or logical device
@@ -36,19 +39,19 @@
gchar *equivalent_id;
gchar *physical_id;
gchar *logical_id;
+ gchar *backend_id;
gchar *proxy_guid;
FuDevice *alternate;
- FuDevice *parent; /* noref */
FuDevice *proxy; /* noref */
FuQuirks *quirks;
- GHashTable *metadata;
+ GHashTable *metadata; /* (nullable) */
GRWLock metadata_mutex;
GPtrArray *parent_guids;
GRWLock parent_guids_mutex;
- GPtrArray *children;
guint remove_delay; /* ms */
guint progress;
- guint order;
+ guint battery_level;
+ gint order;
guint priority;
guint poll_id;
gboolean done_probe;
@@ -61,6 +64,7 @@
GPtrArray *possible_plugins;
GPtrArray *retry_recs; /* of FuDeviceRetryRecovery */
guint retry_delay;
+ FuDeviceInternalFlags internal_flags;
} FuDevicePrivate;
typedef struct {
@@ -72,10 +76,11 @@
enum {
PROP_0,
PROP_PROGRESS,
+ PROP_BATTERY_LEVEL,
PROP_PHYSICAL_ID,
PROP_LOGICAL_ID,
+ PROP_BACKEND_ID,
PROP_QUIRKS,
- PROP_PARENT,
PROP_PROXY,
PROP_LAST
};
@@ -93,18 +98,21 @@
case PROP_PROGRESS:
g_value_set_uint (value, priv->progress);
break;
+ case PROP_BATTERY_LEVEL:
+ g_value_set_uint (value, priv->battery_level);
+ break;
case PROP_PHYSICAL_ID:
g_value_set_string (value, priv->physical_id);
break;
case PROP_LOGICAL_ID:
g_value_set_string (value, priv->logical_id);
break;
+ case PROP_BACKEND_ID:
+ g_value_set_string (value, priv->backend_id);
+ break;
case PROP_QUIRKS:
g_value_set_object (value, priv->quirks);
break;
- case PROP_PARENT:
- g_value_set_object (value, priv->parent);
- break;
case PROP_PROXY:
g_value_set_object (value, priv->proxy);
break;
@@ -123,18 +131,21 @@
case PROP_PROGRESS:
fu_device_set_progress (self, g_value_get_uint (value));
break;
+ case PROP_BATTERY_LEVEL:
+ fu_device_set_battery_level (self, g_value_get_uint (value));
+ break;
case PROP_PHYSICAL_ID:
fu_device_set_physical_id (self, g_value_get_string (value));
break;
case PROP_LOGICAL_ID:
fu_device_set_logical_id (self, g_value_get_string (value));
break;
+ case PROP_BACKEND_ID:
+ fu_device_set_backend_id (self, g_value_get_string (value));
+ break;
case PROP_QUIRKS:
fu_device_set_quirks (self, g_value_get_object (value));
break;
- case PROP_PARENT:
- fu_device_set_parent (self, g_value_get_object (value));
- break;
case PROP_PROXY:
fu_device_set_proxy (self, g_value_get_object (value));
break;
@@ -145,6 +156,123 @@
}
/**
+ * fu_device_internal_flag_to_string:
+ * @flag: A #FuDeviceInternalFlags, e.g. %FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON
+ *
+ * Converts a #FuDeviceInternalFlags to a string.
+ *
+ * Return value: identifier string
+ *
+ * Since: 1.5.5
+ **/
+const gchar *
+fu_device_internal_flag_to_string (FuDeviceInternalFlags flag)
+{
+ if (flag == FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON)
+ return "md-set-icon";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME)
+ return "md-set-name";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME_CATEGORY)
+ return "md-set-name-category";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_MD_SET_VERFMT)
+ return "md-set-verfmt";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_ONLY_SUPPORTED)
+ return "only-supported";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_NO_AUTO_INSTANCE_IDS)
+ return "no-auto-instance-ids";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER)
+ return "ensure-semver";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_RETRY_OPEN)
+ return "retry-open";
+ if (flag == FU_DEVICE_INTERNAL_FLAG_REPLUG_MATCH_GUID)
+ return "replug-match-guid";
+ return NULL;
+}
+
+/**
+ * fu_device_internal_flag_from_string:
+ * @flag: A string, e.g. `md-set-icon`
+ *
+ * Converts a string to a #FuDeviceInternalFlags.
+ *
+ * Return value: enumerated value
+ *
+ * Since: 1.5.5
+ **/
+FuDeviceInternalFlags
+fu_device_internal_flag_from_string (const gchar *flag)
+{
+ if (g_strcmp0 (flag, "md-set-icon") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON;
+ if (g_strcmp0 (flag, "md-set-name") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME;
+ if (g_strcmp0 (flag, "md-set-name-category") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME_CATEGORY;
+ if (g_strcmp0 (flag, "md-set-verfmt") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_MD_SET_VERFMT;
+ if (g_strcmp0 (flag, "only-supported") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_ONLY_SUPPORTED;
+ if (g_strcmp0 (flag, "no-auto-instance-ids") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_NO_AUTO_INSTANCE_IDS;
+ if (g_strcmp0 (flag, "ensure-semver") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER;
+ if (g_strcmp0 (flag, "retry-open") == 0)
+ return FU_DEVICE_INTERNAL_FLAG_RETRY_OPEN;
+ return FU_DEVICE_INTERNAL_FLAG_UNKNOWN;
+}
+
+/**
+ * fu_device_add_internal_flag:
+ * @self: A #FuDevice
+ * @flag: A #FuDeviceInternalFlags, e.g. %FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON
+ *
+ * Adds a private flag that stays internal to the engine and is not leaked to the client.
+ *
+ * Since: 1.5.5
+ **/
+void
+fu_device_add_internal_flag (FuDevice *self, FuDeviceInternalFlags flag)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_DEVICE (self));
+ priv->internal_flags |= flag;
+}
+
+/**
+ * fu_device_remove_internal_flag:
+ * @self: A #FuDevice
+ * @flag: A #FuDeviceInternalFlags, e.g. %FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON
+ *
+ * Removes a private flag that stays internal to the engine and is not leaked to the client.
+ *
+ * Since: 1.5.5
+ **/
+void
+fu_device_remove_internal_flag (FuDevice *self, FuDeviceInternalFlags flag)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_DEVICE (self));
+ priv->internal_flags &= ~flag;
+}
+
+/**
+ * fu_device_has_internal_flag:
+ * @self: A #FuDevice
+ * @flag: A #FuDeviceInternalFlags, e.g. %FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON
+ *
+ * Tests for a private flag that stays internal to the engine and is not leaked to the client.
+ *
+ * Since: 1.5.5
+ **/
+gboolean
+fu_device_has_internal_flag (FuDevice *self, FuDeviceInternalFlags flag)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_DEVICE (self), FALSE);
+ return (priv->internal_flags & flag) > 0;
+}
+
+/**
* fu_device_get_possible_plugins:
* @self: A #FuDevice
*
@@ -169,12 +297,24 @@
* Adds a plugin name to the list of plugins that *might* be able to handle this
* device. This is tyically called from a quirk handler.
*
- * Since: 1.3.3
+ * Duplicate plugin names are ignored.
+ *
+ * Since: 1.5.1
**/
-static void
+void
fu_device_add_possible_plugin (FuDevice *self, const gchar *plugin)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
+
+ g_return_if_fail (FU_IS_DEVICE (self));
+ g_return_if_fail (plugin != NULL);
+
+ /* add if it does not already exist */
+#if GLIB_CHECK_VERSION(2,54,3)
+ if (g_ptr_array_find_with_equal_func (priv->possible_plugins, plugin,
+ g_str_equal, NULL))
+ return;
+#endif
g_ptr_array_add (priv->possible_plugins, g_strdup (plugin));
}
@@ -230,10 +370,11 @@
}
/**
- * fu_device_retry:
+ * fu_device_retry_full:
* @self: A #FuDevice
* @func: (scope async): A function to execute
* @count: The number of tries to try the function
+ * @delay: The delay between each try in ms
* @user_data: (nullable): a helper to pass to @user_data
* @error: A #GError
*
@@ -246,14 +387,15 @@
* If the reset function returns %FALSE, then the function returns straight away
* without processing any pending retries.
*
- * Since: 1.4.0
+ * Since: 1.5.5
**/
gboolean
-fu_device_retry (FuDevice *self,
- FuDeviceRetryFunc func,
- guint count,
- gpointer user_data,
- GError **error)
+fu_device_retry_full (FuDevice *self,
+ FuDeviceRetryFunc func,
+ guint count,
+ guint delay,
+ gpointer user_data,
+ GError **error)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
@@ -266,8 +408,8 @@
g_autoptr(GError) error_local = NULL;
/* delay */
- if (i > 0 && priv->retry_delay > 0)
- g_usleep (priv->retry_delay * 1000);
+ if (i > 0 && delay > 0)
+ g_usleep (delay * 1000);
/* run function, if success return success */
if (func (self, user_data, &error_local))
@@ -321,6 +463,38 @@
}
/**
+ * fu_device_retry:
+ * @self: A #FuDevice
+ * @func: (scope async): A function to execute
+ * @count: The number of tries to try the function
+ * @user_data: (nullable): a helper to pass to @user_data
+ * @error: A #GError
+ *
+ * Calls a specific function a number of times, optionally handling the error
+ * with a reset action.
+ *
+ * If fu_device_retry_add_recovery() has not been used then all errors are
+ * considered non-fatal until the last try.
+ *
+ * If the reset function returns %FALSE, then the function returns straight away
+ * without processing any pending retries.
+ *
+ * Since: 1.4.0
+ **/
+gboolean
+fu_device_retry (FuDevice *self,
+ FuDeviceRetryFunc func,
+ guint count,
+ gpointer user_data,
+ GError **error)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ return fu_device_retry_full (self, func, count,
+ priv->retry_delay,
+ user_data, error);
+}
+
+/**
* fu_device_poll:
* @self: A #FuDevice
* @error: A #GError, or %NULL
@@ -405,7 +579,7 @@
*
* Since: 1.0.8
**/
-guint
+gint
fu_device_get_order (FuDevice *self)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
@@ -424,7 +598,7 @@
* Since: 1.0.8
**/
void
-fu_device_set_order (FuDevice *self, guint order)
+fu_device_set_order (FuDevice *self, gint order)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_DEVICE (self));
@@ -498,6 +672,11 @@
{
FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_DEVICE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->equivalent_id, equivalent_id) == 0)
+ return;
+
g_free (priv->equivalent_id);
priv->equivalent_id = g_strdup (equivalent_id);
}
@@ -536,6 +715,11 @@
{
FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_DEVICE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->alternate_id, alternate_id) == 0)
+ return;
+
g_free (priv->alternate_id);
priv->alternate_id = g_strdup (alternate_id);
}
@@ -603,9 +787,8 @@
FuDevice *
fu_device_get_parent (FuDevice *self)
{
- FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
- return priv->parent;
+ return FU_DEVICE (fwupd_device_get_parent (FWUPD_DEVICE (self)));
}
/**
@@ -624,12 +807,13 @@
FuDevice *
fu_device_get_root (FuDevice *self)
{
- FuDevicePrivate *priv = GET_PRIVATE (self);
+ FuDevice *parent;
g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
- while (priv->parent != NULL) {
- self = priv->parent;
- priv = GET_PRIVATE (self);
- }
+ do {
+ parent = fu_device_get_parent (self);
+ if (parent != NULL)
+ self = parent;
+ } while (parent != NULL);
return g_object_ref (self);
}
@@ -649,17 +833,8 @@
void
fu_device_set_parent (FuDevice *self, FuDevice *parent)
{
- FuDevicePrivate *priv = GET_PRIVATE (self);
-
g_return_if_fail (FU_IS_DEVICE (self));
- /* if unspecified, always child before parent */
- if (parent != NULL &&
- fu_device_get_order (parent) == fu_device_get_order (self)) {
- g_debug ("auto-setting %s order", fu_device_get_id (parent));
- fu_device_set_order (parent, fu_device_get_order (self) + 1);
- }
-
/* if the parent has quirks, make the child inherit it */
if (parent != NULL) {
if (fu_device_get_quirks (self) == NULL &&
@@ -667,15 +842,7 @@
fu_device_set_quirks (self, fu_device_get_quirks (parent));
}
- 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 (FWUPD_DEVICE (self),
- parent != NULL ? fu_device_get_id (parent) : NULL);
+ fwupd_device_set_parent (FWUPD_DEVICE (self), FWUPD_DEVICE (parent));
}
/**
@@ -740,9 +907,8 @@
GPtrArray *
fu_device_get_children (FuDevice *self)
{
- FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
- return priv->children;
+ return fwupd_device_get_children (FWUPD_DEVICE (self));
}
/**
@@ -759,16 +925,26 @@
fu_device_add_child (FuDevice *self, FuDevice *child)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
+ GPtrArray *children;
+ g_autoptr(GError) error = NULL;
+
g_return_if_fail (FU_IS_DEVICE (self));
g_return_if_fail (FU_IS_DEVICE (child));
/* add if the child does not already exist */
- for (guint i = 0; i < priv->children->len; i++) {
- FuDevice *devtmp = g_ptr_array_index (priv->children, i);
- if (devtmp == child)
- return;
+ fwupd_device_add_child (FWUPD_DEVICE (self), FWUPD_DEVICE (child));
+
+ /* ensure the parent has the MAX() of the childrens removal delay */
+ children = fu_device_get_children (self);
+ for (guint i = 0; i < children->len; i++) {
+ FuDevice *child_tmp = g_ptr_array_index (children, i);
+ guint remove_delay = fu_device_get_remove_delay (child_tmp);
+ if (remove_delay > priv->remove_delay) {
+ g_debug ("setting remove delay to %u as child is greater than %u",
+ remove_delay, priv->remove_delay);
+ priv->remove_delay = remove_delay;
+ }
}
- g_ptr_array_add (priv->children, g_object_ref (child));
/* copy from main device if unset */
if (fu_device_get_physical_id (child) == NULL &&
@@ -776,8 +952,13 @@
fu_device_set_physical_id (child, fu_device_get_physical_id (self));
if (fu_device_get_vendor (child) == NULL)
fu_device_set_vendor (child, fu_device_get_vendor (self));
- if (fu_device_get_vendor_id (child) == NULL)
- fu_device_set_vendor_id (child, fu_device_get_vendor_id (self));
+ if (fu_device_get_vendor_ids(child)->len == 0) {
+ GPtrArray *vendor_ids = fu_device_get_vendor_ids (self);
+ for (guint i = 0; i < vendor_ids->len; i++) {
+ const gchar *vendor_id = g_ptr_array_index (vendor_ids, i);
+ fu_device_add_vendor_id (child, vendor_id);
+ }
+ }
if (fu_device_get_icons(child)->len == 0) {
GPtrArray *icons = fu_device_get_icons (self);
for (guint i = 0; i < icons->len; i++) {
@@ -787,19 +968,11 @@
}
/* ensure the ID is converted */
- fu_device_ensure_id (child, NULL);
+ if (!fu_device_ensure_id (child, &error))
+ g_warning ("failed to ensure child: %s", error->message);
/* ensure the parent is also set on the child */
fu_device_set_parent (child, self);
-
- /* order devices so they are updated in the correct sequence */
- if (fu_device_has_flag (child, FWUPD_DEVICE_FLAG_INSTALL_PARENT_FIRST)) {
- if (priv->order >= fu_device_get_order (child))
- fu_device_set_order (child, priv->order + 1);
- } else {
- if (priv->order <= fu_device_get_order (child))
- priv->order = fu_device_get_order (child) + 1;
- }
}
/**
@@ -978,16 +1151,22 @@
fu_device_set_summary (self, value);
return TRUE;
}
+ if (g_strcmp0 (key, FU_QUIRKS_BRANCH) == 0) {
+ fu_device_set_branch (self, value);
+ return TRUE;
+ }
if (g_strcmp0 (key, FU_QUIRKS_VENDOR) == 0) {
fu_device_set_vendor (self, value);
return TRUE;
}
if (g_strcmp0 (key, FU_QUIRKS_VENDOR_ID) == 0) {
- fu_device_set_vendor_id (self, value);
+ fu_device_add_vendor_id (self, value);
return TRUE;
}
if (g_strcmp0 (key, FU_QUIRKS_PROTOCOL) == 0) {
- fu_device_set_protocol (self, value);
+ g_auto(GStrv) sections = g_strsplit (value, ",", -1);
+ for (guint i = 0; sections[i] != NULL; i++)
+ fu_device_add_protocol (self, sections[i]);
return TRUE;
}
if (g_strcmp0 (key, FU_QUIRKS_VERSION) == 0) {
@@ -1062,6 +1241,7 @@
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"device GType %s not supported", value);
+ return FALSE;
}
return TRUE;
}
@@ -1265,6 +1445,7 @@
const gchar *instance_id,
FuDeviceInstanceFlags flags)
{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
g_autofree gchar *guid = NULL;
if (fwupd_guid_is_valid (instance_id)) {
g_warning ("use fu_device_add_guid(\"%s\") instead!", instance_id);
@@ -1280,6 +1461,10 @@
fu_device_add_guid_quirks (self, guid);
if ((flags & FU_DEVICE_INSTANCE_FLAG_ONLY_QUIRKS) == 0)
fwupd_device_add_instance_id (FWUPD_DEVICE (self), instance_id);
+
+ /* already done by ->setup(), so this must be ->registered() */
+ if (priv->done_setup)
+ fwupd_device_add_guid (FWUPD_DEVICE (self), guid);
}
/**
@@ -1398,6 +1583,8 @@
g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (locker != NULL, NULL);
+ if (priv->metadata == NULL)
+ return NULL;
return g_hash_table_lookup (priv->metadata, key);
}
@@ -1423,6 +1610,8 @@
g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (locker != NULL, FALSE);
+ if (priv->metadata == NULL)
+ return FALSE;
tmp = g_hash_table_lookup (priv->metadata, key);
if (tmp == NULL)
return FALSE;
@@ -1453,6 +1642,8 @@
g_return_val_if_fail (key != NULL, G_MAXUINT);
g_return_val_if_fail (locker != NULL, G_MAXUINT);
+ if (priv->metadata == NULL)
+ return G_MAXUINT;
tmp = g_hash_table_lookup (priv->metadata, key);
if (tmp == NULL)
return G_MAXUINT;
@@ -1481,6 +1672,8 @@
g_return_if_fail (FU_IS_DEVICE (self));
g_return_if_fail (key != NULL);
g_return_if_fail (locker != NULL);
+ if (priv->metadata == NULL)
+ return;
g_hash_table_remove (priv->metadata, key);
}
@@ -1503,6 +1696,10 @@
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
g_return_if_fail (locker != 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));
}
@@ -1606,6 +1803,7 @@
fu_device_set_id (FuDevice *self, const gchar *id)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
+ GPtrArray *children;
g_autofree gchar *id_hash = NULL;
g_return_if_fail (FU_IS_DEVICE (self));
@@ -1622,8 +1820,9 @@
priv->device_id_valid = TRUE;
/* ensure the parent ID is set */
- for (guint i = 0; i < priv->children->len; i++) {
- FuDevice *devtmp = g_ptr_array_index (priv->children, i);
+ children = fu_device_get_children (self);
+ for (guint i = 0; i < children->len; i++) {
+ FuDevice *devtmp = g_ptr_array_index (children, i);
fwupd_device_set_parent_id (FWUPD_DEVICE (devtmp), id_hash);
}
}
@@ -1670,7 +1869,7 @@
g_return_if_fail (FU_IS_DEVICE (self));
/* sanitize if required */
- if (fu_device_has_flag (self, FWUPD_DEVICE_FLAG_ENSURE_SEMVER)) {
+ if (fu_device_has_internal_flag (self, FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER)) {
version_safe = fu_common_version_ensure_semver (version);
if (g_strcmp0 (version, version_safe) != 0)
g_debug ("converted '%s' to '%s'", version, version_safe);
@@ -1679,7 +1878,8 @@
}
/* print a console warning for an invalid version, if semver */
- if (!fu_common_version_verify_format (version_safe, fu_device_get_version_format (self), &error))
+ if (version_safe != NULL &&
+ !fu_common_version_verify_format (version_safe, fu_device_get_version_format (self), &error))
g_warning ("%s", error->message);
/* if different */
@@ -1712,7 +1912,7 @@
g_return_if_fail (FU_IS_DEVICE (self));
/* sanitize if required */
- if (fu_device_has_flag (self, FWUPD_DEVICE_FLAG_ENSURE_SEMVER)) {
+ if (fu_device_has_internal_flag (self, FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER)) {
version_safe = fu_common_version_ensure_semver (version);
if (g_strcmp0 (version, version_safe) != 0)
g_debug ("converted '%s' to '%s'", version, version_safe);
@@ -1721,7 +1921,8 @@
}
/* print a console warning for an invalid version, if semver */
- if (!fu_common_version_verify_format (version_safe, fu_device_get_version_format (self), &error))
+ if (version_safe != NULL &&
+ !fu_common_version_verify_format (version_safe, fu_device_get_version_format (self), &error))
g_warning ("%s", error->message);
/* if different */
@@ -1754,7 +1955,7 @@
g_return_if_fail (FU_IS_DEVICE (self));
/* sanitize if required */
- if (fu_device_has_flag (self, FWUPD_DEVICE_FLAG_ENSURE_SEMVER)) {
+ if (fu_device_has_internal_flag (self, FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER)) {
version_safe = fu_common_version_ensure_semver (version);
if (g_strcmp0 (version, version_safe) != 0)
g_debug ("converted '%s' to '%s'", version, version_safe);
@@ -1763,7 +1964,8 @@
}
/* print a console warning for an invalid version, if semver */
- if (!fu_common_version_verify_format (version_safe, fu_device_get_version_format (self), &error))
+ if (version_safe != NULL &&
+ !fu_common_version_verify_format (version_safe, fu_device_get_version_format (self), &error))
g_warning ("%s", error->message);
/* if different */
@@ -1856,6 +2058,11 @@
{
FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_DEVICE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->logical_id, logical_id) == 0)
+ return;
+
g_free (priv->logical_id);
priv->logical_id = g_strdup (logical_id);
priv->device_id_valid = FALSE;
@@ -1863,6 +2070,55 @@
}
/**
+ * fu_device_get_backend_id:
+ * @self: A #FuDevice
+ *
+ * Gets the ID set for the device as recognised by the backend. This is typically
+ * a Linux sysfs path or USB platform ID. If unset, it also falls back to the
+ * physical ID as this may be the same value.
+ *
+ * Returns: a string value, or %NULL if never set.
+ *
+ * Since: 1.5.8
+ **/
+const gchar *
+fu_device_get_backend_id (FuDevice *self)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
+ if (priv->backend_id != NULL)
+ return priv->backend_id;
+ return priv->physical_id;
+}
+
+/**
+ * fu_device_set_backend_id:
+ * @self: A #FuDevice
+ * @backend_id: a string, e.g. `dev2`
+ *
+ * Sets the backend ID on the device. This is designed to disambiguate devices
+ * with the same physical ID. This is typically a Linux sysfs path or USB
+ * platform ID.
+ *
+ * Since: 1.5.8
+ **/
+void
+fu_device_set_backend_id (FuDevice *self, const gchar *backend_id)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_DEVICE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->backend_id, backend_id) == 0)
+ return;
+
+ g_free (priv->backend_id);
+ priv->backend_id = g_strdup (backend_id);
+ priv->device_id_valid = FALSE;
+ g_object_notify (G_OBJECT (self), "backend-id");
+}
+
+/**
* fu_device_get_proxy_guid:
* @self: A #FuDevice
*
@@ -1895,6 +2151,11 @@
{
FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_DEVICE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->proxy_guid, proxy_guid) == 0)
+ return;
+
g_free (priv->proxy_guid);
priv->proxy_guid = g_strdup (proxy_guid);
}
@@ -1913,7 +2174,10 @@
fu_device_get_protocol (FuDevice *self)
{
g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return fwupd_device_get_protocol (FWUPD_DEVICE (self));
+#pragma GCC diagnostic pop
}
/**
@@ -1929,7 +2193,7 @@
fu_device_set_protocol (FuDevice *self, const gchar *protocol)
{
g_return_if_fail (FU_IS_DEVICE (self));
- fwupd_device_set_protocol (FWUPD_DEVICE (self), protocol);
+ fwupd_device_add_protocol (FWUPD_DEVICE (self), protocol);
}
/**
@@ -1954,6 +2218,11 @@
FuDevicePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_DEVICE (self));
g_return_if_fail (physical_id != NULL);
+
+ /* not changed */
+ if (g_strcmp0 (priv->physical_id, physical_id) == 0)
+ return;
+
g_free (priv->physical_id);
priv->physical_id = g_strdup (physical_id);
priv->device_id_valid = FALSE;
@@ -2009,27 +2278,39 @@
if (flag & FWUPD_DEVICE_FLAG_INSTALL_ALL_RELEASES)
flag |= FWUPD_DEVICE_FLAG_VERSION_CHECK_REQUIRED;
fwupd_device_add_flag (FWUPD_DEVICE (self), flag);
+
+ /* activatable devices shouldn't be allowed to update again until activated */
+ /* don't let devices be updated until activated */
+ if (flag & FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION) {
+ fwupd_device_remove_flag (FWUPD_DEVICE (self), FWUPD_DEVICE_FLAG_UPDATABLE);
+ fwupd_device_add_flag (FWUPD_DEVICE (self), FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN);
+ }
}
static void
fu_device_set_custom_flag (FuDevice *self, const gchar *hint)
{
FwupdDeviceFlags flag;
+ FuDeviceInternalFlags internal_flag;
/* is this a negated device flag */
if (g_str_has_prefix (hint, "~")) {
flag = fwupd_device_flag_from_string (hint + 1);
if (flag != FWUPD_DEVICE_FLAG_UNKNOWN)
fu_device_remove_flag (self, flag);
+ internal_flag = fu_device_internal_flag_from_string (hint + 1);
+ if (internal_flag != FU_DEVICE_INTERNAL_FLAG_UNKNOWN)
+ fu_device_remove_internal_flag (self, internal_flag);
return;
}
/* is this a known device flag */
flag = fwupd_device_flag_from_string (hint);
- if (flag != FWUPD_DEVICE_FLAG_UNKNOWN) {
+ if (flag != FWUPD_DEVICE_FLAG_UNKNOWN)
fu_device_add_flag (self, flag);
- return;
- }
+ internal_flag = fu_device_internal_flag_from_string (hint);
+ if (internal_flag != FU_DEVICE_INTERNAL_FLAG_UNKNOWN)
+ fu_device_remove_internal_flag (self, internal_flag);
}
/**
@@ -2239,6 +2520,72 @@
fu_device_set_progress (self, (guint) percentage);
}
+/**
+ * fu_device_sleep_with_progress:
+ * @self: A #FuDevice
+ * @delay_secs: the delay in seconds
+ *
+ * Sleeps, setting the device progress from 0..100% as time continues.
+ * The value is gven in whole seconds as it does not make sense to show the
+ * progressbar advancing so quickly for durations of less than one second.
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_device_sleep_with_progress (FuDevice *self, guint delay_secs)
+{
+ gulong delay_us_pc = (delay_secs * G_USEC_PER_SEC) / 100;
+
+ g_return_if_fail (FU_IS_DEVICE (self));
+ g_return_if_fail (delay_secs > 0);
+
+ fu_device_set_progress (self, 0);
+ for (guint i = 0; i < 100; i++) {
+ g_usleep (delay_us_pc);
+ fu_device_set_progress (self, i + 1);
+ }
+}
+
+/**
+ * fu_device_get_battery_level:
+ * @self: A #FuDevice
+ *
+ * Returns the battery level.
+ *
+ * Returns: value in percent
+ *
+ * Since: 1.5.8
+ **/
+guint
+fu_device_get_battery_level (FuDevice *self)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_DEVICE (self), 0);
+ return priv->battery_level;
+}
+
+/**
+ * fu_device_set_battery_level:
+ * @self: A #FuDevice
+ * @battery_level: the percentage value
+ *
+ * Sets the battery level, or 0 for invalid. Setting this allows fwupd to show
+ * a warning if the device change is too low to perform the update.
+ *
+ * Since: 1.5.8
+ **/
+void
+fu_device_set_battery_level (FuDevice *self, guint battery_level)
+{
+ FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_DEVICE (self));
+ g_return_if_fail (battery_level <= 100);
+ if (priv->battery_level == battery_level)
+ return;
+ priv->battery_level = battery_level;
+ g_object_notify (G_OBJECT (self), "battery-level");
+}
+
static void
fu_device_add_string (FuDevice *self, guint idt, GString *str)
{
@@ -2246,7 +2593,6 @@
FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
FuDevicePrivate *priv = GET_PRIVATE (self);
g_autofree gchar *tmp = NULL;
- g_autoptr(GList) keys = NULL;
g_autoptr(GRWLockReaderLocker) locker = g_rw_lock_reader_locker_new (&priv->metadata_mutex);
g_return_if_fail (locker != NULL);
@@ -2265,10 +2611,14 @@
fu_common_string_append_kv (str, idt + 1, "PhysicalId", priv->physical_id);
if (priv->logical_id != NULL)
fu_common_string_append_kv (str, idt + 1, "LogicalId", priv->logical_id);
+ if (priv->backend_id != NULL)
+ fu_common_string_append_kv (str, idt + 1, "BackendId", priv->backend_id);
if (priv->proxy != NULL)
fu_common_string_append_kv (str, idt + 1, "ProxyId", fu_device_get_id (priv->proxy));
if (priv->proxy_guid != NULL)
fu_common_string_append_kv (str, idt + 1, "ProxyGuid", priv->proxy_guid);
+ if (priv->battery_level != 0)
+ fu_common_string_append_ku (str, idt + 1, "BatteryLevel", priv->battery_level);
if (priv->size_min > 0) {
g_autofree gchar *sz = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->size_min);
fu_common_string_append_kv (str, idt + 1, "FirmwareSizeMin", sz);
@@ -2277,15 +2627,33 @@
g_autofree gchar *sz = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->size_max);
fu_common_string_append_kv (str, idt + 1, "FirmwareSizeMax", sz);
}
- if (priv->order > 0)
+ if (priv->order != G_MAXINT)
fu_common_string_append_ku (str, idt + 1, "Order", priv->order);
if (priv->priority > 0)
fu_common_string_append_ku (str, idt + 1, "Priority", priv->priority);
- 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);
- fu_common_string_append_kv (str, idt + 1, key, value);
+ 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);
+ fu_common_string_append_kv (str, idt + 1, key, value);
+ }
+ }
+ for (guint i = 0; i < priv->possible_plugins->len; i++) {
+ const gchar *name = g_ptr_array_index (priv->possible_plugins, i);
+ fu_common_string_append_kv (str, idt + 1, "PossiblePlugin", name);
+ }
+ if (priv->internal_flags != FU_DEVICE_INTERNAL_FLAG_NONE) {
+ g_autoptr(GString) tmp2 = g_string_new ("");
+ for (guint i = 0; i < 64; i++) {
+ if ((priv->internal_flags & ((guint64) 1 << i)) == 0)
+ continue;
+ g_string_append_printf (tmp2, "%s|",
+ fu_device_internal_flag_to_string ((guint64) 1 << i));
+ }
+ if (tmp2->len > 0)
+ g_string_truncate (tmp2, tmp2->len - 1);
+ fu_common_string_append_kv (str, idt + 1, "InternalFlags", tmp2->str);
}
/* subclassed */
@@ -2294,11 +2662,9 @@
/* print children also */
children = fu_device_get_children (self);
- if (children != NULL) {
- for (guint i = 0; i < children->len; i++) {
- FuDevice *child = g_ptr_array_index (children, i);
- fu_device_add_string (child, idt + 1, str);
- }
+ for (guint i = 0; i < children->len; i++) {
+ FuDevice *child = g_ptr_array_index (children, i);
+ fu_device_add_string (child, idt + 1, str);
}
}
@@ -2463,6 +2829,7 @@
/* optionally subclassed */
if (klass->prepare_firmware != NULL) {
+ fu_device_set_status (self, FWUPD_STATUS_DECOMPRESSING);
firmware = klass->prepare_firmware (self, fw, flags, error);
if (firmware == NULL)
return NULL;
@@ -2506,6 +2873,11 @@
* @error: A #GError
*
* Reads firmware from the device by calling a plugin-specific vfunc.
+ * The device subclass should try to ensure the firmware does not contain any
+ * serial numbers or user-configuration values and can be used to calculate the
+ * device checksum.
+ *
+ * The return value can be converted to a blob of memory using fu_firmware_write().
*
* Returns: (transfer full): A #FuFirmware, or %NULL for error
*
@@ -2515,14 +2887,13 @@
fu_device_read_firmware (FuDevice *self, GError **error)
{
FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+ g_autoptr(GBytes) fw = NULL;
g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* no plugin-specific method or device doesn't support */
- if (!fu_device_has_flag (self, FWUPD_DEVICE_FLAG_CAN_VERIFY_IMAGE) ||
- klass->read_firmware == NULL) {
+ /* device does not support reading for verification CRCs */
+ if (!fu_device_has_flag (self, FWUPD_DEVICE_FLAG_CAN_VERIFY_IMAGE)) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
@@ -2531,7 +2902,49 @@
}
/* call vfunc */
- return klass->read_firmware (self, error);
+ if (klass->read_firmware != NULL)
+ return klass->read_firmware (self, error);
+
+ /* use the default FuFirmware when only ->dump_firmware is provided */
+ fw = fu_device_dump_firmware (self, error);
+ if (fw == NULL)
+ return NULL;
+ return fu_firmware_new_from_bytes (fw);
+}
+
+/**
+ * fu_device_dump_firmware:
+ * @self: A #FuDevice
+ * @error: A #GError
+ *
+ * Reads the raw firmware image from the device by calling a plugin-specific
+ * vfunc. This raw firmware image may contain serial numbers or device-specific
+ * configuration but should be a byte-for-byte match compared to using an
+ * external SPI programmer.
+ *
+ * Returns: (transfer full): A #GBytes, or %NULL for error
+ *
+ * Since: 1.5.0
+ **/
+GBytes *
+fu_device_dump_firmware (FuDevice *self, GError **error)
+{
+ FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+
+ g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* use the default FuFirmware when only ->dump_firmware is provided */
+ if (klass->dump_firmware == NULL) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "not supported");
+ return NULL;
+ }
+
+ /* proxy */
+ return klass->dump_firmware (self, error);
}
/**
@@ -2673,6 +3086,13 @@
return klass->cleanup (self, flags, error);
}
+static gboolean
+fu_device_open_cb (FuDevice *self, gpointer user_data, GError **error)
+{
+ FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+ return klass->open (self, error);
+}
+
/**
* fu_device_open:
* @self: A #FuDevice
@@ -2714,8 +3134,16 @@
/* subclassed */
if (klass->open != NULL) {
- if (!klass->open (self, error))
- return FALSE;
+ if (fu_device_has_internal_flag (self, FU_DEVICE_INTERNAL_FLAG_RETRY_OPEN)) {
+ if (!fu_device_retry_full (self, fu_device_open_cb,
+ FU_DEVICE_RETRY_OPEN_COUNT,
+ FU_DEVICE_RETRY_OPEN_DELAY,
+ NULL, error))
+ return FALSE;
+ } else {
+ if (!klass->open (self, error))
+ return FALSE;
+ }
}
/* setup */
@@ -2855,7 +3283,7 @@
* @self: A #FuDevice
*
* Converts all the Device Instance IDs added using fu_device_add_instance_id()
- * into actual GUIDs, **unless** %FWUPD_DEVICE_FLAG_NO_AUTO_INSTANCE_IDS has
+ * into actual GUIDs, **unless** %FU_DEVICE_INTERNAL_FLAG_NO_AUTO_INSTANCE_IDS has
* been set.
*
* Plugins will only need to need to call this manually when adding child
@@ -2867,23 +3295,17 @@
void
fu_device_convert_instance_ids (FuDevice *self)
{
- FuDevicePrivate *priv = GET_PRIVATE (self);
- GPtrArray *instance_ids = fwupd_device_get_instance_ids (FWUPD_DEVICE (self));
+ GPtrArray *instance_ids;
/* OEM specific hardware */
- if (fu_device_has_flag (self, FWUPD_DEVICE_FLAG_NO_AUTO_INSTANCE_IDS))
+ if (fu_device_has_internal_flag (self, FU_DEVICE_INTERNAL_FLAG_NO_AUTO_INSTANCE_IDS))
return;
+ instance_ids = fwupd_device_get_instance_ids (FWUPD_DEVICE (self));
for (guint i = 0; i < instance_ids->len; i++) {
const gchar *instance_id = g_ptr_array_index (instance_ids, i);
g_autofree gchar *guid = fwupd_guid_hash_string (instance_id);
fwupd_device_add_guid (FWUPD_DEVICE (self), guid);
}
-
- /* convert all children too */
- for (guint i = 0; i < priv->children->len; i++) {
- FuDevice *devtmp = g_ptr_array_index (priv->children, i);
- fu_device_convert_instance_ids (devtmp);
- }
}
/**
@@ -2904,6 +3326,7 @@
{
FuDevicePrivate *priv = GET_PRIVATE (self);
FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+ GPtrArray *children;
g_return_val_if_fail (FU_IS_DEVICE (self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -2918,6 +3341,14 @@
return FALSE;
}
+ /* run setup on the children too (unless done already) */
+ children = fu_device_get_children (self);
+ for (guint i = 0; i < children->len; i++) {
+ FuDevice *child_tmp = g_ptr_array_index (children, i);
+ if (!fu_device_setup (child_tmp, error))
+ return FALSE;
+ }
+
/* convert the instance IDs to GUIDs */
fu_device_convert_instance_ids (self);
@@ -2977,6 +3408,138 @@
}
/**
+ * fu_device_report_metadata_pre:
+ * @self: A #FuDevice
+ *
+ * Collects metadata that would be useful for debugging a failed update report.
+ *
+ * Returns: (transfer full) (nullable): A #GHashTable, or %NULL if there is no data
+ *
+ * Since: 1.5.0
+ **/
+GHashTable *
+fu_device_report_metadata_pre (FuDevice *self)
+{
+ FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+ g_autoptr(GHashTable) metadata = NULL;
+
+ g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
+
+ /* not implemented */
+ if (klass->report_metadata_pre == NULL)
+ return NULL;
+
+ /* metadata for all devices */
+ metadata = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ klass->report_metadata_pre (self, metadata);
+ return g_steal_pointer (&metadata);
+}
+
+/**
+ * fu_device_report_metadata_post:
+ * @self: A #FuDevice
+ *
+ * Collects metadata that would be useful for debugging a failed update report.
+ *
+ * Returns: (transfer full) (nullable): A #GHashTable, or %NULL if there is no data
+ *
+ * Since: 1.5.0
+ **/
+GHashTable *
+fu_device_report_metadata_post (FuDevice *self)
+{
+ FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+ g_autoptr(GHashTable) metadata = NULL;
+
+ g_return_val_if_fail (FU_IS_DEVICE (self), NULL);
+
+ /* not implemented */
+ if (klass->report_metadata_post == NULL)
+ return NULL;
+
+ /* metadata for all devices */
+ metadata = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ klass->report_metadata_post (self, metadata);
+ return g_steal_pointer (&metadata);
+}
+
+/**
+ * fu_device_bind_driver:
+ * @self: A #FuDevice
+ * @subsystem: A subsystem string, e.g. `pci`
+ * @driver: A kernel module name, e.g. `tg3`
+ * @error: A #GError, or %NULL
+ *
+ * Binds a driver to the device, which normally means the kernel driver takes
+ * control of the hardware.
+ *
+ * Returns: %TRUE if driver was bound.
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_device_bind_driver (FuDevice *self,
+ const gchar *subsystem,
+ const gchar *driver,
+ GError **error)
+{
+ FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+
+ g_return_val_if_fail (FU_IS_DEVICE (self), FALSE);
+ g_return_val_if_fail (subsystem != NULL, FALSE);
+ g_return_val_if_fail (driver != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* not implemented */
+ if (klass->bind_driver == NULL) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "not supported");
+ return FALSE;
+ }
+
+ /* subclass */
+ return klass->bind_driver (self, subsystem, driver, error);
+}
+
+/**
+ * fu_device_unbind_driver:
+ * @self: A #FuDevice
+ * @error: A #GError, or %NULL
+ *
+ * Unbinds the driver from the device, which normally means the kernel releases
+ * the hardware so it can be used from userspace.
+ *
+ * If there is no driver bound then this function will return with success
+ * without actually doing anything.
+ *
+ * Returns: %TRUE if driver was unbound.
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_device_unbind_driver (FuDevice *self, GError **error)
+{
+ FuDeviceClass *klass = FU_DEVICE_GET_CLASS (self);
+
+ g_return_val_if_fail (FU_IS_DEVICE (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* not implemented */
+ if (klass->unbind_driver == NULL) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "not supported");
+ return FALSE;
+ }
+
+ /* subclass */
+ return klass->unbind_driver (self, error);
+}
+
+/**
* fu_device_incorporate:
* @self: A #FuDevice
* @donor: Another #FuDevice
@@ -2993,7 +3556,6 @@
FuDevicePrivate *priv_donor = GET_PRIVATE (donor);
GPtrArray *instance_ids = fu_device_get_instance_ids (donor);
GPtrArray *parent_guids = fu_device_get_parent_guids (donor);
- g_autoptr(GList) metadata_keys = NULL;
g_return_if_fail (FU_IS_DEVICE (self));
g_return_if_fail (FU_IS_DEVICE (donor));
@@ -3007,6 +3569,8 @@
fu_device_set_physical_id (self, priv_donor->physical_id);
if (priv->logical_id == NULL && priv_donor->logical_id != NULL)
fu_device_set_logical_id (self, priv_donor->logical_id);
+ if (priv->backend_id == NULL && priv_donor->backend_id != NULL)
+ fu_device_set_backend_id (self, priv_donor->backend_id);
if (priv->proxy == NULL && priv_donor->proxy != NULL)
fu_device_set_proxy (self, priv_donor->proxy);
if (priv->proxy_guid == NULL && priv_donor->proxy_guid != NULL)
@@ -3018,12 +3582,14 @@
fu_device_add_parent_guid (self, g_ptr_array_index (parent_guids, i));
g_rw_lock_reader_unlock (&priv_donor->parent_guids_mutex);
g_rw_lock_reader_lock (&priv_donor->metadata_mutex);
- metadata_keys = g_hash_table_get_keys (priv_donor->metadata);
- for (GList *l = metadata_keys; l != NULL; l = l->next) {
- const gchar *key = l->data;
- if (g_hash_table_lookup (priv->metadata, key) == NULL) {
- const gchar *value = g_hash_table_lookup (priv_donor->metadata, key);
- fu_device_set_metadata (self, key, value);
+ if (priv->metadata != NULL) {
+ g_autoptr(GList) keys = g_hash_table_get_keys (priv_donor->metadata);
+ for (GList *l = keys; l != NULL; l = l->next) {
+ const gchar *key = l->data;
+ if (g_hash_table_lookup (priv->metadata, key) == NULL) {
+ const gchar *value = g_hash_table_lookup (priv_donor->metadata, key);
+ fu_device_set_metadata (self, key, value);
+ }
}
}
g_rw_lock_reader_unlock (&priv_donor->metadata_mutex);
@@ -3111,25 +3677,29 @@
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_LOGICAL_ID, pspec);
+ pspec = g_param_spec_string ("backend-id", NULL, NULL, NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME);
+ g_object_class_install_property (object_class, PROP_BACKEND_ID, pspec);
+
pspec = g_param_spec_uint ("progress", NULL, NULL,
0, 100, 0,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_PROGRESS, pspec);
+ pspec = g_param_spec_uint ("battery-level", NULL, NULL,
+ 0, 100, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME);
+ g_object_class_install_property (object_class, PROP_BATTERY_LEVEL, pspec);
+
pspec = g_param_spec_object ("quirks", NULL, NULL,
FU_TYPE_QUIRKS,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME);
g_object_class_install_property (object_class, PROP_QUIRKS, pspec);
- pspec = g_param_spec_object ("parent", NULL, NULL,
- FU_TYPE_DEVICE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_NAME);
- g_object_class_install_property (object_class, PROP_PARENT, pspec);
-
pspec = g_param_spec_object ("proxy", NULL, NULL,
FU_TYPE_DEVICE,
G_PARAM_READWRITE |
@@ -3142,13 +3712,11 @@
fu_device_init (FuDevice *self)
{
FuDevicePrivate *priv = GET_PRIVATE (self);
- priv->children = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+ priv->order = G_MAXINT;
priv->parent_guids = g_ptr_array_new_with_free_func (g_free);
priv->possible_plugins = g_ptr_array_new_with_free_func (g_free);
priv->retry_recs = g_ptr_array_new_with_free_func (g_free);
g_rw_lock_init (&priv->parent_guids_mutex);
- priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
g_rw_lock_init (&priv->metadata_mutex);
}
@@ -3158,20 +3726,19 @@
FuDevice *self = FU_DEVICE (object);
FuDevicePrivate *priv = GET_PRIVATE (self);
+ g_rw_lock_clear (&priv->metadata_mutex);
+ g_rw_lock_clear (&priv->parent_guids_mutex);
+
if (priv->alternate != NULL)
g_object_unref (priv->alternate);
- if (priv->parent != NULL)
- g_object_remove_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
if (priv->proxy != NULL)
g_object_remove_weak_pointer (G_OBJECT (priv->proxy), (gpointer *) &priv->proxy);
if (priv->quirks != NULL)
g_object_unref (priv->quirks);
if (priv->poll_id != 0)
g_source_remove (priv->poll_id);
- g_rw_lock_clear (&priv->metadata_mutex);
- g_rw_lock_clear (&priv->parent_guids_mutex);
- g_hash_table_unref (priv->metadata);
- g_ptr_array_unref (priv->children);
+ if (priv->metadata != NULL)
+ g_hash_table_unref (priv->metadata);
g_ptr_array_unref (priv->parent_guids);
g_ptr_array_unref (priv->possible_plugins);
g_ptr_array_unref (priv->retry_recs);
@@ -3179,6 +3746,7 @@
g_free (priv->equivalent_id);
g_free (priv->physical_id);
g_free (priv->logical_id);
+ g_free (priv->backend_id);
g_free (priv->proxy_guid);
G_OBJECT_CLASS (fu_device_parent_class)->finalize (object);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-device.h fwupd-1.5.8/libfwupdplugin/fu-device.h
--- fwupd-1.4.5/libfwupdplugin/fu-device.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-device.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -25,47 +25,78 @@
gboolean (*write_firmware) (FuDevice *self,
FuFirmware *firmware,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FuFirmware *(*read_firmware) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*detach) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*attach) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*open) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*close) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*probe) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*rescan) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FuFirmware *(*prepare_firmware) (FuDevice *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*set_quirk_kv) (FuDevice *self,
const gchar *key,
const gchar *value,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*setup) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void (*incorporate) (FuDevice *self,
FuDevice *donor);
gboolean (*poll) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*activate) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*reload) (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*prepare) (FuDevice *self,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean (*cleanup) (FuDevice *self,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+ void (*report_metadata_pre) (FuDevice *self,
+ GHashTable *metadata);
+ void (*report_metadata_post)(FuDevice *self,
+ GHashTable *metadata);
+ gboolean (*bind_driver) (FuDevice *self,
+ const gchar *subsystem,
+ const gchar *driver,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+ gboolean (*unbind_driver) (FuDevice *self,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+ GBytes *(*dump_firmware) (FuDevice *self,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
/*< private >*/
- gpointer padding[16];
+ gpointer padding[11];
};
/**
@@ -102,7 +133,8 @@
typedef gboolean (*FuDeviceRetryFunc) (FuDevice *device,
gpointer user_data,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FuDevice *fu_device_new (void);
@@ -110,6 +142,8 @@
#define fu_device_remove_flag(d,v) fwupd_device_remove_flag(FWUPD_DEVICE(d),v)
#define fu_device_has_flag(d,v) fwupd_device_has_flag(FWUPD_DEVICE(d),v)
#define fu_device_has_instance_id(d,v) fwupd_device_has_instance_id(FWUPD_DEVICE(d),v)
+#define fu_device_has_vendor_id(d,v) fwupd_device_has_vendor_id(FWUPD_DEVICE(d),v)
+#define fu_device_has_protocol(d,v) fwupd_device_has_protocol(FWUPD_DEVICE(d),v)
#define fu_device_add_checksum(d,v) fwupd_device_add_checksum(FWUPD_DEVICE(d),v)
#define fu_device_add_release(d,v) fwupd_device_add_release(FWUPD_DEVICE(d),v)
#define fu_device_add_icon(d,v) fwupd_device_add_icon(FWUPD_DEVICE(d),v)
@@ -120,12 +154,14 @@
#define fu_device_set_plugin(d,v) fwupd_device_set_plugin(FWUPD_DEVICE(d),v)
#define fu_device_set_serial(d,v) fwupd_device_set_serial(FWUPD_DEVICE(d),v)
#define fu_device_set_summary(d,v) fwupd_device_set_summary(FWUPD_DEVICE(d),v)
+#define fu_device_set_branch(d,v) fwupd_device_set_branch(FWUPD_DEVICE(d),v)
#define fu_device_set_update_message(d,v) fwupd_device_set_update_message(FWUPD_DEVICE(d),v)
#define fu_device_set_update_image(d,v) fwupd_device_set_update_image(FWUPD_DEVICE(d),v)
#define fu_device_set_update_error(d,v) fwupd_device_set_update_error(FWUPD_DEVICE(d),v)
#define fu_device_set_update_state(d,v) fwupd_device_set_update_state(FWUPD_DEVICE(d),v)
#define fu_device_set_vendor(d,v) fwupd_device_set_vendor(FWUPD_DEVICE(d),v)
-#define fu_device_set_vendor_id(d,v) fwupd_device_set_vendor_id(FWUPD_DEVICE(d),v)
+#define fu_device_add_vendor_id(d,v) fwupd_device_add_vendor_id(FWUPD_DEVICE(d),v)
+#define fu_device_add_protocol(d,v) fwupd_device_add_protocol(FWUPD_DEVICE(d),v)
#define fu_device_set_version_raw(d,v) fwupd_device_set_version_raw(FWUPD_DEVICE(d),v)
#define fu_device_set_version_lowest_raw(d,v) fwupd_device_set_version_lowest_raw(FWUPD_DEVICE(d),v)
#define fu_device_set_version_bootloader_raw(d,v) fwupd_device_set_version_bootloader_raw(FWUPD_DEVICE(d),v)
@@ -142,6 +178,7 @@
#define fu_device_get_name(d) fwupd_device_get_name(FWUPD_DEVICE(d))
#define fu_device_get_serial(d) fwupd_device_get_serial(FWUPD_DEVICE(d))
#define fu_device_get_summary(d) fwupd_device_get_summary(FWUPD_DEVICE(d))
+#define fu_device_get_branch(d) fwupd_device_get_branch(FWUPD_DEVICE(d))
#define fu_device_get_id(d) fwupd_device_get_id(FWUPD_DEVICE(d))
#define fu_device_get_plugin(d) fwupd_device_get_plugin(FWUPD_DEVICE(d))
#define fu_device_get_update_error(d) fwupd_device_get_update_error(FWUPD_DEVICE(d))
@@ -154,10 +191,41 @@
#define fu_device_get_version_raw(d) fwupd_device_get_version_raw(FWUPD_DEVICE(d))
#define fu_device_get_version_lowest_raw(d) fwupd_device_get_version_lowest_raw(FWUPD_DEVICE(d))
#define fu_device_get_version_bootloader_raw(d) fwupd_device_get_version_bootloader_raw(FWUPD_DEVICE(d))
-#define fu_device_get_vendor_id(d) fwupd_device_get_vendor_id(FWUPD_DEVICE(d))
+#define fu_device_get_vendor_ids(d) fwupd_device_get_vendor_ids(FWUPD_DEVICE(d))
+#define fu_device_get_protocols(d) fwupd_device_get_protocols(FWUPD_DEVICE(d))
#define fu_device_get_flashes_left(d) fwupd_device_get_flashes_left(FWUPD_DEVICE(d))
#define fu_device_get_install_duration(d) fwupd_device_get_install_duration(FWUPD_DEVICE(d))
+/**
+ * FuDeviceInternalFlags:
+ * @FU_DEVICE_INTERNAL_FLAG_NONE: No flags set
+ * @FU_DEVICE_INTERNAL_FLAG_NO_AUTO_INSTANCE_IDS: Do not add instance IDs from the device baseclass
+ * @FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER: Ensure the version is a valid semantic version, e.g. numbers separated with dots
+ * @FU_DEVICE_INTERNAL_FLAG_ONLY_SUPPORTED: Only devices supported in the metadata will be opened
+ * @FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME: Set the device name from the metadata `name` if available
+ * @FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME_CATEGORY: Set the device name from the metadata `category` if available
+ * @FU_DEVICE_INTERNAL_FLAG_MD_SET_VERFMT: Set the device version format from the metadata if available
+ * @FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON: Set the device icon from the metadata if available
+ * @FU_DEVICE_INTERNAL_FLAG_RETRY_OPEN: Retry the device open up to 5 times if it fails
+ * @FU_DEVICE_INTERNAL_FLAG_REPLUG_MATCH_GUID: Match GUIDs on device replug where the physical and logical IDs will be different
+ *
+ * The device internal flags.
+ **/
+typedef enum {
+ FU_DEVICE_INTERNAL_FLAG_NONE = 0,
+ FU_DEVICE_INTERNAL_FLAG_NO_AUTO_INSTANCE_IDS = (1llu << 0), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER = (1llu << 1), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_ONLY_SUPPORTED = (1llu << 2), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME = (1llu << 3), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_MD_SET_NAME_CATEGORY = (1llu << 4), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_MD_SET_VERFMT = (1llu << 5), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_MD_SET_ICON = (1llu << 6), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_RETRY_OPEN = (1llu << 7), /* Since: 1.5.5 */
+ FU_DEVICE_INTERNAL_FLAG_REPLUG_MATCH_GUID = (1llu << 8), /* Since: 1.5.8 */
+ /*< private >*/
+ FU_DEVICE_INTERNAL_FLAG_UNKNOWN = G_MAXUINT64,
+} FuDeviceInternalFlags;
+
/* accessors */
gchar *fu_device_to_string (FuDevice *self);
const gchar *fu_device_get_alternate_id (FuDevice *self);
@@ -221,10 +289,15 @@
const gchar *fu_device_get_logical_id (FuDevice *self);
void fu_device_set_logical_id (FuDevice *self,
const gchar *logical_id);
+const gchar *fu_device_get_backend_id (FuDevice *self);
+void fu_device_set_backend_id (FuDevice *self,
+ const gchar *backend_id);
const gchar *fu_device_get_proxy_guid (FuDevice *self);
void fu_device_set_proxy_guid (FuDevice *self,
const gchar *proxy_guid);
+G_DEPRECATED_FOR(fu_device_get_protocols)
const gchar *fu_device_get_protocol (FuDevice *self);
+G_DEPRECATED_FOR(fu_device_add_protocol)
void fu_device_set_protocol (FuDevice *self,
const gchar *protocol);
guint fu_device_get_priority (FuDevice *self);
@@ -256,55 +329,85 @@
guint fu_device_get_progress (FuDevice *self);
void fu_device_set_progress (FuDevice *self,
guint progress);
+guint fu_device_get_battery_level (FuDevice *self);
+void fu_device_set_battery_level (FuDevice *self,
+ guint battery_level);
void fu_device_set_progress_full (FuDevice *self,
gsize progress_done,
gsize progress_total);
+void fu_device_sleep_with_progress (FuDevice *self,
+ guint delay_secs);
void fu_device_set_quirks (FuDevice *self,
FuQuirks *quirks);
FuQuirks *fu_device_get_quirks (FuDevice *self);
FwupdRelease *fu_device_get_release_default (FuDevice *self);
+GType fu_device_get_specialized_gtype (FuDevice *self);
+void fu_device_add_internal_flag (FuDevice *self,
+ FuDeviceInternalFlags flag);
+void fu_device_remove_internal_flag (FuDevice *self,
+ FuDeviceInternalFlags flag);
+gboolean fu_device_has_internal_flag (FuDevice *self,
+ FuDeviceInternalFlags flag);
gboolean fu_device_write_firmware (FuDevice *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FuFirmware *fu_device_prepare_firmware (FuDevice *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FuFirmware *fu_device_read_firmware (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GBytes *fu_device_dump_firmware (FuDevice *self,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_attach (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_detach (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_reload (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_prepare (FuDevice *self,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_cleanup (FuDevice *self,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void fu_device_incorporate (FuDevice *self,
FuDevice *donor);
void fu_device_incorporate_flag (FuDevice *self,
FuDevice *donor,
FwupdDeviceFlags flag);
gboolean fu_device_open (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_close (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_probe (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_setup (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_rescan (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_activate (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void fu_device_probe_invalidate (FuDevice *self);
gboolean fu_device_poll (FuDevice *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void fu_device_set_poll_interval (FuDevice *self,
guint interval);
void fu_device_retry_set_delay (FuDevice *self,
@@ -317,4 +420,22 @@
FuDeviceRetryFunc func,
guint count,
gpointer user_data,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_device_retry_full (FuDevice *self,
+ FuDeviceRetryFunc func,
+ guint count,
+ guint delay,
+ gpointer user_data,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_device_bind_driver (FuDevice *self,
+ const gchar *subsystem,
+ const gchar *driver,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_device_unbind_driver (FuDevice *self,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GHashTable *fu_device_report_metadata_pre (FuDevice *self);
+GHashTable *fu_device_report_metadata_post (FuDevice *self);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-device-locker.c fwupd-1.5.8/libfwupdplugin/fu-device-locker.c
--- fwupd-1.4.5/libfwupdplugin/fu-device-locker.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-device-locker.c 2021-03-31 20:08:32.000000000 +0000
@@ -9,7 +9,9 @@
#include "config.h"
#include
+#ifdef HAVE_GUSB
#include
+#endif
#include "fu-device-locker.h"
#include "fu-usb-device.h"
@@ -46,8 +48,8 @@
if (!self->close_func (self->device, &error))
g_warning ("failed to close device: %s", error->message);
}
-
- g_object_unref (self->device);
+ if (self->device != NULL)
+ g_object_unref (self->device);
G_OBJECT_CLASS (fu_device_locker_parent_class)->finalize (obj);
}
@@ -80,12 +82,28 @@
gboolean
fu_device_locker_close (FuDeviceLocker *self, GError **error)
{
+ g_autoptr(GError) error_local = NULL;
g_return_val_if_fail (FU_IS_DEVICE_LOCKER (self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!self->device_open)
return TRUE;
- if (!self->close_func (self->device, error))
+ if (!self->close_func (self->device, &error_local)) {
+#ifdef HAVE_GUSB
+ if (G_USB_IS_DEVICE (self->device) &&
+ g_error_matches (error_local,
+ G_USB_DEVICE_ERROR,
+ G_USB_DEVICE_ERROR_NO_DEVICE)) {
+ g_debug ("ignoring: %s", error_local->message);
+ return TRUE;
+ } else {
+ g_propagate_error (error, g_steal_pointer (&error_local));
+ return FALSE;
+ }
+#else
+ g_propagate_error (error, g_steal_pointer (&error_local));
return FALSE;
+#endif
+ }
self->device_open = FALSE;
return TRUE;
}
@@ -120,6 +138,7 @@
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (error != NULL, NULL);
+#ifdef HAVE_GUSB
/* GUsbDevice */
if (G_USB_IS_DEVICE (device)) {
return fu_device_locker_new_full (device,
@@ -127,6 +146,7 @@
(FuDeviceLockerFunc) g_usb_device_close,
error);
}
+#endif
/* FuDevice */
if (FU_IS_DEVICE (device)) {
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-device-locker.h fwupd-1.5.8/libfwupdplugin/fu-device-locker.h
--- fwupd-1.4.5/libfwupdplugin/fu-device-locker.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-device-locker.h 2021-03-31 20:08:32.000000000 +0000
@@ -16,10 +16,13 @@
GError **error);
FuDeviceLocker *fu_device_locker_new (gpointer device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
FuDeviceLocker *fu_device_locker_new_full (gpointer device,
FuDeviceLockerFunc open_func,
FuDeviceLockerFunc close_func,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_device_locker_close (FuDeviceLocker *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-device-private.h fwupd-1.5.8/libfwupdplugin/fu-device-private.h
--- fwupd-1.4.5/libfwupdplugin/fu-device-private.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-device-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -11,21 +11,26 @@
#define fu_device_set_plugin(d,v) fwupd_device_set_plugin(FWUPD_DEVICE(d),v)
+const gchar *fu_device_internal_flag_to_string (FuDeviceInternalFlags flag);
+FuDeviceInternalFlags fu_device_internal_flag_from_string (const gchar *flag);
+
GPtrArray *fu_device_get_parent_guids (FuDevice *self);
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);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void fu_device_incorporate_from_component (FuDevice *device,
XbNode *component);
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);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-dfu-firmware.c fwupd-1.5.8/libfwupdplugin/fu-dfu-firmware.c
--- fwupd-1.4.5/libfwupdplugin/fu-dfu-firmware.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-dfu-firmware.c 2021-03-31 20:08:32.000000000 +0000
@@ -8,8 +8,10 @@
#include "config.h"
+#include
+
#include "fu-common.h"
-#include "fu-dfu-firmware.h"
+#include "fu-dfu-firmware-private.h"
/**
* SECTION:fu-dfu-firmware
@@ -25,6 +27,7 @@
guint16 pid;
guint16 release;
guint16 version;
+ guint8 footer_len;
} FuDfuFirmwarePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FuDfuFirmware, fu_dfu_firmware, FU_TYPE_FIRMWARE)
@@ -41,6 +44,15 @@
fu_common_string_append_kx (str, idt, "Version", priv->version);
}
+/* private */
+guint8
+fu_dfu_firmware_get_footer_len (FuDfuFirmware *self)
+{
+ FuDfuFirmwarePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_DFU_FIRMWARE (self), 0x0);
+ return priv->footer_len;
+}
+
/**
* fu_dfu_firmware_get_vid:
* @self: a #FuDfuFirmware
@@ -181,60 +193,6 @@
priv->version = version;
}
-static guint32 _crctbl[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
-
-static guint32
-fu_dfu_firmware_generate_crc32 (const guint8 *data, gsize length)
-{
- guint32 accum = 0xffffffff;
- for (guint i = 0; i < length; i++)
- accum = _crctbl[(accum^data[i]) & 0xff] ^ (accum >> 8);
- return accum;
-}
-
typedef struct __attribute__((packed)) {
guint16 release;
guint16 pid;
@@ -245,23 +203,18 @@
guint32 crc;
} FuDfuFirmwareFooter;
-static gboolean
-fu_dfu_firmware_parse (FuFirmware *firmware,
- GBytes *fw,
- guint64 addr_start,
- guint64 addr_end,
- FwupdInstallFlags flags,
- GError **error)
+gboolean
+fu_dfu_firmware_parse_footer (FuDfuFirmware *self,
+ GBytes *fw,
+ FwupdInstallFlags flags,
+ GError **error)
{
- FuDfuFirmware *self = FU_DFU_FIRMWARE (firmware);
FuDfuFirmwarePrivate *priv = GET_PRIVATE (self);
FuDfuFirmwareFooter ftr;
gsize len;
guint32 crc;
guint32 crc_new;
guint8 *data;
- g_autoptr(FuFirmwareImage) image = NULL;
- g_autoptr(GBytes) contents = NULL;
/* check data size */
data = (guint8 *) g_bytes_get_data (fw, &len);
@@ -289,8 +242,8 @@
sizeof(FuDfuFirmwareFooter), error))
return FALSE;
crc = GUINT32_FROM_LE(ftr.crc);
- if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
- crc_new = fu_dfu_firmware_generate_crc32 (data, len - 4);
+ if ((flags & FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM) == 0) {
+ crc_new = ~fu_common_crc32 (data, len - 4);
if (crc != crc_new) {
g_set_error (error,
FWUPD_ERROR,
@@ -306,26 +259,51 @@
priv->pid = GUINT16_FROM_LE(ftr.pid);
priv->release = GUINT16_FROM_LE(ftr.release);
priv->version = GUINT16_FROM_LE(ftr.ver);
+ priv->footer_len = ftr.len;
/* check reported length */
- if (ftr.len > len) {
+ if (priv->footer_len > len) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
- "reported firmware size %04x larger than file %04x",
- (guint) ftr.len, (guint) len);
+ "reported footer size %04x larger than file %04x",
+ (guint) priv->footer_len, (guint) len);
return FALSE;
}
/* success */
- contents = g_bytes_new_from_bytes (fw, 0, len - ftr.len);
+ return TRUE;
+}
+
+static gboolean
+fu_dfu_firmware_parse (FuFirmware *firmware,
+ GBytes *fw,
+ guint64 addr_start,
+ guint64 addr_end,
+ FwupdInstallFlags flags,
+ GError **error)
+{
+ FuDfuFirmware *self = FU_DFU_FIRMWARE (firmware);
+ FuDfuFirmwarePrivate *priv = GET_PRIVATE (self);
+ gsize len = g_bytes_get_size (fw);
+ g_autoptr(FuFirmwareImage) image = NULL;
+ g_autoptr(GBytes) contents = NULL;
+
+ /* parse footer */
+ if (!fu_dfu_firmware_parse_footer (self, fw, flags, error))
+ return FALSE;
+
+ /* trim footer off */
+ contents = fu_common_bytes_new_offset (fw, 0, len - priv->footer_len, error);
+ if (contents == NULL)
+ return FALSE;
image = fu_firmware_image_new (contents);
fu_firmware_add_image (firmware, image);
return TRUE;
}
-static GBytes *
-fu_dfu_firmware_add_footer (FuDfuFirmware *self, GBytes *contents, GError **error)
+GBytes *
+fu_dfu_firmware_append_footer (FuDfuFirmware *self, GBytes *contents, GError **error)
{
FuDfuFirmwarePrivate *priv = GET_PRIVATE (self);
GByteArray *buf = g_byte_array_new ();
@@ -343,9 +321,7 @@
fu_byte_array_append_uint16 (buf, priv->version, G_LITTLE_ENDIAN);
g_byte_array_append (buf, (const guint8 *) "UFD", 3);
fu_byte_array_append_uint8 (buf, sizeof(FuDfuFirmwareFooter));
- fu_byte_array_append_uint32 (buf,
- fu_dfu_firmware_generate_crc32 (buf->data, buf->len),
- G_LITTLE_ENDIAN);
+ fu_byte_array_append_uint32 (buf, ~fu_common_crc32 (buf->data, buf->len), G_LITTLE_ENDIAN);
return g_byte_array_free_to_bytes (buf);
}
@@ -369,7 +345,29 @@
fw = fu_firmware_get_image_default_bytes (firmware, error);
if (fw == NULL)
return NULL;
- return fu_dfu_firmware_add_footer (self, fw, error);
+ return fu_dfu_firmware_append_footer (self, fw, error);
+}
+
+static gboolean
+fu_dfu_firmware_build (FuFirmware *firmware, XbNode *n, GError **error)
+{
+ FuDfuFirmware *self = FU_DFU_FIRMWARE (firmware);
+ FuDfuFirmwarePrivate *priv = GET_PRIVATE (self);
+ guint64 tmp;
+
+ /* optional properties */
+ tmp = xb_node_query_text_as_uint (n, "vendor", NULL);
+ if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT16)
+ priv->vid = tmp;
+ tmp = xb_node_query_text_as_uint (n, "product", NULL);
+ if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT16)
+ priv->pid = tmp;
+ tmp = xb_node_query_text_as_uint (n, "release", NULL);
+ if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT16)
+ priv->release = tmp;
+
+ /* success */
+ return TRUE;
}
static void
@@ -379,7 +377,9 @@
priv->vid = 0xffff;
priv->pid = 0xffff;
priv->release = 0xffff;
- priv->version = 0x0100;
+ priv->version = DFU_VERSION_DFU_1_0;
+ fu_firmware_add_flag (FU_FIRMWARE (self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
+ fu_firmware_add_flag (FU_FIRMWARE (self), FU_FIRMWARE_FLAG_HAS_VID_PID);
}
static void
@@ -389,6 +389,7 @@
klass_firmware->to_string = fu_dfu_firmware_to_string;
klass_firmware->parse = fu_dfu_firmware_parse;
klass_firmware->write = fu_dfu_firmware_write;
+ klass_firmware->build = fu_dfu_firmware_build;
}
/**
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-dfu-firmware-private.h fwupd-1.5.8/libfwupdplugin/fu-dfu-firmware-private.h
--- fwupd-1.4.5/libfwupdplugin/fu-dfu-firmware-private.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-dfu-firmware-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fu-dfu-firmware.h"
+
+/**
+ * DfuVersion:
+ * @DFU_VERSION_UNKNOWN: Format unknown
+ * @DFU_VERSION_DFU_1_0: DFU 1.0
+ * @DFU_VERSION_DFU_1_1: DFU 1.1
+ * @DFU_VERSION_DFUSE: DfuSe
+ * @DFU_VERSION_ATMEL_AVR: Atmel AVR
+ *
+ * The known versions of the DFU standard in BCD format.
+ **/
+typedef enum {
+ DFU_VERSION_UNKNOWN = 0,
+ DFU_VERSION_DFU_1_0 = 0x0100,
+ DFU_VERSION_DFU_1_1 = 0x0110,
+ DFU_VERSION_DFUSE = 0x011a, /* defined by ST */
+ DFU_VERSION_ATMEL_AVR = 0xff01, /* made up */
+ /*< private >*/
+ DFU_VERSION_LAST
+} DfuVersion;
+
+guint8 fu_dfu_firmware_get_footer_len (FuDfuFirmware *self);
+GBytes *fu_dfu_firmware_append_footer (FuDfuFirmware *self,
+ GBytes *contents,
+ GError **error);
+gboolean fu_dfu_firmware_parse_footer (FuDfuFirmware *self,
+ GBytes *fw,
+ FwupdInstallFlags flags,
+ GError **error);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-dfuse-firmware.c fwupd-1.5.8/libfwupdplugin/fu-dfuse-firmware.c
--- fwupd-1.4.5/libfwupdplugin/fu-dfuse-firmware.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-dfuse-firmware.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2015 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#define G_LOG_DOMAIN "FuFirmware"
+
+#include "config.h"
+
+#include
+
+#include "fu-chunk-private.h"
+#include "fu-common.h"
+#include "fu-dfu-firmware-private.h"
+#include "fu-dfuse-firmware.h"
+
+/**
+ * SECTION:fu-dfuse-firmware
+ * @short_description: DfuSe firmware image
+ *
+ * An object that represents a DfuSe firmware image.
+ *
+ * See also: #FuDfuFirmware
+ */
+
+G_DEFINE_TYPE (FuDfuseFirmware, fu_dfuse_firmware, FU_TYPE_DFU_FIRMWARE)
+
+/* firmware: LE */
+typedef struct __attribute__((packed)) {
+ guint8 sig[5];
+ guint8 ver;
+ guint32 image_size;
+ guint8 targets;
+} DfuSeHdr;
+
+/* image: LE */
+typedef struct __attribute__((packed)) {
+ guint8 sig[6];
+ guint8 alt_setting;
+ guint32 target_named;
+ gchar target_name[255];
+ guint32 target_size;
+ guint32 chunks;
+} DfuSeImageHdr;
+
+/* element: LE */
+typedef struct __attribute__((packed)) {
+ guint32 address;
+ guint32 size;
+} DfuSeElementHdr;
+
+G_STATIC_ASSERT(sizeof(DfuSeHdr) == 11);
+G_STATIC_ASSERT(sizeof(DfuSeImageHdr) == 274);
+G_STATIC_ASSERT(sizeof(DfuSeElementHdr) == 8);
+
+static FuChunk *
+fu_firmware_image_chunk_parse (FuDfuseFirmware *self,
+ GBytes *bytes,
+ gsize *offset,
+ GError **error)
+{
+ DfuSeElementHdr hdr = { 0x0 };
+ gsize bufsz = 0;
+ gsize ftrlen = fu_dfu_firmware_get_footer_len (FU_DFU_FIRMWARE (self));
+ const guint8 *buf = g_bytes_get_data (bytes, &bufsz);
+ g_autoptr(FuChunk) chk = NULL;
+ g_autoptr(GBytes) blob = NULL;
+
+ /* check size */
+ if (!fu_memcpy_safe ((guint8 *) &hdr, sizeof(hdr), 0x0, /* dst */
+ buf, bufsz - ftrlen, *offset, /* src */
+ sizeof(hdr), error))
+ return NULL;
+
+ /* create new chunk */
+ *offset += sizeof(hdr);
+ blob = fu_common_bytes_new_offset (bytes, *offset,
+ GUINT32_FROM_LE (hdr.size),
+ error);
+ if (blob == NULL)
+ return NULL;
+ chk = fu_chunk_bytes_new (blob);
+ fu_chunk_set_address (chk, GUINT32_FROM_LE (hdr.address));
+ *offset += fu_chunk_get_data_sz (chk);
+
+ /* success */
+ return g_steal_pointer (&chk);
+}
+
+static FuFirmwareImage *
+fu_dfuse_firmware_image_parse (FuDfuseFirmware *self,
+ GBytes *bytes,
+ gsize *offset,
+ GError **error)
+{
+ DfuSeImageHdr hdr = { 0x0 };
+ gsize bufsz = 0;
+ const guint8 *buf = g_bytes_get_data (bytes, &bufsz);
+ g_autoptr(FuFirmwareImage) image = fu_firmware_image_new (NULL);
+
+ /* verify image signature */
+ if (!fu_memcpy_safe ((guint8 *) &hdr, sizeof(hdr), 0x0, /* dst */
+ buf, bufsz, *offset, /* src */
+ sizeof(hdr), error))
+ return NULL;
+ if (memcmp (hdr.sig, "Target", sizeof(hdr.sig)) != 0) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "invalid DfuSe target signature");
+ return NULL;
+ }
+
+ /* set properties */
+ fu_firmware_image_set_idx (image, hdr.alt_setting);
+ if (GUINT32_FROM_LE (hdr.target_named) == 0x01) {
+ g_autofree gchar *img_id = NULL;
+ img_id = g_strndup (hdr.target_name, sizeof(hdr.target_name));
+ fu_firmware_image_set_id (image, img_id);
+ }
+
+ /* no chunks */
+ if (hdr.chunks == 0) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "DfuSe image has no chunks");
+ return NULL;
+ }
+
+ /* parse chunks */
+ *offset += sizeof(hdr);
+ for (guint j = 0; j < GUINT32_FROM_LE (hdr.chunks); j++) {
+ g_autoptr(FuChunk) chk = NULL;
+ chk = fu_firmware_image_chunk_parse (self,
+ bytes,
+ offset,
+ error);
+ if (chk == NULL)
+ return NULL;
+ fu_firmware_image_add_chunk (image, chk);
+ }
+
+ /* success */
+ return g_steal_pointer (&image);
+}
+
+static gboolean
+fu_dfuse_firmware_parse (FuFirmware *firmware,
+ GBytes *fw,
+ guint64 addr_start,
+ guint64 addr_end,
+ FwupdInstallFlags flags,
+ GError **error)
+{
+ FuDfuFirmware *dfu_firmware = FU_DFU_FIRMWARE (firmware);
+ DfuSeHdr hdr = { 0x0 };
+ gsize bufsz = 0;
+ gsize offset = 0;
+ const guint8 *buf;
+
+ /* DFU footer first */
+ if (!fu_dfu_firmware_parse_footer (dfu_firmware, fw, flags, error))
+ return FALSE;
+
+ /* check the prefix */
+ buf = (const guint8 *) g_bytes_get_data (fw, &bufsz);
+ if (!fu_memcpy_safe ((guint8 *) &hdr, sizeof(hdr), 0x0, /* dst */
+ buf, bufsz, offset, /* src */
+ sizeof(hdr), error))
+ return FALSE;
+ if (memcmp (hdr.sig, "DfuSe", sizeof(hdr.sig)) != 0) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "invalid DfuSe prefix");
+ return FALSE;
+ }
+
+ /* check the version */
+ if (hdr.ver != 0x01) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "invalid DfuSe version, got %02x",
+ hdr.ver);
+ return FALSE;
+ }
+
+ /* check image size */
+ if (GUINT32_FROM_LE (hdr.image_size) !=
+ bufsz - fu_dfu_firmware_get_footer_len (dfu_firmware)) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "invalid DfuSe image size, "
+ "got %" G_GUINT32_FORMAT ", "
+ "expected %" G_GSIZE_FORMAT,
+ GUINT32_FROM_LE (hdr.image_size),
+ bufsz - fu_dfu_firmware_get_footer_len (dfu_firmware));
+ return FALSE;
+ }
+
+ /* parse the image targets */
+ offset += sizeof(hdr);
+ for (guint i = 0; i < hdr.targets; i++) {
+ g_autoptr(FuFirmwareImage) image = NULL;
+ image = fu_dfuse_firmware_image_parse (FU_DFUSE_FIRMWARE (firmware),
+ fw, &offset,
+ error);
+ if (image == NULL)
+ return FALSE;
+ fu_firmware_add_image (firmware, image);
+ }
+ return TRUE;
+}
+
+static GBytes *
+fu_firmware_image_chunk_write (FuChunk *chk)
+{
+ DfuSeElementHdr hdr = { 0x0 };
+ const guint8 *data = fu_chunk_get_data (chk);
+ gsize length = fu_chunk_get_data_sz (chk);
+ g_autoptr(GByteArray) buf = NULL;
+
+ buf = g_byte_array_sized_new (sizeof(DfuSeElementHdr) + length);
+ hdr.address = GUINT32_TO_LE (fu_chunk_get_address (chk));
+ hdr.size = GUINT32_TO_LE (length);
+ g_byte_array_append (buf, (const guint8 *) &hdr, sizeof(hdr));
+ g_byte_array_append (buf, data, length);
+ return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
+}
+
+static GBytes *
+fu_dfuse_firmware_image_write (FuFirmwareImage *image, GError **error)
+{
+ DfuSeImageHdr hdr = { 0x0 };
+ gsize totalsz = 0;
+ g_autoptr(GByteArray) buf = NULL;
+ g_autoptr(GPtrArray) blobs = NULL;
+ g_autoptr(GPtrArray) chunks = NULL;
+
+ /* get total size */
+ blobs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
+ chunks = fu_firmware_image_get_chunks (image, error);
+ if (chunks == NULL)
+ return NULL;
+ for (guint i = 0; i < chunks->len; i++) {
+ FuChunk *chk = g_ptr_array_index (chunks, i);
+ GBytes *bytes = fu_firmware_image_chunk_write (chk);
+ g_ptr_array_add (blobs, bytes);
+ totalsz += g_bytes_get_size (bytes);
+ }
+
+ /* mutable output buffer */
+ buf = g_byte_array_sized_new (sizeof(DfuSeImageHdr) + totalsz);
+
+ /* add prefix */
+ memcpy (hdr.sig, "Target", 6);
+ hdr.alt_setting = fu_firmware_image_get_idx (image);
+ if (fu_firmware_image_get_id (image) != NULL) {
+ hdr.target_named = GUINT32_TO_LE (0x01);
+ g_strlcpy ((gchar *) &hdr.target_name,
+ fu_firmware_image_get_id (image),
+ sizeof(hdr.target_name));
+ }
+ hdr.target_size = GUINT32_TO_LE (totalsz);
+ hdr.chunks = GUINT32_TO_LE (chunks->len);
+ g_byte_array_append (buf, (const guint8 *) &hdr, sizeof(hdr));
+
+ /* copy data */
+ for (guint i = 0; i < blobs->len; i++) {
+ GBytes *blob = g_ptr_array_index (blobs, i);
+ g_byte_array_append (buf,
+ g_bytes_get_data (blob, NULL),
+ g_bytes_get_size (blob));
+ }
+ return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
+}
+
+static GBytes *
+fu_dfuse_firmware_write (FuFirmware *firmware, GError **error)
+{
+ DfuSeHdr hdr = { 0x0 };
+ gsize totalsz = 0;
+ g_autoptr(GByteArray) buf = NULL;
+ g_autoptr(GBytes) blob_noftr = NULL;
+ g_autoptr(GPtrArray) blobs = NULL;
+ g_autoptr(GPtrArray) images = NULL;
+
+ /* create mutable output buffer */
+ blobs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
+ images = fu_firmware_get_images (FU_FIRMWARE (firmware));
+ for (guint i = 0; i < images->len; i++) {
+ FuFirmwareImage *img = g_ptr_array_index (images, i);
+ g_autoptr(GBytes) blob = NULL;
+ blob = fu_dfuse_firmware_image_write (img, error);
+ if (blob == NULL)
+ return NULL;
+ totalsz += g_bytes_get_size (blob);
+ g_ptr_array_add (blobs, g_steal_pointer (&blob));
+ }
+ buf = g_byte_array_sized_new (sizeof(DfuSeHdr) + totalsz);
+
+ /* DfuSe header */
+ memcpy (hdr.sig, "DfuSe", 5);
+ hdr.ver = 0x01;
+ hdr.image_size = GUINT32_TO_LE (sizeof(hdr) + totalsz);
+ if (images->len > G_MAXUINT8) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "too many (%u) images to write DfuSe file",
+ images->len);
+ return NULL;
+ }
+ hdr.targets = (guint8) images->len;
+ g_byte_array_append (buf, (const guint8 *) &hdr, sizeof(hdr));
+
+ /* copy images */
+ for (guint i = 0; i < blobs->len; i++) {
+ GBytes *blob = g_ptr_array_index (blobs, i);
+ g_byte_array_append (buf,
+ g_bytes_get_data (blob, NULL),
+ g_bytes_get_size (blob));
+ }
+
+ /* return blob */
+ blob_noftr = g_byte_array_free_to_bytes (g_steal_pointer (&buf));
+ return fu_dfu_firmware_append_footer (FU_DFU_FIRMWARE (firmware),
+ blob_noftr, error);
+}
+
+static void
+fu_dfuse_firmware_init (FuDfuseFirmware *self)
+{
+ fu_dfu_firmware_set_version (FU_DFU_FIRMWARE (self), DFU_VERSION_DFUSE);
+}
+
+static void
+fu_dfuse_firmware_class_init (FuDfuseFirmwareClass *klass)
+{
+ FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
+ klass_firmware->parse = fu_dfuse_firmware_parse;
+ klass_firmware->write = fu_dfuse_firmware_write;
+}
+
+/**
+ * fu_dfuse_firmware_new:
+ *
+ * Creates a new #FuFirmware of sub type Dfuse
+ *
+ * Since: 1.5.6
+ **/
+FuFirmware *
+fu_dfuse_firmware_new (void)
+{
+ return FU_FIRMWARE (g_object_new (FU_TYPE_DFUSE_FIRMWARE, NULL));
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-dfuse-firmware.h fwupd-1.5.8/libfwupdplugin/fu-dfuse-firmware.h
--- fwupd-1.4.5/libfwupdplugin/fu-dfuse-firmware.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-dfuse-firmware.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fu-dfu-firmware.h"
+
+#define FU_TYPE_DFUSE_FIRMWARE (fu_dfuse_firmware_get_type ())
+G_DECLARE_DERIVABLE_TYPE (FuDfuseFirmware, fu_dfuse_firmware, FU, DFUSE_FIRMWARE, FuDfuFirmware)
+
+struct _FuDfuseFirmwareClass
+{
+ FuDfuFirmwareClass parent_class;
+};
+
+FuFirmware *fu_dfuse_firmware_new (void);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efi-signature.c fwupd-1.5.8/libfwupdplugin/fu-efi-signature.c
--- fwupd-1.4.5/libfwupdplugin/fu-efi-signature.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efi-signature.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#include "fu-efi-signature-private.h"
+
+/**
+ * SECTION:fu-efi-signature
+ * @short_description: Parser for EFI_SIGNATURE
+ *
+ * An object that represents a UEFI Signature.
+ *
+ * See also: #FuFirmware
+ */
+
+struct _FuEfiSignature {
+ FuFirmwareImage parent_instance;
+ FuEfiSignatureKind kind;
+ gchar *owner;
+};
+
+G_DEFINE_TYPE (FuEfiSignature, fu_efi_signature, FU_TYPE_FIRMWARE_IMAGE)
+
+/**
+ * fu_efi_signature_kind_to_string:
+ * @kind: A #FuEfiSignatureKind, e.g. %FU_EFI_SIGNATURE_KIND_X509
+ *
+ * Converts the signature kind to a text representation.
+ *
+ * Returns: text, e.g. `x509_cert`
+ *
+ * Since: 1.5.5
+ **/
+const gchar *
+fu_efi_signature_kind_to_string (FuEfiSignatureKind kind)
+{
+ if (kind == FU_EFI_SIGNATURE_KIND_SHA256)
+ return "sha256";
+ if (kind == FU_EFI_SIGNATURE_KIND_X509)
+ return "x509_cert";
+ return "unknown";
+}
+
+/**
+ * fu_efi_signature_new: (skip):
+ * @kind: A #FuEfiSignatureKind
+ * @owner: A GUID, e.g. %FU_EFI_SIGNATURE_GUID_MICROSOFT
+ *
+ * Creates a new EFI_SIGNATURE.
+ *
+ * Returns: (transfer full): signature
+ *
+ * Since: 1.5.5
+ **/
+FuEfiSignature *
+fu_efi_signature_new (FuEfiSignatureKind kind, const gchar *owner)
+{
+ g_autoptr(FuEfiSignature) self = g_object_new (FU_TYPE_EFI_SIGNATURE, NULL);
+ self->kind = kind;
+ self->owner = g_strdup (owner);
+ return g_steal_pointer (&self);
+}
+
+/**
+ * fu_efi_signature_get_kind:
+ * @self: A #FuEfiSignature
+ *
+ * Returns the signature kind.
+ *
+ * Returns: #FuEfiSignatureKind, e.g. %FU_EFI_SIGNATURE_KIND_SHA256
+ *
+ * Since: 1.5.5
+ **/
+FuEfiSignatureKind
+fu_efi_signature_get_kind (FuEfiSignature *self)
+{
+ g_return_val_if_fail (FU_IS_EFI_SIGNATURE (self), FU_EFI_SIGNATURE_KIND_UNKNOWN);
+ return self->kind;
+}
+
+/**
+ * fu_efi_signature_get_owner:
+ * @self: A #FuEfiSignature
+ *
+ * Returns the GUID of the signature owner.
+ *
+ * Returns: GUID owner, perhaps %FU_EFI_SIGNATURE_GUID_MICROSOFT
+ *
+ * Since: 1.5.5
+ **/
+const gchar *
+fu_efi_signature_get_owner (FuEfiSignature *self)
+{
+ g_return_val_if_fail (FU_IS_EFI_SIGNATURE (self), NULL);
+ return self->owner;
+}
+
+static gchar *
+fu_efi_signature_get_checksum (FuFirmwareImage *firmware_image,
+ GChecksumType csum_kind,
+ GError **error)
+{
+ FuEfiSignature *self = FU_EFI_SIGNATURE (firmware_image);
+ g_autoptr(GBytes) data = fu_firmware_image_get_bytes (firmware_image);
+
+ /* special case: this is *literally* a hash */
+ if (self->kind == FU_EFI_SIGNATURE_KIND_SHA256 &&
+ csum_kind == G_CHECKSUM_SHA256) {
+ GString *str;
+ const guint8 *buf;
+ gsize bufsz = 0;
+ buf = g_bytes_get_data (data, &bufsz);
+ str = g_string_new (NULL);
+ for (gsize i = 0; i < bufsz; i++)
+ g_string_append_printf (str, "%02x", buf[i]);
+ return g_string_free (str, FALSE);
+ }
+
+ /* fallback */
+ return g_compute_checksum_for_bytes (csum_kind, data);
+}
+
+static void
+fu_efi_signature_finalize (GObject *obj)
+{
+ FuEfiSignature *self = FU_EFI_SIGNATURE (obj);
+ g_free (self->owner);
+ G_OBJECT_CLASS (fu_efi_signature_parent_class)->finalize (obj);
+}
+
+static void
+fu_efi_signature_class_init (FuEfiSignatureClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ FuFirmwareImageClass *firmware_image_class = FU_FIRMWARE_IMAGE_CLASS (klass);
+ object_class->finalize = fu_efi_signature_finalize;
+ firmware_image_class->get_checksum = fu_efi_signature_get_checksum;
+}
+
+static void
+fu_efi_signature_init (FuEfiSignature *self)
+{
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efi-signature.h fwupd-1.5.8/libfwupdplugin/fu-efi-signature.h
--- fwupd-1.4.5/libfwupdplugin/fu-efi-signature.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efi-signature.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include
+
+#include "fu-firmware-image.h"
+
+#define FU_TYPE_EFI_SIGNATURE (fu_efi_signature_get_type ())
+G_DECLARE_FINAL_TYPE (FuEfiSignature, fu_efi_signature, FU, EFI_SIGNATURE, FuFirmwareImage)
+
+typedef enum {
+ FU_EFI_SIGNATURE_KIND_UNKNOWN,
+ FU_EFI_SIGNATURE_KIND_SHA256,
+ FU_EFI_SIGNATURE_KIND_X509,
+ /*< private >*/
+ FU_EFI_SIGNATURE_KIND_LAST
+} FuEfiSignatureKind;
+
+#define FU_EFI_SIGNATURE_GUID_ZERO "00000000-0000-0000-0000-000000000000"
+#define FU_EFI_SIGNATURE_GUID_MICROSOFT "77fa9abd-0359-4d32-bd60-28f4e78f784b"
+#define FU_EFI_SIGNATURE_GUID_OVMF "a0baa8a3-041d-48a8-bc87-c36d121b5e3d"
+#define FU_EFI_SIGNATURE_GUID_OVMF_LEGACY "d5c1df0b-1bac-4edf-ba48-08834009ca5a"
+
+const gchar *fu_efi_signature_kind_to_string (FuEfiSignatureKind kind);
+
+FuEfiSignatureKind fu_efi_signature_get_kind (FuEfiSignature *self);
+const gchar *fu_efi_signature_get_owner (FuEfiSignature *self);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efi-signature-list.c fwupd-1.5.8/libfwupdplugin/fu-efi-signature-list.c
--- fwupd-1.4.5/libfwupdplugin/fu-efi-signature-list.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efi-signature-list.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "fu-common.h"
+#include "fu-efi-signature-private.h"
+#include "fu-efi-signature-list.h"
+
+/**
+ * SECTION:fu-efi-signature-list
+ * @short_description: Parser for EFI_SIGNATURE_LIST
+ *
+ * An object that represents a UEFI SignatureList.
+ *
+ * See also: #FuFirmware
+ */
+
+struct _FuEfiSignatureList {
+ FuFirmware parent_instance;
+};
+
+G_DEFINE_TYPE (FuEfiSignatureList, fu_efi_signature_list, FU_TYPE_FIRMWARE)
+
+static gboolean
+fu_efi_signature_list_parse_item (FuEfiSignatureList *self,
+ FuEfiSignatureKind sig_kind,
+ const guint8 *buf,
+ gsize bufsz,
+ gsize offset,
+ guint32 sig_size,
+ GError **error)
+{
+ fwupd_guid_t guid;
+ gsize sig_datasz;
+ g_autofree gchar *sig_owner = NULL;
+ g_autofree guint8 *sig_data = NULL;
+ g_autoptr(FuEfiSignature) sig = NULL;
+ g_autoptr(GBytes) data = NULL;
+
+ /* allocate data buf */
+ if (sig_size <= sizeof(fwupd_guid_t)) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "SignatureSize invalid: 0x%x",
+ (guint) sig_size);
+ return FALSE;
+ }
+ sig_datasz = sig_size - sizeof(fwupd_guid_t);
+ sig_data = g_malloc0 (sig_datasz);
+
+ /* read both blocks of data */
+ if (!fu_memcpy_safe ((guint8 *) &guid, sizeof(guid), 0x0, /* dst */
+ buf, bufsz, offset, /* src */
+ sizeof(guid), error)) {
+ g_prefix_error (error, "failed to read signature GUID: ");
+ return FALSE;
+ }
+ if (!fu_memcpy_safe (sig_data, sig_datasz, 0x0, /* dst */
+ buf, bufsz, offset + sizeof(fwupd_guid_t), /* src */
+ sig_datasz, error)) {
+ g_prefix_error (error, "failed to read signature data: ");
+ return FALSE;
+ }
+
+ /* create item */
+ sig_owner = fwupd_guid_to_string (&guid, FWUPD_GUID_FLAG_MIXED_ENDIAN);
+ data = g_bytes_new (sig_data, sig_datasz);
+ sig = fu_efi_signature_new (sig_kind, sig_owner);
+ fu_firmware_image_set_bytes (FU_FIRMWARE_IMAGE (sig), data);
+ fu_firmware_add_image (FU_FIRMWARE (self), FU_FIRMWARE_IMAGE (sig));
+ return TRUE;
+}
+
+static gboolean
+fu_efi_signature_list_parse_list (FuEfiSignatureList *self,
+ const guint8 *buf,
+ gsize bufsz,
+ gsize *offset,
+ GError **error)
+{
+ FuEfiSignatureKind sig_kind = FU_EFI_SIGNATURE_KIND_UNKNOWN;
+ fwupd_guid_t guid;
+ gsize offset_tmp;
+ guint32 sig_header_size = 0;
+ guint32 sig_list_size = 0;
+ guint32 sig_size = 0;
+ g_autofree gchar *sig_type = NULL;
+
+ /* read EFI_SIGNATURE_LIST */
+ if (!fu_memcpy_safe ((guint8 *) &guid, sizeof(guid), 0x0, /* dst */
+ buf, bufsz, *offset, /* src */
+ sizeof(guid), error)) {
+ g_prefix_error (error, "failed to read GUID header: ");
+ return FALSE;
+ }
+ sig_type = fwupd_guid_to_string (&guid, FWUPD_GUID_FLAG_MIXED_ENDIAN);
+ if (g_strcmp0 (sig_type, "c1c41626-504c-4092-aca9-41f936934328") == 0) {
+ sig_kind = FU_EFI_SIGNATURE_KIND_SHA256;
+ } else if (g_strcmp0 (sig_type, "a5c059a1-94e4-4aa7-87b5-ab155c2bf072") == 0) {
+ sig_kind = FU_EFI_SIGNATURE_KIND_X509;
+ }
+ if (!fu_common_read_uint32_safe (buf, bufsz, *offset + 0x10,
+ &sig_list_size, G_LITTLE_ENDIAN, error))
+ return FALSE;
+ if (sig_list_size < 0x1c || sig_list_size > 1024 * 1024) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "SignatureListSize invalid: 0x%x", sig_list_size);
+ return FALSE;
+ }
+ if (!fu_common_read_uint32_safe (buf, bufsz, *offset + 0x14,
+ &sig_header_size, G_LITTLE_ENDIAN, error))
+ return FALSE;
+ if (sig_header_size > 1024 * 1024) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "SignatureHeaderSize invalid: 0x%x", sig_size);
+ return FALSE;
+ }
+ if (!fu_common_read_uint32_safe (buf, bufsz, *offset + 0x18,
+ &sig_size, G_LITTLE_ENDIAN, error))
+ return FALSE;
+ if (sig_size < sizeof(fwupd_guid_t) || sig_size > 1024 * 1024) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "SignatureSize invalid: 0x%x", sig_size);
+ return FALSE;
+ }
+
+ /* header is typically unused */
+ offset_tmp = *offset + 0x1c + sig_header_size;
+ for (guint i = 0; i < (sig_list_size - 0x1c) / sig_size; i++) {
+ if (!fu_efi_signature_list_parse_item (self, sig_kind, buf, bufsz,
+ offset_tmp, sig_size,
+ error))
+ return FALSE;
+ offset_tmp += sig_size;
+ }
+ *offset += sig_list_size;
+ return TRUE;
+}
+
+static gchar *
+fu_efi_signature_list_get_version (FuEfiSignatureList *self)
+{
+ guint csum_cnt = 0;
+ const gchar *ignored_guids[] = {
+ FU_EFI_SIGNATURE_GUID_OVMF,
+ FU_EFI_SIGNATURE_GUID_OVMF_LEGACY,
+ NULL };
+ g_autoptr(GPtrArray) sigs = NULL;
+ sigs = fu_firmware_get_images (FU_FIRMWARE (self));
+ for (guint i = 0; i < sigs->len; i++) {
+ FuEfiSignature *sig = g_ptr_array_index (sigs, i);
+ if (fu_efi_signature_get_kind (sig) != FU_EFI_SIGNATURE_KIND_SHA256)
+ continue;
+ if (g_strv_contains (ignored_guids, fu_efi_signature_get_owner (sig)))
+ continue;
+ csum_cnt++;
+ }
+ return g_strdup_printf ("%u", csum_cnt);
+}
+
+static gboolean
+fu_efi_signature_list_parse (FuFirmware *firmware,
+ GBytes *fw,
+ guint64 addr_start,
+ guint64 addr_end,
+ FwupdInstallFlags flags,
+ GError **error)
+{
+ FuEfiSignatureList *self = FU_EFI_SIGNATURE_LIST (firmware);
+ gsize bufsz = 0;
+ gsize offset_fs = 0;
+ const guint8 *buf = g_bytes_get_data (fw, &bufsz);
+ g_autofree gchar *version_str = NULL;
+
+ /* this allows us to skip the efi permissions uint32_t or even the
+ * Microsoft PKCS-7 signature */
+ if ((flags & FWUPD_INSTALL_FLAG_NO_SEARCH) == 0) {
+ if (bufsz < 5) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "signature invalid: 0x%x",
+ (guint) bufsz);
+ return FALSE;
+ }
+ for (gsize i = 0; i < bufsz - 5; i++) {
+ if (memcmp (buf + i, "\x26\x16\xc4\xc1\x4c", 5) == 0) {
+ g_debug ("found EFI_SIGNATURE_LIST @0x%x", (guint) i);
+ offset_fs = i;
+ break;
+ }
+ }
+ }
+
+ /* parse each EFI_SIGNATURE_LIST */
+ for (gsize offset = offset_fs; offset < bufsz;) {
+ if (!fu_efi_signature_list_parse_list (self, buf, bufsz, &offset, error))
+ return FALSE;
+ }
+
+ /* set version */
+ version_str = fu_efi_signature_list_get_version (self);
+ if (version_str != NULL)
+ fu_firmware_set_version (firmware, version_str);
+
+ /* success */
+ return TRUE;
+}
+
+static GBytes *
+fu_efi_signature_list_write (FuFirmware *firmware, GError **error)
+{
+ GByteArray *buf = g_byte_array_new ();
+
+ /* SignatureType */
+ for (guint i = 0; i < 16; i++)
+ fu_byte_array_append_uint8 (buf, 0x0);
+
+ /* SignatureListSize */
+ fu_byte_array_append_uint32 (buf, 16 + 4 + 4 + 4 + 16 + 32, G_LITTLE_ENDIAN);
+
+ /* SignatureHeaderSize */
+ fu_byte_array_append_uint32 (buf, 0, G_LITTLE_ENDIAN);
+
+ /* SignatureSize */
+ fu_byte_array_append_uint32 (buf, 16 + 32, G_LITTLE_ENDIAN);
+
+ /* SignatureOwner */
+ for (guint i = 0; i < 16; i++)
+ fu_byte_array_append_uint8 (buf, '1');
+
+ /* SignatureData */
+ for (guint i = 0; i < 16; i++)
+ fu_byte_array_append_uint8 (buf, '2');
+
+ return g_byte_array_free_to_bytes (buf);
+}
+
+/**
+ * fu_efi_signature_list_new:
+ *
+ * Creates a new #FuFirmware that can parse an EFI_SIGNATURE_LIST
+ *
+ * Since: 1.5.5
+ **/
+FuFirmware *
+fu_efi_signature_list_new (void)
+{
+ return g_object_new (FU_TYPE_EFI_SIGNATURE_LIST, NULL);
+}
+
+static void
+fu_efi_signature_list_class_init (FuEfiSignatureListClass *klass)
+{
+ FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
+ klass_firmware->parse = fu_efi_signature_list_parse;
+ klass_firmware->write = fu_efi_signature_list_write;
+}
+
+static void
+fu_efi_signature_list_init (FuEfiSignatureList *self)
+{
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efi-signature-list.h fwupd-1.5.8/libfwupdplugin/fu-efi-signature-list.h
--- fwupd-1.4.5/libfwupdplugin/fu-efi-signature-list.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efi-signature-list.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fu-firmware.h"
+
+#define FU_TYPE_EFI_SIGNATURE_LIST (fu_efi_signature_list_get_type ())
+G_DECLARE_FINAL_TYPE (FuEfiSignatureList, fu_efi_signature_list, FU, EFI_SIGNATURE_LIST, FuFirmware)
+
+FuFirmware *fu_efi_signature_list_new (void);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efi-signature-private.h fwupd-1.5.8/libfwupdplugin/fu-efi-signature-private.h
--- fwupd-1.4.5/libfwupdplugin/fu-efi-signature-private.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efi-signature-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fu-efi-signature.h"
+
+FuEfiSignature *fu_efi_signature_new (FuEfiSignatureKind kind,
+ const gchar *owner);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efivar.c fwupd-1.5.8/libfwupdplugin/fu-efivar.c
--- fwupd-1.4.5/libfwupdplugin/fu-efivar.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efivar.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018 Richard Hughes
- * Copyright (C) 2015-2017 Peter Jones
+ * Copyright (C) 2015 Peter Jones
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -51,6 +51,7 @@
{
#ifndef _WIN32
g_autofree gchar *efivardir = fu_efivar_get_path ();
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!g_file_test (efivardir, G_FILE_TEST_IS_DIR)) {
g_set_error (error,
FWUPD_ERROR,
@@ -61,6 +62,7 @@
}
return TRUE;
#else
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
@@ -69,13 +71,13 @@
#endif
}
+#ifndef _WIN32
static gboolean
fu_efivar_set_immutable_fd (int fd,
gboolean value,
gboolean *value_old,
GError **error)
{
-#ifndef _WIN32
guint flags;
gboolean is_immutable;
int rc;
@@ -124,14 +126,8 @@
return FALSE;
}
return TRUE;
-#else
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_SUPPORTED,
- "efivarfs not currently supported on Windows");
- return FALSE;
-#endif
}
+#endif
static gboolean
fu_efivar_set_immutable (const gchar *fn,
@@ -179,8 +175,15 @@
gboolean
fu_efivar_delete (const gchar *guid, const gchar *name, GError **error)
{
- g_autofree gchar *fn = fu_efivar_get_filename (guid, name);
- g_autoptr(GFile) file = g_file_new_for_path (fn);
+ g_autofree gchar *fn = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ g_return_val_if_fail (guid != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ fn = fu_efivar_get_filename (guid, name);
+ file = g_file_new_for_path (fn);
if (!g_file_query_exists (file, NULL))
return TRUE;
if (!fu_efivar_set_immutable (fn, FALSE, NULL, error)) {
@@ -208,7 +211,13 @@
const gchar *fn;
g_autofree gchar *nameguid_glob = NULL;
g_autofree gchar *efivardir = fu_efivar_get_path ();
- g_autoptr(GDir) dir = g_dir_open (efivardir, 0, error);
+ g_autoptr(GDir) dir = NULL;
+
+ g_return_val_if_fail (guid != NULL, FALSE);
+ g_return_val_if_fail (name_glob != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ dir = g_dir_open (efivardir, 0, error);
if (dir == NULL)
return FALSE;
nameguid_glob = g_strdup_printf ("%s-%s", name_glob, guid);
@@ -227,10 +236,27 @@
return TRUE;
}
+static gboolean
+fu_efivar_exists_guid (const gchar *guid)
+{
+ const gchar *fn;
+ g_autofree gchar *efivardir = fu_efivar_get_path ();
+ g_autoptr(GDir) dir = NULL;
+
+ dir = g_dir_open (efivardir, 0, NULL);
+ if (dir == NULL)
+ return FALSE;
+ while ((fn = g_dir_read_name (dir)) != NULL) {
+ if (g_str_has_suffix (fn, guid))
+ return TRUE;
+ }
+ return TRUE;
+}
+
/**
* fu_efivar_exists:
* @guid: Globally unique identifier
- * @name: Variable name
+ * @name: (nullable): Variable name
*
* Test if a variable exists
*
@@ -241,7 +267,15 @@
gboolean
fu_efivar_exists (const gchar *guid, const gchar *name)
{
- g_autofree gchar *fn = fu_efivar_get_filename (guid, name);
+ g_autofree gchar *fn = NULL;
+
+ g_return_val_if_fail (guid != NULL, FALSE);
+
+ /* any name */
+ if (name == NULL)
+ return fu_efivar_exists_guid (guid);
+
+ fn = fu_efivar_get_filename (guid, name);
return g_file_test (fn, G_FILE_TEST_EXISTS);
}
@@ -269,12 +303,18 @@
gssize data_sz_tmp;
guint32 attr_tmp;
guint64 sz;
- g_autofree gchar *fn = fu_efivar_get_filename (guid, name);
- g_autoptr(GFile) file = g_file_new_for_path (fn);
+ g_autofree gchar *fn = NULL;
+ g_autoptr(GFile) file = NULL;
g_autoptr(GFileInfo) info = NULL;
g_autoptr(GInputStream) istr = NULL;
+ g_return_val_if_fail (guid != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* open file as stream */
+ fn = fu_efivar_get_filename (guid, name);
+ file = g_file_new_for_path (fn);
istr = G_INPUT_STREAM (g_file_read (file, NULL, error));
if (istr == NULL)
return FALSE;
@@ -329,6 +369,165 @@
}
/**
+ * fu_efivar_get_data_bytes:
+ * @guid: Globally unique identifier
+ * @name: Variable name
+ * @attr: (nullable): Attributes
+ * @error: A #GError
+ *
+ * Gets the data from a UEFI variable in NVRAM
+ *
+ * Returns: (transfer full): a #GBytes, or %NULL
+ *
+ * Since: 1.5.0
+ **/
+GBytes *
+fu_efivar_get_data_bytes (const gchar *guid,
+ const gchar *name,
+ guint32 *attr,
+ GError **error)
+{
+ guint8 *data = NULL;
+ gsize datasz = 0;
+
+ g_return_val_if_fail (guid != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (!fu_efivar_get_data (guid, name, &data, &datasz, attr, error))
+ return NULL;
+ return g_bytes_new_take (data, datasz);
+}
+
+/**
+ * fu_efivar_get_names:
+ * @guid: Globally unique identifier
+ * @error: A #GError
+ *
+ * Gets the list of names where the GUID matches. An error is set if there are
+ * no names matching the GUID.
+ *
+ * Returns: (transfer container) (element-type utf8): array of names
+ *
+ * Since: 1.4.7
+ **/
+GPtrArray *
+fu_efivar_get_names (const gchar *guid, GError **error)
+{
+ const gchar *name_guid;
+ g_autofree gchar *path = fu_efivar_get_path ();
+ g_autoptr(GDir) dir = NULL;
+ g_autoptr(GPtrArray) names = g_ptr_array_new_with_free_func (g_free);
+
+ g_return_val_if_fail (guid != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* find names with matching GUID */
+ dir = g_dir_open (path, 0, error);
+ if (dir == NULL)
+ return NULL;
+ while ((name_guid = g_dir_read_name (dir)) != NULL) {
+ gsize name_guidsz = strlen (name_guid);
+ if (name_guidsz < 38)
+ continue;
+ if (g_strcmp0 (name_guid + name_guidsz - 36, guid) == 0) {
+ g_ptr_array_add (names,
+ g_strndup (name_guid, name_guidsz - 37));
+ }
+ }
+
+ /* nothing found */
+ if (names->len == 0) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "no names for GUID %s", guid);
+ return NULL;
+ }
+
+ /* success */
+ return g_steal_pointer (&names);
+}
+
+/**
+ * fu_efivar_get_monitor:
+ * @guid: Globally unique identifier
+ * @name: Variable name
+ * @error: A #GError
+ *
+ * Returns a file monitor for a specific key.
+ *
+ * Returns: (transfer full): a #GFileMonitor, or %NULL for an error
+ *
+ * Since: 1.5.5
+ **/
+GFileMonitor *
+fu_efivar_get_monitor (const gchar *guid, const gchar *name, GError **error)
+{
+ g_autofree gchar *fn = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileMonitor) monitor = NULL;
+
+ g_return_val_if_fail (guid != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ fn = fu_efivar_get_filename (guid, name);
+ file = g_file_new_for_path (fn);
+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, error);
+ if (monitor == NULL)
+ return NULL;
+ g_file_monitor_set_rate_limit (monitor, 5000);
+ return g_steal_pointer (&monitor);
+}
+
+/**
+ * fu_efivar_space_used:
+ * @error: A #GError
+ *
+ * Gets the total size used by all EFI variables. This may be less than the size reported by the
+ * kernel as some (hopefully small) variables are hidden from userspace.
+ *
+ * Returns: total allocated size of all visible variables, or %G_MAXUINT64 on error
+ *
+ * Since: 1.5.1
+ **/
+guint64
+fu_efivar_space_used (GError **error)
+{
+ const gchar *fn;
+ guint64 total = 0;
+ g_autoptr(GDir) dir = NULL;
+ g_autofree gchar *path = fu_efivar_get_path ();
+
+ g_return_val_if_fail (error == NULL || *error == NULL, G_MAXUINT64);
+
+ /* stat each file */
+ dir = g_dir_open (path, 0, error);
+ if (dir == NULL)
+ return G_MAXUINT64;
+ while ((fn = g_dir_read_name (dir)) != NULL) {
+ guint64 sz;
+ g_autofree gchar *pathfn = g_build_filename (path, fn, NULL);
+ g_autoptr(GFile) file = g_file_new_for_path (pathfn);
+ g_autoptr(GFileInfo) info = NULL;
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, error);
+ if (info == NULL)
+ return G_MAXUINT64;
+ sz = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
+ if (sz == 0)
+ sz = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+ total += sz;
+ }
+
+ /* success */
+ return total;
+}
+/**
* fu_efivar_set_data:
* @guid: Globally unique identifier
* @name: Variable name
@@ -349,12 +548,18 @@
{
#ifndef _WIN32
int fd;
+ int open_wflags;
gboolean was_immutable;
g_autofree gchar *fn = fu_efivar_get_filename (guid, name);
g_autofree guint8 *buf = g_malloc0 (sizeof(guint32) + sz);
g_autoptr(GFile) file = g_file_new_for_path (fn);
g_autoptr(GOutputStream) ostr = NULL;
+ g_return_val_if_fail (guid != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* create empty file so we can clear the immutable bit before writing */
if (!g_file_query_exists (file, NULL)) {
g_autoptr(GFileOutputStream) ostr_tmp = NULL;
@@ -374,8 +579,11 @@
return FALSE;
}
- /* open file for writing */
- fd = open (fn, O_WRONLY);
+ /* open file for writing, optionally append */
+ open_wflags = O_WRONLY;
+ if (attr & FU_EFIVAR_ATTR_APPEND_WRITE)
+ open_wflags |= O_APPEND;
+ fd = open (fn, open_wflags);
if (fd < 0) {
g_set_error (error,
G_IO_ERROR,
@@ -410,24 +618,83 @@
}
/**
- * fu_efivar_secure_boot_enabled:
+ * fu_efivar_set_data_bytes:
+ * @guid: Globally unique identifier
+ * @name: Variable name
+ * @bytes: a #GBytes
+ * @attr: Attributes
+ * @error: A #GError
+ *
+ * Sets the data to a UEFI variable in NVRAM
+ *
+ * Returns: %TRUE on success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_efivar_set_data_bytes (const gchar *guid, const gchar *name, GBytes *bytes,
+ guint32 attr, GError **error)
+{
+ gsize bufsz = 0;
+ const guint8 *buf;
+
+ g_return_val_if_fail (guid != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (bytes != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ buf = g_bytes_get_data (bytes, &bufsz);
+ return fu_efivar_set_data (guid, name, buf, bufsz, attr, error);
+}
+
+/**
+ * fu_efivar_secure_boot_enabled_full:
+ * @error: A #GError
*
* Determines if secure boot was enabled
*
* Returns: %TRUE on success
*
- * Since: 1.4.0
+ * Since: 1.5.0
**/
gboolean
-fu_efivar_secure_boot_enabled (void)
+fu_efivar_secure_boot_enabled_full (GError **error)
{
gsize data_size = 0;
g_autofree guint8 *data = NULL;
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
if (!fu_efivar_get_data (FU_EFIVAR_GUID_EFI_GLOBAL, "SecureBoot",
- &data, &data_size, NULL, NULL))
+ &data, &data_size, NULL, NULL)) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "SecureBoot is not available");
return FALSE;
+ }
if (data_size >= 1 && data[0] & 1)
return TRUE;
+
+ /* available, but not enabled */
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "SecureBoot is not enabled");
return FALSE;
}
+
+/**
+ * fu_efivar_secure_boot_enabled:
+ *
+ * Determines if secure boot was enabled
+ *
+ * Returns: %TRUE on success
+ *
+ * Since: 1.4.0
+ **/
+gboolean
+fu_efivar_secure_boot_enabled (void)
+{
+ return fu_efivar_secure_boot_enabled_full (NULL);
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-efivar.h fwupd-1.5.8/libfwupdplugin/fu-efivar.h
--- fwupd-1.4.5/libfwupdplugin/fu-efivar.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-efivar.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,45 +1,70 @@
/*
* Copyright (C) 2018 Richard Hughes
- * Copyright (C) 2015-2017 Peter Jones
+ * Copyright (C) 2015 Peter Jones
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
-#include
+#include
#define FU_EFIVAR_GUID_EFI_GLOBAL "8be4df61-93ca-11d2-aa0d-00e098032b8c"
-#define FU_EFIVAR_GUID_FWUPDATE "0abba7dc-e516-4167-bbf5-4d9d1c739416"
+#define FU_EFIVAR_GUID_FWUPDATE "0abba7dc-e516-4167-bbf5-4d9d1c739416"
+#define FU_EFIVAR_GUID_UX_CAPSULE "3b8c8162-188c-46a4-aec9-be43f1d65697"
+#define FU_EFIVAR_GUID_SECURITY_DATABASE "d719b2cb-3d3a-4596-a3bc-dad00e67656f"
#define FU_EFIVAR_GUID_UX_CAPSULE "3b8c8162-188c-46a4-aec9-be43f1d65697"
#define FU_EFIVAR_ATTR_NON_VOLATILE (1 << 0)
#define FU_EFIVAR_ATTR_BOOTSERVICE_ACCESS (1 << 1)
-#define FU_EFIVAR_ATTR_RUNTIME_ACCESS (1 << 2)
+#define FU_EFIVAR_ATTR_RUNTIME_ACCESS (1 << 2)
#define FU_EFIVAR_ATTR_HARDWARE_ERROR_RECORD (1 << 3)
#define FU_EFIVAR_ATTR_AUTHENTICATED_WRITE_ACCESS (1 << 4)
-#define FU_EFIVAR_ATTR_TIME_BASED_AUTHENTICATED_WRITE_ACCESS (5 << 0)
+#define FU_EFIVAR_ATTR_TIME_BASED_AUTHENTICATED_WRITE_ACCESS (1 << 5)
#define FU_EFIVAR_ATTR_APPEND_WRITE (1 << 6)
gboolean fu_efivar_supported (GError **error);
+guint64 fu_efivar_space_used (GError **error);
gboolean fu_efivar_exists (const gchar *guid,
const gchar *name);
+GFileMonitor *fu_efivar_get_monitor (const gchar *guid,
+ const gchar *name,
+ GError **error);
gboolean fu_efivar_get_data (const gchar *guid,
const gchar *name,
guint8 **data,
gsize *data_sz,
guint32 *attr,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GBytes *fu_efivar_get_data_bytes (const gchar *guid,
+ const gchar *name,
+ guint32 *attr,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_efivar_set_data (const gchar *guid,
const gchar *name,
const guint8 *data,
gsize sz,
guint32 attr,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_efivar_set_data_bytes (const gchar *guid,
+ const gchar *name,
+ GBytes *bytes,
+ guint32 attr,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_efivar_delete (const gchar *guid,
const gchar *name,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_efivar_delete_with_glob (const gchar *guid,
const gchar *name_glob,
- GError **error);
-gboolean fu_efivar_secure_boot_enabled (void);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fu_efivar_get_names (const gchar *guid,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_efivar_secure_boot_enabled (void);
+gboolean fu_efivar_secure_boot_enabled_full(GError **error);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-firmware.c fwupd-1.5.8/libfwupdplugin/fu-firmware.c
--- fwupd-1.4.5/libfwupdplugin/fu-firmware.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-firmware.c 2021-03-31 20:08:32.000000000 +0000
@@ -21,14 +21,103 @@
*/
typedef struct {
+ FuFirmwareFlags flags;
GPtrArray *images; /* FuFirmwareImage */
gchar *version;
+ guint64 version_raw;
} FuFirmwarePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FuFirmware, fu_firmware, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fu_firmware_get_instance_private (o))
/**
+ * fu_firmware_flag_to_string:
+ * @flag: A #FuFirmwareFlags, e.g. %FU_FIRMWARE_FLAG_DEDUPE_ID
+ *
+ * Converts a #FuFirmwareFlags to a string.
+ *
+ * Return value: identifier string
+ *
+ * Since: 1.5.0
+ **/
+const gchar *
+fu_firmware_flag_to_string (FuFirmwareFlags flag)
+{
+ if (flag == FU_FIRMWARE_FLAG_NONE)
+ return "none";
+ if (flag == FU_FIRMWARE_FLAG_DEDUPE_ID)
+ return "dedupe-id";
+ if (flag == FU_FIRMWARE_FLAG_DEDUPE_IDX)
+ return "dedupe-idx";
+ if (flag == FU_FIRMWARE_FLAG_HAS_CHECKSUM)
+ return "has-checksum";
+ if (flag == FU_FIRMWARE_FLAG_HAS_VID_PID)
+ return "has-vid-pid";
+ return NULL;
+}
+
+/**
+ * fu_firmware_flag_from_string:
+ * @flag: A string, e.g. `dedupe-id`
+ *
+ * Converts a string to a #FuFirmwareFlags.
+ *
+ * Return value: enumerated value
+ *
+ * Since: 1.5.0
+ **/
+FuFirmwareFlags
+fu_firmware_flag_from_string (const gchar *flag)
+{
+ if (g_strcmp0 (flag, "dedupe-id") == 0)
+ return FU_FIRMWARE_FLAG_DEDUPE_ID;
+ if (g_strcmp0 (flag, "dedupe-idx") == 0)
+ return FU_FIRMWARE_FLAG_DEDUPE_IDX;
+ if (g_strcmp0 (flag, "has-checksum") == 0)
+ return FU_FIRMWARE_FLAG_HAS_CHECKSUM;
+ if (g_strcmp0 (flag, "has-vid-pid") == 0)
+ return FU_FIRMWARE_FLAG_HAS_VID_PID;
+ return FU_FIRMWARE_FLAG_NONE;
+}
+
+/**
+ * fu_firmware_add_flag:
+ * @firmware: A #FuFirmware
+ * @flag: the #FuFirmwareFlags
+ *
+ * Adds a specific firmware flag to the firmware.
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_firmware_add_flag (FuFirmware *firmware, FuFirmwareFlags flag)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (firmware);
+ g_return_if_fail (FU_IS_FIRMWARE (firmware));
+ priv->flags |= flag;
+}
+
+
+/**
+ * fu_firmware_has_flag:
+ * @firmware: A #FuFirmware
+ * @flag: the #FuFirmwareFlags
+ *
+ * Finds if the firmware has a specific firmware flag.
+ *
+ * Returns: %TRUE if the flag is set
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_has_flag (FuFirmware *firmware, FuFirmwareFlags flag)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (firmware);
+ g_return_val_if_fail (FU_IS_FIRMWARE (firmware), FALSE);
+ return (priv->flags & flag) > 0;
+}
+
+/**
* fu_firmware_get_version:
* @self: A #FuFirmware
*
@@ -60,11 +149,55 @@
{
FuFirmwarePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_FIRMWARE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->version, version) == 0)
+ return;
+
g_free (priv->version);
priv->version = g_strdup (version);
}
/**
+ * fu_firmware_get_version_raw:
+ * @self: A #FuFirmware
+ *
+ * Gets an raw version that represents the firmware. This is most frequently
+ * used when building firmware with `0x123456` in a
+ * `firmware.builder.xml` file to avoid string splitting and sanity checks.
+ *
+ * Returns: an integer, or %G_MAXUINT64 for invalid
+ *
+ * Since: 1.5.7
+ **/
+guint64
+fu_firmware_get_version_raw (FuFirmware *self)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), G_MAXUINT64);
+ return priv->version_raw;
+}
+
+/**
+ * fu_firmware_set_version_raw:
+ * @self: A #FuFirmware
+ * @version_raw: A raw version, or %G_MAXUINT64 for invalid
+ *
+ * Sets an raw version that represents the firmware.
+ *
+ * This is optional, and is typically only used for debugging.
+ *
+ * Since: 1.5.7
+ **/
+void
+fu_firmware_set_version_raw (FuFirmware *self, guint64 version_raw)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_FIRMWARE (self));
+ priv->version_raw = version_raw;
+}
+
+/**
* fu_firmware_tokenize:
* @self: A #FuFirmware
* @fw: A #GBytes
@@ -126,6 +259,15 @@
g_return_val_if_fail (fw != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ /* sanity check */
+ if (g_bytes_get_size (fw) == 0) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "invalid firmware as zero sized");
+ return FALSE;
+ }
+
/* subclassed */
if (klass->tokenize != NULL) {
if (!klass->tokenize (self, fw, flags, error))
@@ -160,6 +302,112 @@
}
/**
+ * fu_firmware_build:
+ * @self: A #FuFirmware
+ * @n: A #XbNode
+ * @error: A #GError, or %NULL
+ *
+ * Builds a firmware from an XML manifest. The manifest would typically have the
+ * following form:
+ *
+ * |[
+ *
+ *
+ * 1.2.3
+ *
+ * 7.8.9
+ * stage1
+ * 0x01
+ * stage1.bin
+ *
+ *
+ * stage2
+ *
+ *
+ *
+ * ape
+ * 0x7
+ * aGVsbG8gd29ybGQ=
+ *
+ *
+ * ]|
+ *
+ * This would be used in a build-system to merge images from generated files:
+ * `fwupdtool firmware-build fw.builder.xml test.fw`
+ *
+ * Static binary content can be specified in the `/` sections and
+ * is encoded as base64 text if not empty.
+ *
+ * Additionally, extra nodes can be included under `` and ``
+ * which can be parsed by the subclassed objects. You should verify the
+ * subclassed object `FuFirmwareImage->build` vfunc for the specific additional
+ * options supported.
+ *
+ * Plugins should manually g_type_ensure() subclassed image objects if not
+ * constructed as part of the plugin fu_plugin_init() or fu_plugin_setup()
+ * functions.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_build (FuFirmware *self, XbNode *n, GError **error)
+{
+ FuFirmwareClass *klass = FU_FIRMWARE_GET_CLASS (self);
+ const gchar *tmp;
+ guint64 version_raw;
+ g_autoptr(GPtrArray) xb_images = NULL;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), FALSE);
+ g_return_val_if_fail (XB_IS_NODE (n), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* set attributes */
+ tmp = xb_node_query_text (n, "version", NULL);
+ if (tmp != NULL)
+ fu_firmware_set_version (self, tmp);
+ version_raw = xb_node_query_text_as_uint (n, "version_raw", NULL);
+ if (version_raw != G_MAXUINT64)
+ fu_firmware_set_version_raw (self, version_raw);
+
+ /* parse images */
+ xb_images = xb_node_query (n, "image", 0, NULL);
+ if (xb_images != NULL) {
+ for (guint i = 0; i < xb_images->len; i++) {
+ XbNode *xb_image = g_ptr_array_index (xb_images, i);
+ g_autoptr(FuFirmwareImage) img = NULL;
+ tmp = xb_node_get_attr (xb_image, "gtype");
+ if (tmp != NULL) {
+ GType gtype = g_type_from_name (tmp);
+ if (gtype == G_TYPE_INVALID) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "GType %s not registered", tmp);
+ return FALSE;
+ }
+ img = g_object_new (gtype, NULL);
+ } else {
+ img = fu_firmware_image_new (NULL);
+ }
+ if (!fu_firmware_image_build (img, xb_image, error))
+ return FALSE;
+ fu_firmware_add_image (self, img);
+ }
+ }
+
+ /* subclassed */
+ if (klass->build != NULL) {
+ if (!klass->build (self, n, error))
+ return FALSE;
+ }
+
+ /* success */
+ return TRUE;
+}
+
+/**
* fu_firmware_parse_file:
* @self: A #FuFirmware
* @file: A #GFile
@@ -178,6 +426,11 @@
gchar *buf = NULL;
gsize bufsz = 0;
g_autoptr(GBytes) fw = NULL;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
if (!g_file_load_contents (file, NULL, &buf, &bufsz, NULL, error))
return FALSE;
fw = g_bytes_new_take (buf, bufsz);
@@ -227,6 +480,11 @@
fu_firmware_write_file (FuFirmware *self, GFile *file, GError **error)
{
g_autoptr(GBytes) blob = NULL;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
blob = fu_firmware_write (self, error);
if (blob == NULL)
return FALSE;
@@ -245,7 +503,8 @@
*
* Adds an image to the firmware.
*
- * If an image with the same ID is already present it is replaced.
+ * If %FU_FIRMWARE_FLAG_DEDUPE_ID is set, an image with the same ID is already
+ * present it is replaced.
*
* Since: 1.3.1
**/
@@ -255,10 +514,119 @@
FuFirmwarePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_FIRMWARE (self));
g_return_if_fail (FU_IS_FIRMWARE_IMAGE (img));
+
+ /* dedupe */
+ for (guint i = 0; i < priv->images->len; i++) {
+ FuFirmwareImage *img_tmp = g_ptr_array_index (priv->images, i);
+ if (priv->flags & FU_FIRMWARE_FLAG_DEDUPE_ID) {
+ if (g_strcmp0 (fu_firmware_image_get_id (img_tmp),
+ fu_firmware_image_get_id (img)) == 0) {
+ g_ptr_array_remove_index (priv->images, i);
+ break;
+ }
+ }
+ if (priv->flags & FU_FIRMWARE_FLAG_DEDUPE_IDX) {
+ if (fu_firmware_image_get_idx (img_tmp) ==
+ fu_firmware_image_get_idx (img)) {
+ g_ptr_array_remove_index (priv->images, i);
+ break;
+ }
+ }
+ }
+
g_ptr_array_add (priv->images, g_object_ref (img));
}
/**
+ * fu_firmware_remove_image:
+ * @self: a #FuPlugin
+ * @img: A #FuFirmwareImage
+ * @error: A #GError, or %NULL
+ *
+ * Remove an image from the firmware.
+ *
+ * Returns: %TRUE if the image was removed
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_remove_image (FuFirmware *self, FuFirmwareImage *img, GError **error)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (self);
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), FALSE);
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (img), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (g_ptr_array_remove (priv->images, img))
+ return TRUE;
+
+ /* did not exist */
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "image %s not found in firmware",
+ fu_firmware_image_get_id (img));
+ return FALSE;
+}
+
+/**
+ * fu_firmware_remove_image_by_idx:
+ * @self: a #FuPlugin
+ * @idx: index
+ * @error: A #GError, or %NULL
+ *
+ * Removes the first image from the firmware matching the index.
+ *
+ * Returns: %TRUE if an image was removed
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_remove_image_by_idx (FuFirmware *self, guint64 idx, GError **error)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (self);
+ g_autoptr(FuFirmwareImage) img = NULL;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ img = fu_firmware_get_image_by_idx (self, idx, error);
+ if (img == NULL)
+ return FALSE;
+ g_ptr_array_remove (priv->images, img);
+ return TRUE;
+}
+
+/**
+ * fu_firmware_remove_image_by_id:
+ * @self: a #FuPlugin
+ * @id: (nullable): image ID, e.g. "config"
+ * @error: A #GError, or %NULL
+ *
+ * Removes the first image from the firmware matching the ID.
+ *
+ * Returns: %TRUE if an image was removed
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_remove_image_by_id (FuFirmware *self, const gchar *id, GError **error)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (self);
+ g_autoptr(FuFirmwareImage) img = NULL;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ img = fu_firmware_get_image_by_id (self, id, error);
+ if (img == NULL)
+ return FALSE;
+ g_ptr_array_remove (priv->images, img);
+ return TRUE;
+}
+
+/**
* fu_firmware_get_images:
* @self: a #FuFirmware
*
@@ -370,6 +738,51 @@
}
/**
+ * fu_firmware_get_image_by_checksum:
+ * @self: a #FuPlugin
+ * @checksum: checksum string of any format
+ * @error: A #GError, or %NULL
+ *
+ * Gets the firmware image using the image checksum. The checksum type is guessed
+ * based on the length of the input string.
+ *
+ * Returns: (transfer full): a #FuFirmwareImage, or %NULL if the image is not found
+ *
+ * Since: 1.5.5
+ **/
+FuFirmwareImage *
+fu_firmware_get_image_by_checksum (FuFirmware *self,
+ const gchar *checksum,
+ GError **error)
+{
+ FuFirmwarePrivate *priv = GET_PRIVATE (self);
+ GChecksumType csum_kind;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE (self), NULL);
+ g_return_val_if_fail (checksum != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ csum_kind = fwupd_checksum_guess_kind (checksum);
+ for (guint i = 0; i < priv->images->len; i++) {
+ FuFirmwareImage *img = g_ptr_array_index (priv->images, i);
+ g_autofree gchar *checksum_tmp = NULL;
+
+ /* if this expensive then the subclassed FuFirmwareImage can
+ * cache the result as required */
+ checksum_tmp = fu_firmware_image_get_checksum (img, csum_kind, error);
+ if (checksum_tmp == NULL)
+ return NULL;
+ if (g_strcmp0 (checksum_tmp, checksum) == 0)
+ return g_object_ref (img);
+ }
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "no image with checksum %s found in firmware", checksum);
+ return NULL;
+}
+
+/**
* fu_firmware_get_image_by_idx_bytes:
* @self: a #FuPlugin
* @idx: image index
@@ -464,8 +877,22 @@
/* subclassed type */
fu_common_string_append_kv (str, 0, G_OBJECT_TYPE_NAME (self), NULL);
+ if (priv->flags != FU_FIRMWARE_FLAG_NONE) {
+ g_autoptr(GString) tmp = g_string_new ("");
+ for (guint i = 0; i < 64; i++) {
+ if ((priv->flags & ((guint64) 1 << i)) == 0)
+ continue;
+ g_string_append_printf (tmp, "%s|",
+ fu_firmware_flag_to_string ((guint64) 1 << i));
+ }
+ if (tmp->len > 0)
+ g_string_truncate (tmp, tmp->len - 1);
+ fu_common_string_append_kv (str, 0, "Flags", tmp->str);
+ }
if (priv->version != NULL)
fu_common_string_append_kv (str, 0, "Version", priv->version);
+ if (priv->version_raw != 0x0)
+ fu_common_string_append_kx (str, 0, "VersionRaw", priv->version_raw);
/* vfunc */
if (klass->to_string != NULL)
@@ -538,3 +965,68 @@
fu_firmware_add_image (self, img);
return self;
}
+
+/**
+ * fu_firmware_new_from_gtypes:
+ * @fw: a #GBytes
+ * @flags: a #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM
+ * @error: (nullable): a #GError or %NULL
+ * @...: An array of #GTypes, ending with %G_TYPE_INVALID
+ *
+ * Tries to parse the firmware with each #GType in order.
+ *
+ * Return value: (transfer full) (nullable): A #FuFirmware, or %NULL
+ *
+ * Since: 1.5.6
+ **/
+FuFirmware *
+fu_firmware_new_from_gtypes (GBytes *fw, FwupdInstallFlags flags, GError **error, ...)
+{
+ va_list args;
+ g_autoptr(GArray) gtypes = g_array_new (FALSE, FALSE, sizeof(GType));
+ g_autoptr(GError) error_all = NULL;
+
+ g_return_val_if_fail (fw != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* create array of GTypes */
+ va_start (args, error);
+ for (guint i = 0; ; i++) {
+ GType gtype = va_arg (args, GType);
+ if (gtype == G_TYPE_INVALID)
+ break;
+ g_array_append_val (gtypes, gtype);
+ }
+ va_end (args);
+
+ /* invalid */
+ if (gtypes->len == 0) {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "no GTypes specified");
+ return NULL;
+ }
+
+ /* try each GType in turn */
+ for (guint i = 0; i < gtypes->len; i++) {
+ GType gtype = g_array_index (gtypes, GType, i);
+ g_autoptr(FuFirmware) firmware = g_object_new (gtype, NULL);
+ g_autoptr(GError) error_local = NULL;
+ if (!fu_firmware_parse (firmware, fw, flags, &error_local)) {
+ if (error_all == NULL) {
+ g_propagate_error (&error_all,
+ g_steal_pointer (&error_local));
+ } else {
+ g_prefix_error (&error_all, "%s: ",
+ error_local->message);
+ }
+ continue;
+ }
+ return g_steal_pointer (&firmware);
+ }
+
+ /* failed */
+ g_propagate_error (error, g_steal_pointer (&error_all));
+ return NULL;
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-firmware-common.c fwupd-1.5.8/libfwupdplugin/fu-firmware-common.c
--- fwupd-1.4.5/libfwupdplugin/fu-firmware-common.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-firmware-common.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -10,6 +10,7 @@
#include
+#include "fu-common.h"
#include "fu-firmware-common.h"
/**
@@ -121,3 +122,163 @@
buffer[8] = '\0';
return (guint32) g_ascii_strtoull (buffer, NULL, 16);
}
+
+/**
+ * fu_firmware_strparse_uint4_safe:
+ * @data: destination buffer
+ * @datasz: size of @data, typcally the same as `strlen(data)`
+ * @offset: offset in chars into @data to read
+ * @value: (out) (nullable): parsed value
+ * @error: A #GError or %NULL
+ *
+ * Parses a base 16 number from a string of 1 character in length.
+ * The returned @value will range from from 0 to 0xf.
+ *
+ * Return value: %TRUE if parsed, %FALSE otherwise
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_firmware_strparse_uint4_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint8 *value,
+ GError **error)
+{
+ gchar buffer[2] = { '\0' };
+ if (!fu_memcpy_safe ((guint8 *) buffer, sizeof(buffer), 0x0, /* dst */
+ (const guint8 *) data, datasz, offset, /* src */
+ sizeof(buffer) - 1, error))
+ return FALSE;
+ if (value != NULL)
+ *value = (guint8) g_ascii_strtoull (buffer, NULL, 16);
+ return TRUE;
+}
+
+/**
+ * fu_firmware_strparse_uint8_safe:
+ * @data: destination buffer
+ * @datasz: size of @data, typcally the same as `strlen(data)`
+ * @offset: offset in chars into @data to read
+ * @value: (out) (nullable): parsed value
+ * @error: A #GError or %NULL
+ *
+ * Parses a base 16 number from a string of 2 characters in length.
+ * The returned @value will range from from 0 to 0xff.
+ *
+ * Return value: %TRUE if parsed, %FALSE otherwise
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_firmware_strparse_uint8_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint8 *value,
+ GError **error)
+{
+ gchar buffer[3] = { '\0' };
+ if (!fu_memcpy_safe ((guint8 *) buffer, sizeof(buffer), 0x0, /* dst */
+ (const guint8 *) data, datasz, offset, /* src */
+ sizeof(buffer) - 1, error))
+ return FALSE;
+ if (value != NULL)
+ *value = (guint8) g_ascii_strtoull (buffer, NULL, 16);
+ return TRUE;
+}
+
+/**
+ * fu_firmware_strparse_uint16_safe:
+ * @data: destination buffer
+ * @datasz: size of @data, typcally the same as `strlen(data)`
+ * @offset: offset in chars into @data to read
+ * @value: (out) (nullable): parsed value
+ * @error: A #GError or %NULL
+ *
+ * Parses a base 16 number from a string of 4 characters in length.
+ * The returned @value will range from from 0 to 0xffff.
+ *
+ * Return value: %TRUE if parsed, %FALSE otherwise
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_firmware_strparse_uint16_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint16 *value,
+ GError **error)
+{
+ gchar buffer[5] = { '\0' };
+ if (!fu_memcpy_safe ((guint8 *) buffer, sizeof(buffer), 0x0, /* dst */
+ (const guint8 *) data, datasz, offset, /* src */
+ sizeof(buffer) - 1, error))
+ return FALSE;
+ if (value != NULL)
+ *value = (guint16) g_ascii_strtoull (buffer, NULL, 16);
+ return TRUE;
+}
+
+/**
+ * fu_firmware_strparse_uint24_safe:
+ * @data: destination buffer
+ * @datasz: size of @data, typcally the same as `strlen(data)`
+ * @offset: offset in chars into @data to read
+ * @value: (out) (nullable): parsed value
+ * @error: A #GError or %NULL
+ *
+ * Parses a base 16 number from a string of 6 characters in length.
+ * The returned @value will range from from 0 to 0xffffff.
+ *
+ * Return value: %TRUE if parsed, %FALSE otherwise
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_firmware_strparse_uint24_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint32 *value,
+ GError **error)
+{
+ gchar buffer[7] = { '\0' };
+ if (!fu_memcpy_safe ((guint8 *) buffer, sizeof(buffer), 0x0, /* dst */
+ (const guint8 *) data, datasz, offset, /* src */
+ sizeof(buffer) - 1, error))
+ return FALSE;
+ if (value != NULL)
+ *value = (guint16) g_ascii_strtoull (buffer, NULL, 16);
+ return TRUE;
+}
+
+/**
+ * fu_firmware_strparse_uint32_safe:
+ * @data: destination buffer
+ * @datasz: size of @data, typcally the same as `strlen(data)`
+ * @offset: offset in chars into @data to read
+ * @value: (out) (nullable): parsed value
+ * @error: A #GError or %NULL
+ *
+ * Parses a base 16 number from a string of 8 characters in length.
+ * The returned @value will range from from 0 to 0xffffffff.
+ *
+ * Return value: %TRUE if parsed, %FALSE otherwise
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_firmware_strparse_uint32_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint32 *value,
+ GError **error)
+{
+ gchar buffer[9] = { '\0' };
+ if (!fu_memcpy_safe ((guint8 *) buffer, sizeof(buffer), 0x0, /* dst */
+ (const guint8 *) data, datasz, offset, /* src */
+ sizeof(buffer) - 1, error))
+ return FALSE;
+ if (value != NULL)
+ *value = (guint32) g_ascii_strtoull (buffer, NULL, 16);
+ return TRUE;
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-firmware-common.h fwupd-1.5.8/libfwupdplugin/fu-firmware-common.h
--- fwupd-1.4.5/libfwupdplugin/fu-firmware-common.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-firmware-common.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Richard Hughes
+ * Copyright (C) 2015 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -8,8 +8,39 @@
#include
+G_DEPRECATED_FOR(fu_firmware_strparse_uint4_safe)
guint8 fu_firmware_strparse_uint4 (const gchar *data);
+G_DEPRECATED_FOR(fu_firmware_strparse_uint8_safe)
guint8 fu_firmware_strparse_uint8 (const gchar *data);
+G_DEPRECATED_FOR(fu_firmware_strparse_uint16_safe)
guint16 fu_firmware_strparse_uint16 (const gchar *data);
+G_DEPRECATED_FOR(fu_firmware_strparse_uint24_safe)
guint32 fu_firmware_strparse_uint24 (const gchar *data);
+G_DEPRECATED_FOR(fu_firmware_strparse_uint32_safe)
guint32 fu_firmware_strparse_uint32 (const gchar *data);
+
+gboolean fu_firmware_strparse_uint4_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint8 *value,
+ GError **error);
+gboolean fu_firmware_strparse_uint8_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint8 *value,
+ GError **error);
+gboolean fu_firmware_strparse_uint16_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint16 *value,
+ GError **error);
+gboolean fu_firmware_strparse_uint24_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint32 *value,
+ GError **error);
+gboolean fu_firmware_strparse_uint32_safe (const gchar *data,
+ gsize datasz,
+ gsize offset,
+ guint32 *value,
+ GError **error);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-firmware.h fwupd-1.5.8/libfwupdplugin/fu-firmware.h
--- fwupd-1.4.5/libfwupdplugin/fu-firmware.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-firmware.h 2021-03-31 20:08:32.000000000 +0000
@@ -22,53 +22,110 @@
guint64 addr_start,
guint64 addr_end,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *(*write) (FuFirmware *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void (*to_string) (FuFirmware *self,
guint indent,
GString *str);
gboolean (*tokenize) (FuFirmware *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+ gboolean (*build) (FuFirmware *self,
+ XbNode *n,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
/*< private >*/
- gpointer padding[28];
+ gpointer padding[27];
};
+/**
+ * FuFirmwareFlags:
+ * @FU_FIRMWARE_FLAG_NONE: No flags set
+ * @FU_FIRMWARE_FLAG_DEDUPE_ID: Dedupe imges by ID
+ * @FU_FIRMWARE_FLAG_DEDUPE_IDX: Dedupe imges by IDX
+ * @FU_FIRMWARE_FLAG_HAS_CHECKSUM: Has a CRC or checksum to test internal consistency
+ * @FU_FIRMWARE_FLAG_HAS_VID_PID: Has a vendor or product ID in the firmware
+ *
+ * The firmware flags.
+ **/
+#define FU_FIRMWARE_FLAG_NONE (0u) /* Since: 1.5.0 */
+#define FU_FIRMWARE_FLAG_DEDUPE_ID (1u << 0) /* Since: 1.5.0 */
+#define FU_FIRMWARE_FLAG_DEDUPE_IDX (1u << 1) /* Since: 1.5.0 */
+#define FU_FIRMWARE_FLAG_HAS_CHECKSUM (1u << 2) /* Since: 1.5.6 */
+#define FU_FIRMWARE_FLAG_HAS_VID_PID (1u << 3) /* Since: 1.5.6 */
+typedef guint64 FuFirmwareFlags;
+
+const gchar *fu_firmware_flag_to_string (FuFirmwareFlags flag);
+FuFirmwareFlags fu_firmware_flag_from_string (const gchar *flag);
+
FuFirmware *fu_firmware_new (void);
FuFirmware *fu_firmware_new_from_bytes (GBytes *fw);
+FuFirmware *fu_firmware_new_from_gtypes (GBytes *fw,
+ FwupdInstallFlags flags,
+ GError **error,
+ ...);
gchar *fu_firmware_to_string (FuFirmware *self);
const gchar *fu_firmware_get_version (FuFirmware *self);
void fu_firmware_set_version (FuFirmware *self,
const gchar *version);
+guint64 fu_firmware_get_version_raw (FuFirmware *self);
+void fu_firmware_set_version_raw (FuFirmware *self,
+ guint64 version_raw);
+void fu_firmware_add_flag (FuFirmware *firmware,
+ FuFirmwareFlags flag);
+gboolean fu_firmware_has_flag (FuFirmware *firmware,
+ FuFirmwareFlags flag);
gboolean fu_firmware_tokenize (FuFirmware *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_firmware_build (FuFirmware *self,
+ XbNode *n,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_firmware_parse (FuFirmware *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_firmware_parse_file (FuFirmware *self,
GFile *file,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_firmware_parse_full (FuFirmware *self,
GBytes *fw,
guint64 addr_start,
guint64 addr_end,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_firmware_write (FuFirmware *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_firmware_write_file (FuFirmware *self,
GFile *file,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void fu_firmware_add_image (FuFirmware *self,
FuFirmwareImage *img);
+gboolean fu_firmware_remove_image (FuFirmware *self,
+ FuFirmwareImage *img,
+ GError **error);
+gboolean fu_firmware_remove_image_by_idx (FuFirmware *self,
+ guint64 idx,
+ GError **error);
+gboolean fu_firmware_remove_image_by_id (FuFirmware *self,
+ const gchar *id,
+ GError **error);
GPtrArray *fu_firmware_get_images (FuFirmware *self);
FuFirmwareImage *fu_firmware_get_image_by_id (FuFirmware *self,
const gchar *id,
@@ -82,6 +139,9 @@
GBytes *fu_firmware_get_image_by_idx_bytes (FuFirmware *self,
guint64 idx,
GError **error);
+FuFirmwareImage *fu_firmware_get_image_by_checksum (FuFirmware *self,
+ const gchar *checksum,
+ GError **error);
FuFirmwareImage *fu_firmware_get_image_default (FuFirmware *self,
GError **error);
GBytes *fu_firmware_get_image_default_bytes (FuFirmware *self,
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-firmware-image.c fwupd-1.5.8/libfwupdplugin/fu-firmware-image.c
--- fwupd-1.4.5/libfwupdplugin/fu-firmware-image.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-firmware-image.c 2021-03-31 20:08:32.000000000 +0000
@@ -9,21 +9,25 @@
#include "config.h"
#include "fu-common.h"
+#include "fu-chunk-private.h"
#include "fu-firmware-image-private.h"
/**
- * SECTION:fu-firmware_image
- * @short_description: a firmware_image file
+ * SECTION:fu-firmware-image
+ * @short_description: a firmware image section
*
- * An object that represents a firmware_image file.
+ * An object that represents an image within the firmware file.
*/
typedef struct {
gchar *id;
GBytes *bytes;
guint64 addr;
+ guint64 offset;
guint64 idx;
gchar *version;
+ gchar *filename;
+ GPtrArray *chunks; /* nullable, element-type FuChunk */
} FuFirmwareImagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FuFirmwareImage, fu_firmware_image, G_TYPE_OBJECT)
@@ -61,11 +65,57 @@
{
FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_FIRMWARE_IMAGE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->version, version) == 0)
+ return;
+
g_free (priv->version);
priv->version = g_strdup (version);
}
/**
+ * fu_firmware_image_get_filename:
+ * @self: A #FuFirmwareImage
+ *
+ * Gets an optional filename that represents the image source or destination.
+ *
+ * Returns: a string, or %NULL
+ *
+ * Since: 1.5.0
+ **/
+const gchar *
+fu_firmware_image_get_filename (FuFirmwareImage *self)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), NULL);
+ return priv->filename;
+}
+
+/**
+ * fu_firmware_image_set_filename:
+ * @self: A #FuFirmwareImage
+ * @filename: (nullable): A string filename, or %NULL
+ *
+ * Sets an optional filename that represents the image source or destination.
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_firmware_image_set_filename (FuFirmwareImage *self, const gchar *filename)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_FIRMWARE_IMAGE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->filename, filename) == 0)
+ return;
+
+ g_free (priv->filename);
+ priv->filename = g_strdup (filename);
+}
+
+/**
* fu_firmware_image_set_id:
* @self: a #FuPlugin
* @id: (nullable): image ID, e.g. "config"
@@ -77,6 +127,11 @@
{
FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_FIRMWARE_IMAGE (self));
+
+ /* not changed */
+ if (g_strcmp0 (priv->id, id) == 0)
+ return;
+
g_free (priv->id);
priv->id = g_strdup (id);
}
@@ -135,6 +190,41 @@
}
/**
+ * fu_firmware_image_set_offset:
+ * @self: a #FuPlugin
+ * @offset: integer
+ *
+ * Sets the base offset of the image.
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_firmware_image_set_offset (FuFirmwareImage *self, guint64 offset)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_FIRMWARE_IMAGE (self));
+ priv->offset = offset;
+}
+
+/**
+ * fu_firmware_image_get_offset:
+ * @self: a #FuPlugin
+ *
+ * Gets the base offset of the image.
+ *
+ * Returns: integer
+ *
+ * Since: 1.5.0
+ **/
+guint64
+fu_firmware_image_get_offset (FuFirmwareImage *self)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), G_MAXUINT64);
+ return priv->offset;
+}
+
+/**
* fu_firmware_image_set_idx:
* @self: a #FuPlugin
* @idx: integer
@@ -189,6 +279,250 @@
}
/**
+ * fu_firmware_image_get_bytes:
+ * @self: a #FuPlugin
+ *
+ * Gets the data set using fu_firmware_image_set_bytes().
+ *
+ * This should only really be used by objects subclassing #FuFirmwareImage as
+ * images are normally exported to a file using fu_firmware_image_write().
+ *
+ * Returns: (transfer full): a #GBytes of the data, or %NULL if the bytes is not set
+ *
+ * Since: 1.5.0
+ **/
+GBytes *
+fu_firmware_image_get_bytes (FuFirmwareImage *self)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), NULL);
+ if (priv->bytes == NULL)
+ return NULL;
+ return g_bytes_ref (priv->bytes);
+}
+/**
+ * fu_firmware_image_get_chunks:
+ * @self: a #FuFirmwareImage
+ * @error: A #GError, or %NULL
+ *
+ * Gets the optional image chunks.
+ *
+ * Return value: (transfer container) (element-type FuChunk) (nullable): chunk data, or %NULL
+ *
+ * Since: 1.5.6
+ **/
+GPtrArray *
+fu_firmware_image_get_chunks (FuFirmwareImage *self, GError **error)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* set */
+ if (priv->chunks != NULL)
+ return g_ptr_array_ref (priv->chunks);
+
+ /* lets build something plausible */
+ if (priv->bytes != NULL) {
+ g_autoptr(GPtrArray) chunks = NULL;
+ g_autoptr(FuChunk) chk = NULL;
+ chunks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+ chk = fu_chunk_bytes_new (priv->bytes);
+ fu_chunk_set_idx (chk, priv->idx);
+ fu_chunk_set_address (chk, priv->addr);
+ g_ptr_array_add (chunks, g_steal_pointer (&chk));
+ return g_steal_pointer (&chunks);
+ }
+
+ /* nothing to do */
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "no bytes or chunks found in firmware");
+ return NULL;
+}
+
+/**
+ * fu_firmware_image_add_chunk:
+ * @self: a #FuFirmwareImage
+ * @chk: a #FuChunk
+ *
+ * Adds a chunk to the image.
+ *
+ * Since: 1.5.6
+ **/
+void
+fu_firmware_image_add_chunk (FuFirmwareImage *self, FuChunk *chk)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_FIRMWARE_IMAGE (self));
+ g_return_if_fail (FU_IS_CHUNK (chk));
+ if (priv->chunks == NULL)
+ priv->chunks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+ g_ptr_array_add (priv->chunks, g_object_ref (chk));
+}
+
+/**
+ * fu_firmware_image_get_checksum:
+ * @self: a #FuPlugin
+ * @csum_kind: a #GChecksumType, e.g. %G_CHECKSUM_SHA256
+ * @error: A #GError, or %NULL
+ *
+ * Returns a checksum of the data.
+ *
+ * Returns: (transfer full): a checksum string, or %NULL if the checksum is not available
+ *
+ * Since: 1.5.5
+ **/
+gchar *
+fu_firmware_image_get_checksum (FuFirmwareImage *self,
+ GChecksumType csum_kind,
+ GError **error)
+{
+ FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
+ FuFirmwareImageClass *klass = FU_FIRMWARE_IMAGE_GET_CLASS (self);
+
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* subclassed */
+ if (klass->get_checksum != NULL)
+ return klass->get_checksum (self, csum_kind, error);
+
+ /* internal data */
+ if (priv->bytes == NULL) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "no bytes found in firmware bytes %s",
+ priv->id);
+ return NULL;
+ }
+ return g_compute_checksum_for_bytes (csum_kind, priv->bytes);
+}
+
+/**
+ * fu_firmware_image_parse:
+ * @self: A #FuFirmwareImage
+ * @fw: A #GBytes
+ * @flags: some #FwupdInstallFlags, e.g. %FWUPD_INSTALL_FLAG_FORCE
+ * @error: A #GError, or %NULL
+ *
+ * Parses a firmware image, typically checking image CRCs and/or headers.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_image_parse (FuFirmwareImage *self,
+ GBytes *fw,
+ FwupdInstallFlags flags,
+ GError **error)
+{
+ FuFirmwareImageClass *klass = FU_FIRMWARE_IMAGE_GET_CLASS (self);
+
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), FALSE);
+ g_return_val_if_fail (fw != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* subclassed */
+ if (klass->parse != NULL)
+ return klass->parse (self, fw, flags, error);
+
+ /* just add entire blob */
+ fu_firmware_image_set_bytes (self, fw);
+ return TRUE;
+}
+
+/**
+ * fu_firmware_image_build:
+ * @self: A #FuFirmwareImage
+ * @n: A #XbNode
+ * @error: A #GError, or %NULL
+ *
+ * Builds a firmware image from an XML manifest.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.5.0
+ **/
+gboolean
+fu_firmware_image_build (FuFirmwareImage *self, XbNode *n, GError **error)
+{
+ FuFirmwareImageClass *klass = FU_FIRMWARE_IMAGE_GET_CLASS (self);
+ guint64 tmpval;
+ const gchar *tmp;
+ g_autoptr(GPtrArray) chunks = NULL;
+ g_autoptr(XbNode) data = NULL;
+
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), FALSE);
+ g_return_val_if_fail (XB_IS_NODE (n), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ tmp = xb_node_query_text (n, "version", NULL);
+ if (tmp != NULL)
+ fu_firmware_image_set_version (self, tmp);
+ tmp = xb_node_query_text (n, "id", NULL);
+ if (tmp != NULL)
+ fu_firmware_image_set_id (self, tmp);
+ tmpval = xb_node_query_text_as_uint (n, "idx", NULL);
+ if (tmpval != G_MAXUINT64)
+ fu_firmware_image_set_idx (self, tmpval);
+ tmpval = xb_node_query_text_as_uint (n, "addr", NULL);
+ if (tmpval != G_MAXUINT64)
+ fu_firmware_image_set_addr (self, tmpval);
+ tmpval = xb_node_query_text_as_uint (n, "offset", NULL);
+ if (tmpval != G_MAXUINT64)
+ fu_firmware_image_set_offset (self, tmpval);
+ tmp = xb_node_query_text (n, "filename", NULL);
+ if (tmp != NULL) {
+ g_autoptr(GBytes) blob = NULL;
+ blob = fu_common_get_contents_bytes (tmp, error);
+ if (blob == NULL)
+ return FALSE;
+ fu_firmware_image_set_bytes (self, blob);
+ fu_firmware_image_set_filename (self, tmp);
+ }
+ data = xb_node_query_first (n, "data", NULL);
+ if (data != NULL && xb_node_get_text (data) != NULL) {
+ gsize bufsz = 0;
+ g_autofree guchar *buf = NULL;
+ g_autoptr(GBytes) blob = NULL;
+ buf = g_base64_decode (xb_node_get_text (data), &bufsz);
+ blob = g_bytes_new (buf, bufsz);
+ fu_firmware_image_set_bytes (self, blob);
+ } else if (data != NULL) {
+ g_autoptr(GBytes) blob = NULL;
+ blob = g_bytes_new (NULL, 0);
+ fu_firmware_image_set_bytes (self, blob);
+ }
+
+ /* optional chunks */
+ chunks = xb_node_query (n, "chunks/chunk", 0, NULL);
+ if (chunks != NULL) {
+ for (guint i = 0; i < chunks->len; i++) {
+ XbNode *c = g_ptr_array_index (chunks, i);
+ g_autoptr(FuChunk) chk = fu_chunk_bytes_new (NULL);
+ fu_chunk_set_idx (chk, i);
+ if (!fu_chunk_build (chk, c, error))
+ return FALSE;
+ fu_firmware_image_add_chunk (self, chk);
+ }
+ }
+
+ /* subclassed */
+ if (klass->build != NULL) {
+ if (!klass->build (self, n, error))
+ return FALSE;
+ }
+
+ /* success */
+ return TRUE;
+}
+
+/**
* fu_firmware_image_write:
* @self: a #FuPlugin
* @error: A #GError, or %NULL
@@ -215,15 +549,22 @@
if (klass->write != NULL)
return klass->write (self, error);
- /* fall back to what was set manually */
- if (priv->bytes == NULL) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_NOT_FOUND,
- "no bytes found in firmware bytes %s", priv->id);
- return NULL;
+ /* set */
+ if (priv->bytes != NULL)
+ return g_bytes_ref (priv->bytes);
+
+ /* fall back to chunks */
+ if (priv->chunks != NULL && priv->chunks->len == 1) {
+ FuChunk *chk = g_ptr_array_index (priv->chunks, 0);
+ return fu_chunk_get_bytes (chk);
}
- return g_bytes_ref (priv->bytes);
+
+ /* failed */
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "no bytes found in firmware bytes %s", priv->id);
+ return NULL;
}
/**
@@ -253,6 +594,9 @@
gsize chunk_left;
guint64 offset;
+ g_return_val_if_fail (FU_IS_FIRMWARE_IMAGE (self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
/* check address requested is larger than base address */
if (address < priv->addr) {
g_set_error (error,
@@ -277,11 +621,18 @@
/* if we have less data than requested */
chunk_left = g_bytes_get_size (priv->bytes) - offset;
- if (chunk_sz_max > chunk_left)
- return g_bytes_new_from_bytes (priv->bytes, offset, chunk_left);
+ if (chunk_sz_max > chunk_left) {
+ return fu_common_bytes_new_offset (priv->bytes,
+ offset,
+ chunk_left,
+ error);
+ }
/* check chunk */
- return g_bytes_new_from_bytes (priv->bytes, offset, chunk_sz_max);
+ return fu_common_bytes_new_offset (priv->bytes,
+ offset,
+ chunk_sz_max,
+ error);
}
void
@@ -297,13 +648,25 @@
fu_common_string_append_kx (str, idt, "Index", priv->idx);
if (priv->addr != 0x0)
fu_common_string_append_kx (str, idt, "Address", priv->addr);
+ if (priv->offset != 0x0)
+ fu_common_string_append_kx (str, idt, "Offset", priv->offset);
if (priv->version != NULL)
fu_common_string_append_kv (str, idt, "Version", priv->version);
+ if (priv->filename != NULL)
+ fu_common_string_append_kv (str, idt, "Filename", priv->filename);
if (priv->bytes != NULL) {
fu_common_string_append_kx (str, idt, "Data",
g_bytes_get_size (priv->bytes));
}
+ /* add chunks */
+ if (priv->chunks != NULL) {
+ for (guint i = 0; i < priv->chunks->len; i++) {
+ FuChunk *chk = g_ptr_array_index (priv->chunks, i);
+ fu_chunk_add_string (chk, idt + 1, str);
+ }
+ }
+
/* vfunc */
if (klass->to_string != NULL)
klass->to_string (self, idt, str);
@@ -339,8 +702,11 @@
FuFirmwareImagePrivate *priv = GET_PRIVATE (self);
g_free (priv->id);
g_free (priv->version);
+ g_free (priv->filename);
if (priv->bytes != NULL)
g_bytes_unref (priv->bytes);
+ if (priv->chunks != NULL)
+ g_ptr_array_unref (priv->chunks);
G_OBJECT_CLASS (fu_firmware_image_parent_class)->finalize (object);
}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-firmware-image.h fwupd-1.5.8/libfwupdplugin/fu-firmware-image.h
--- fwupd-1.4.5/libfwupdplugin/fu-firmware-image.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-firmware-image.h 2021-03-31 20:08:32.000000000 +0000
@@ -8,6 +8,9 @@
#include
#include
+#include
+
+#include "fu-chunk.h"
#define FU_TYPE_FIRMWARE_IMAGE (fu_firmware_image_get_type ())
G_DECLARE_DERIVABLE_TYPE (FuFirmwareImage, fu_firmware_image, FU, FIRMWARE_IMAGE, GObject)
@@ -18,14 +21,24 @@
gboolean (*parse) (FuFirmwareImage *self,
GBytes *fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
void (*to_string) (FuFirmwareImage *self,
guint idt,
GString *str);
GBytes *(*write) (FuFirmwareImage *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+ gboolean (*build) (FuFirmwareImage *self,
+ XbNode *n,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+ gchar *(*get_checksum)(FuFirmwareImage *self,
+ GChecksumType csum_kind,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
/*< private >*/
- gpointer padding[28];
+ gpointer padding[26];
};
#define FU_FIRMWARE_IMAGE_ID_PAYLOAD "payload"
@@ -38,20 +51,45 @@
const gchar *fu_firmware_image_get_version (FuFirmwareImage *self);
void fu_firmware_image_set_version (FuFirmwareImage *self,
const gchar *version);
+const gchar *fu_firmware_image_get_filename (FuFirmwareImage *self);
+void fu_firmware_image_set_filename (FuFirmwareImage *self,
+ const gchar *filename);
const gchar *fu_firmware_image_get_id (FuFirmwareImage *self);
void fu_firmware_image_set_id (FuFirmwareImage *self,
const gchar *id);
guint64 fu_firmware_image_get_addr (FuFirmwareImage *self);
void fu_firmware_image_set_addr (FuFirmwareImage *self,
guint64 addr);
+guint64 fu_firmware_image_get_offset (FuFirmwareImage *self);
+void fu_firmware_image_set_offset (FuFirmwareImage *self,
+ guint64 offset);
guint64 fu_firmware_image_get_idx (FuFirmwareImage *self);
void fu_firmware_image_set_idx (FuFirmwareImage *self,
guint64 idx);
+GBytes *fu_firmware_image_get_bytes (FuFirmwareImage *self);
void fu_firmware_image_set_bytes (FuFirmwareImage *self,
GBytes *bytes);
-GBytes *fu_firmware_image_write (FuFirmwareImage *self,
+void fu_firmware_image_add_chunk (FuFirmwareImage *self,
+ FuChunk *chk);
+GPtrArray *fu_firmware_image_get_chunks (FuFirmwareImage *self,
+ GError **error);
+gchar *fu_firmware_image_get_checksum (FuFirmwareImage *self,
+ GChecksumType csum_kind,
GError **error);
+gboolean fu_firmware_image_parse (FuFirmwareImage *self,
+ GBytes *fw,
+ FwupdInstallFlags flags,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_firmware_image_build (FuFirmwareImage *self,
+ XbNode *n,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GBytes *fu_firmware_image_write (FuFirmwareImage *self,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_firmware_image_write_chunk (FuFirmwareImage *self,
guint64 address,
guint64 chunk_sz_max,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-fmap-firmware.c fwupd-1.5.8/libfwupdplugin/fu-fmap-firmware.c
--- fwupd-1.4.5/libfwupdplugin/fu-fmap-firmware.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-fmap-firmware.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2020 Benson Leung
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#include
+
+#include "fu-common.h"
+#include "fu-fmap-firmware.h"
+
+#define FMAP_SIGNATURE "__FMAP__"
+#define FMAP_AREANAME "FMAP"
+
+typedef struct {
+ guint64 base;
+ gsize offset;
+} FuFmapFirmwarePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (FuFmapFirmware, fu_fmap_firmware, FU_TYPE_FIRMWARE)
+#define GET_PRIVATE(o) (fu_fmap_firmware_get_instance_private (o))
+
+static gboolean
+fu_fmap_firmware_find_offset (FuFmapFirmware *self,
+ const guint8 *buf, gsize bufsz,
+ GError **error)
+{
+#ifdef HAVE_MEMMEM
+ FuFmapFirmwarePrivate *priv = GET_PRIVATE (self);
+ const guint8 *tmp;
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+
+ /* trust glibc to do a binary or linear search as appropriate */
+ tmp = memmem (buf, bufsz, FMAP_SIGNATURE, 8);
+ if (tmp == NULL) {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "fmap header not found");
+ return FALSE;
+ }
+ priv->offset = tmp - buf;
+ return TRUE;
+#else
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "memmem() not available");
+ return FALSE;
+#endif
+}
+
+static void
+fu_fmap_firmware_to_string (FuFirmware *firmware, guint idt, GString *str)
+{
+ FuFmapFirmware *self = FU_FMAP_FIRMWARE (firmware);
+ FuFmapFirmwarePrivate *priv = GET_PRIVATE (self);
+ if (priv->offset > 0)
+ fu_common_string_append_kx (str, idt, "Offset", priv->offset);
+ fu_common_string_append_kx (str, idt, "Base", priv->base);
+}
+
+static gboolean
+fu_fmap_firmware_parse (FuFirmware *firmware,
+ GBytes *fw,
+ guint64 addr_start,
+ guint64 addr_end,
+ FwupdInstallFlags flags,
+ GError **error)
+{
+ FuFmapFirmware *self = FU_FMAP_FIRMWARE (firmware);
+ FuFmapFirmwarePrivate *priv = GET_PRIVATE (self);
+ FuFmapFirmwareClass *klass_firmware = FU_FMAP_FIRMWARE_GET_CLASS (firmware);
+ gsize bufsz;
+ const guint8 *buf = g_bytes_get_data (fw, &bufsz);
+ gsize offset = 0;
+ FuFmap fmap;
+
+ /* corrupt */
+ if (g_bytes_get_size (fw) < sizeof (FuFmap)) {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "firmware too small for fmap");
+ return FALSE;
+ }
+
+ /* only search for the fmap signature if not fuzzing */
+ if ((flags & FWUPD_INSTALL_FLAG_NO_SEARCH) == 0) {
+ if (!fu_fmap_firmware_find_offset (self, buf, bufsz, error))
+ return FALSE;
+ }
+
+ /* load header */
+ if (!fu_memcpy_safe ((guint8 *) &fmap, sizeof(fmap), 0x0, /* dst */
+ buf, bufsz, priv->offset, /* src */
+ sizeof(fmap), error))
+ return FALSE;
+ priv->base = GUINT64_FROM_LE (fmap.base);
+
+ if (GUINT32_FROM_LE (fmap.size) != bufsz) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "file size incorrect, expected 0x%04x got 0x%04x",
+ (guint) fmap.size,
+ (guint) bufsz);
+ return FALSE;
+ }
+ if (GUINT16_FROM_LE (fmap.nareas) < 1) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "number of areas too small, got %" G_GUINT16_FORMAT,
+ GUINT16_FROM_LE (fmap.nareas));
+ return FALSE;
+ }
+ offset = priv->offset + sizeof(fmap);
+
+ for (gsize i = 0; i < GUINT16_FROM_LE (fmap.nareas); i++) {
+ FuFmapArea area;
+ g_autoptr(FuFirmwareImage) img = NULL;
+ g_autoptr(GBytes) bytes = NULL;
+ g_autofree gchar *area_name = NULL;
+
+ /* load area */
+ if (!fu_memcpy_safe ((guint8 *) &area, sizeof(area), 0x0, /* dst */
+ buf, bufsz, offset, /* src */
+ sizeof(area), error))
+ return FALSE;
+
+ /* skip */
+ if (area.size == 0)
+ continue;
+
+ img = fu_firmware_image_new (NULL);
+ bytes = fu_common_bytes_new_offset (fw,
+ (gsize) GUINT32_FROM_LE (area.offset),
+ (gsize) GUINT32_FROM_LE (area.size),
+ error);
+ if (bytes == NULL)
+ return FALSE;
+ area_name = g_strndup ((const gchar *) area.name, FU_FMAP_FIRMWARE_STRLEN);
+ fu_firmware_image_set_id (img, area_name);
+ fu_firmware_image_set_idx (img, i + 1);
+ fu_firmware_image_set_addr (img, GUINT32_FROM_LE (area.offset));
+ fu_firmware_image_set_bytes (img, bytes);
+ fu_firmware_add_image (firmware, img);
+
+ if (g_strcmp0 (area_name, FMAP_AREANAME) == 0) {
+ g_autofree gchar *version = NULL;
+ version = g_strdup_printf ("%d.%d",
+ fmap.ver_major,
+ fmap.ver_minor);
+ fu_firmware_image_set_version (img, version);
+ }
+ offset += sizeof(area);
+ }
+
+ /* subclassed */
+ if (klass_firmware->parse != NULL) {
+ if (!klass_firmware->parse (firmware, fw, addr_start, addr_end, flags, error))
+ return FALSE;
+ }
+
+ /* success */
+ return TRUE;
+}
+
+static GBytes *
+fu_fmap_firmware_write (FuFirmware *firmware, GError **error)
+{
+ FuFmapFirmware *self = FU_FMAP_FIRMWARE (firmware);
+ FuFmapFirmwarePrivate *priv = GET_PRIVATE (self);
+ gsize total_sz;
+ gsize offset;
+ g_autoptr(GPtrArray) images = fu_firmware_get_images (firmware);
+ g_autoptr(GByteArray) buf = g_byte_array_new ();
+ FuFmap hdr = {
+ .signature = { FMAP_SIGNATURE },
+ .ver_major = 0x1,
+ .ver_minor = 0x1,
+ .base = GUINT64_TO_LE (priv->base),
+ .size = 0x0,
+ .name = "",
+ .nareas = GUINT16_TO_LE (images->len),
+ };
+
+ /* pad to offset */
+ if (priv->offset > 0)
+ fu_byte_array_set_size (buf, priv->offset);
+
+ /* add header */
+ total_sz = offset = sizeof(hdr) + (sizeof(FuFmapArea) * images->len);
+ for (guint i = 0; i < images->len; i++) {
+ FuFirmwareImage *img = g_ptr_array_index (images, i);
+ g_autoptr(GBytes) fw = fu_firmware_image_get_bytes (img);
+ total_sz += g_bytes_get_size (fw);
+ }
+ hdr.size = GUINT32_TO_LE (priv->offset + total_sz);
+ g_byte_array_append (buf, (const guint8 *) &hdr, sizeof(hdr));
+
+ /* add each area */
+ for (guint i = 0; i < images->len; i++) {
+ FuFirmwareImage *img = g_ptr_array_index (images, i);
+ const gchar *id = fu_firmware_image_get_id (img);
+ g_autoptr(GBytes) fw = fu_firmware_image_get_bytes (img);
+ FuFmapArea area = {
+ .offset = GUINT32_TO_LE (priv->offset + offset),
+ .size = GUINT32_TO_LE (g_bytes_get_size (fw)),
+ .name = { "" },
+ .flags = 0x0,
+ };
+ if (id != NULL)
+ strncpy ((gchar *) area.name, id, sizeof(area.name) - 1);
+ g_byte_array_append (buf, (const guint8 *) &area, sizeof(area));
+ offset += g_bytes_get_size (fw);
+ }
+
+ /* add the images */
+ for (guint i = 0; i < images->len; i++) {
+ FuFirmwareImage *img = g_ptr_array_index (images, i);
+ g_autoptr(GBytes) fw = fu_firmware_image_get_bytes (img);
+ g_byte_array_append (buf,
+ g_bytes_get_data (fw, NULL),
+ g_bytes_get_size (fw));
+ }
+
+ /* success */
+ return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
+}
+
+static gboolean
+fu_fmap_firmware_build (FuFirmware *firmware, XbNode *n, GError **error)
+{
+ FuFmapFirmware *self = FU_FMAP_FIRMWARE (firmware);
+ FuFmapFirmwarePrivate *priv = GET_PRIVATE (self);
+ guint64 tmp;
+
+ /* simple properties */
+ tmp = xb_node_query_text_as_uint (n, "base", NULL);
+ if (tmp != G_MAXUINT64)
+ priv->base = tmp;
+ tmp = xb_node_query_text_as_uint (n, "offset", NULL);
+ if (tmp != G_MAXUINT64)
+ priv->offset = tmp;
+
+ /* success */
+ return TRUE;
+}
+
+static void
+fu_fmap_firmware_init (FuFmapFirmware *self)
+{
+}
+
+static void
+fu_fmap_firmware_class_init (FuFmapFirmwareClass *klass)
+{
+ FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
+ klass_firmware->to_string = fu_fmap_firmware_to_string;
+ klass_firmware->parse = fu_fmap_firmware_parse;
+ klass_firmware->write = fu_fmap_firmware_write;
+ klass_firmware->build = fu_fmap_firmware_build;
+}
+
+/**
+ * fu_fmap_firmware_new
+ *
+ * Creates a new #FuFirmware of sub type fmap
+ *
+ * Since: 1.5.0
+ **/
+FuFirmware *
+fu_fmap_firmware_new (void)
+{
+ return FU_FIRMWARE (g_object_new (FU_TYPE_FMAP_FIRMWARE, NULL));
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-fmap-firmware.h fwupd-1.5.8/libfwupdplugin/fu-fmap-firmware.h
--- fwupd-1.4.5/libfwupdplugin/fu-fmap-firmware.h 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-fmap-firmware.h 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 Benson Leung
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "fu-firmware.h"
+
+#define FU_FMAP_FIRMWARE_STRLEN 32 /* maximum length for strings, */
+ /* including null-terminator */
+
+#define FU_TYPE_FMAP_FIRMWARE (fu_fmap_firmware_get_type ())
+G_DECLARE_DERIVABLE_TYPE (FuFmapFirmware, fu_fmap_firmware, FU, FMAP_FIRMWARE, FuFirmware)
+
+struct _FuFmapFirmwareClass
+{
+ FuFirmwareClass parent_class;
+ gboolean (*parse) (FuFirmware *self,
+ GBytes *fw,
+ guint64 addr_start,
+ guint64 addr_end,
+ FwupdInstallFlags flags,
+ GError **error);
+ /*< private >*/
+ gpointer padding[14];
+};
+
+/* mapping of volatile and static regions in firmware binary */
+typedef struct __attribute__((packed)) {
+ guint32 offset; /* offset relative to base */
+ guint32 size; /* size in bytes */
+ guint8 name[FU_FMAP_FIRMWARE_STRLEN]; /* descriptive name */
+ guint16 flags; /* flags for this area */
+} FuFmapArea;
+
+typedef struct __attribute__((packed)) {
+ guint8 signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */
+ guint8 ver_major; /* major version */
+ guint8 ver_minor; /* minor version */
+ guint64 base; /* address of the firmware binary */
+ guint32 size; /* size of firmware binary in bytes */
+ guint8 name[FU_FMAP_FIRMWARE_STRLEN]; /* name of this firmware binary */
+ guint16 nareas; /* number of areas described by
+ areas[] below */
+ FuFmapArea areas[];
+} FuFmap;
+
+FuFirmware *fu_fmap_firmware_new (void);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-fuzzer-firmware.c.in fwupd-1.5.8/libfwupdplugin/fu-fuzzer-firmware.c.in
--- fwupd-1.4.5/libfwupdplugin/fu-fuzzer-firmware.c.in 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-fuzzer-firmware.c.in 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+#include "@INCLUDE@"
+
+int
+LLVMFuzzerTestOneInput (const guint8 *data, gsize size)
+{
+ g_autoptr(FuFirmware) firmware = @FIRMWARENEW@ ();
+ g_autoptr(GBytes) fw = g_bytes_new (data, size);
+ gboolean ret = fu_firmware_parse (firmware, fw, FWUPD_INSTALL_FLAG_NONE, NULL);
+ if (!ret && fu_firmware_has_flag (firmware, FU_FIRMWARE_FLAG_HAS_CHECKSUM)) {
+ ret = fu_firmware_parse (firmware, fw,
+ FWUPD_INSTALL_FLAG_NO_SEARCH |
+ FWUPD_INSTALL_FLAG_IGNORE_VID_PID |
+ FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM,
+ NULL);
+ }
+ if (ret) {
+ g_autofree gchar *str = fu_firmware_to_string (firmware);
+ g_autoptr(GBytes) fw2 = fu_firmware_write (firmware, NULL);
+ g_print ("%s", str);
+ if (fw2 != NULL) {
+ g_print ("[%" G_GSIZE_FORMAT " bytes]\n",
+ g_bytes_get_size (fw2));
+ }
+ }
+ return 0;
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-fuzzer-main.c fwupd-1.5.8/libfwupdplugin/fu-fuzzer-main.c
--- fwupd-1.4.5/libfwupdplugin/fu-fuzzer-main.c 1970-01-01 00:00:00.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-fuzzer-main.c 2021-03-31 20:08:32.000000000 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 Richard Hughes
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include
+
+__attribute__((weak)) extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
+__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+
+int
+main (int argc, char **argv)
+{
+ g_assert (LLVMFuzzerTestOneInput != NULL);
+ if (LLVMFuzzerInitialize != NULL)
+ LLVMFuzzerInitialize (&argc, &argv);
+ for (int i = 1; i < argc; i++) {
+ gsize bufsz = 0;
+ g_autofree gchar *buf = NULL;
+ g_autoptr(GError) error = NULL;
+ g_printerr ("Running: %s\n", argv[i]);
+ if (!g_file_get_contents (argv[i], &buf, &bufsz, &error)) {
+ g_printerr ("Failed to load: %s\n", error->message);
+ continue;
+ }
+ LLVMFuzzerTestOneInput ((const guint8 *)buf, bufsz);
+ g_printerr ("Done\n");
+ }
+}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-hid-device.c fwupd-1.5.8/libfwupdplugin/fu-hid-device.c
--- fwupd-1.4.5/libfwupdplugin/fu-hid-device.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-hid-device.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2020 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -17,6 +17,8 @@
#define FU_HID_REPORT_TYPE_OUTPUT 0x02
#define FU_HID_REPORT_TYPE_FEATURE 0x03
+#define FU_HID_DEVICE_RETRIES 10
+
/**
* SECTION:fu-hid-device
* @short_description: a HID device
@@ -31,6 +33,7 @@
FuUsbDevice *usb_device;
guint8 interface;
gboolean interface_autodetect;
+ FuHidDeviceFlags flags;
} FuHidDevicePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FuHidDevice, fu_hid_device, FU_TYPE_USB_DEVICE)
@@ -75,12 +78,18 @@
}
static gboolean
-fu_hid_device_open (FuUsbDevice *device, GError **error)
+fu_hid_device_open (FuDevice *device, GError **error)
{
FuHidDevice *self = FU_HID_DEVICE (device);
FuHidDeviceClass *klass = FU_HID_DEVICE_GET_CLASS (device);
+#ifdef HAVE_GUSB
FuHidDevicePrivate *priv = GET_PRIVATE (self);
- GUsbDevice *usb_device = fu_usb_device_get_dev (device);
+ GUsbDeviceClaimInterfaceFlags flags = 0;
+ GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device));
+
+ /* FuUsbDevice->open */
+ if (!FU_DEVICE_CLASS (fu_hid_device_parent_class)->open (device, error))
+ return FALSE;
/* auto-detect */
if (priv->interface_autodetect) {
@@ -107,15 +116,17 @@
}
/* claim */
- if (!g_usb_device_claim_interface (usb_device, priv->interface,
- G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
- error)) {
+ if ((priv->flags & FU_HID_DEVICE_FLAG_NO_KERNEL_UNBIND) == 0)
+ flags |= G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER;
+ if (!g_usb_device_claim_interface (usb_device, priv->interface, flags, error)) {
g_prefix_error (error, "failed to claim HID interface: ");
return FALSE;
}
+#endif
/* subclassed */
if (klass->open != NULL) {
+ g_warning ("FuHidDevice->open is deprecated!");
if (!klass->open (self, error))
return FALSE;
}
@@ -125,29 +136,47 @@
}
static gboolean
-fu_hid_device_close (FuUsbDevice *device, GError **error)
+fu_hid_device_close (FuDevice *device, GError **error)
{
FuHidDevice *self = FU_HID_DEVICE (device);
FuHidDeviceClass *klass = FU_HID_DEVICE_GET_CLASS (device);
+#ifdef HAVE_GUSB
FuHidDevicePrivate *priv = GET_PRIVATE (self);
- GUsbDevice *usb_device = fu_usb_device_get_dev (device);
+ GUsbDeviceClaimInterfaceFlags flags = 0;
+ GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device));
+ g_autoptr(GError) error_local = NULL;
+#endif
/* subclassed */
if (klass->close != NULL) {
+ g_warning ("FuHidDevice->close is deprecated!");
if (!klass->close (self, error))
return FALSE;
}
+#ifdef HAVE_GUSB
/* release */
- if (!g_usb_device_release_interface (usb_device, priv->interface,
- G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
- error)) {
- g_prefix_error (error, "failed to release HID interface: ");
+ if ((priv->flags & FU_HID_DEVICE_FLAG_NO_KERNEL_REBIND) == 0)
+ flags |= G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER;
+ if (!g_usb_device_release_interface (usb_device, priv->interface, flags, &error_local)) {
+ if (g_error_matches (error_local,
+ G_USB_DEVICE_ERROR,
+ G_USB_DEVICE_ERROR_NO_DEVICE) ||
+ g_error_matches (error_local,
+ G_USB_DEVICE_ERROR,
+ G_USB_DEVICE_ERROR_INTERNAL)) {
+ g_debug ("ignoring: %s", error_local->message);
+ return TRUE;
+ }
+ g_propagate_prefixed_error (error,
+ g_steal_pointer (&error_local),
+ "failed to release HID interface: ");
return FALSE;
}
+#endif
- /* success */
- return TRUE;
+ /* FuUsbDevice->close */
+ return FU_DEVICE_CLASS (fu_hid_device_parent_class)->close (device, error);
}
/**
@@ -191,45 +220,52 @@
}
/**
- * fu_hid_device_set_report:
+ * fu_hid_device_add_flag:
* @self: A #FuHidDevice
- * @value: low byte of wValue
- * @buf: (nullable): a mutable buffer of data to send
- * @bufsz: Size of @buf
- * @timeout: timeout in ms
- * @flags: #FuHidDeviceFlags e.g. %FU_HID_DEVICE_FLAG_ALLOW_TRUNC
- * @error: a #GError or %NULL
+ * @flag: #FuHidDeviceFlags, e.g. %FU_HID_DEVICE_FLAG_RETRY_FAILURE
*
- * Calls SetReport on the hardware.
+ * Adds a flag to be used for all set and get report messages.
*
- * Returns: %TRUE for success
- *
- * Since: 1.4.0
+ * Since: 1.5.2
**/
-gboolean
-fu_hid_device_set_report (FuHidDevice *self,
- guint8 value,
- guint8 *buf,
- gsize bufsz,
- guint timeout,
- FuHidDeviceFlags flags,
- GError **error)
+void
+fu_hid_device_add_flag (FuHidDevice *self, FuHidDeviceFlags flag)
+{
+ FuHidDevicePrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_HID_DEVICE (self));
+ priv->flags |= flag;
+}
+
+typedef struct {
+ guint8 value;
+ guint8 *buf;
+ gsize bufsz;
+ guint timeout;
+ FuHidDeviceFlags flags;
+} FuHidDeviceRetryHelper;
+
+static gboolean
+fu_hid_device_set_report_internal (FuHidDevice *self,
+ FuHidDeviceRetryHelper *helper,
+ GError **error)
{
+#ifdef HAVE_GUSB
FuHidDevicePrivate *priv = GET_PRIVATE (self);
GUsbDevice *usb_device;
gsize actual_len = 0;
- guint16 wvalue = (FU_HID_REPORT_TYPE_OUTPUT << 8) | value;
+ guint16 wvalue = (FU_HID_REPORT_TYPE_OUTPUT << 8) | helper->value;
/* special case */
- if (flags & FU_HID_DEVICE_FLAG_IS_FEATURE)
- wvalue = (FU_HID_REPORT_TYPE_FEATURE << 8) | value;
-
- g_return_val_if_fail (FU_HID_DEVICE (self), FALSE);
- g_return_val_if_fail (buf != NULL, FALSE);
- g_return_val_if_fail (bufsz != 0, FALSE);
+ if (helper->flags & FU_HID_DEVICE_FLAG_IS_FEATURE)
+ wvalue = (FU_HID_REPORT_TYPE_FEATURE << 8) | helper->value;
- if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL)
- fu_common_dump_raw (G_LOG_DOMAIN, "HID::SetReport", buf, bufsz);
+ if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL) {
+ g_autofree gchar *title = NULL;
+ title = g_strdup_printf ("HID::SetReport [wValue=0x%04x ,wIndex=%u]",
+ wvalue, priv->interface);
+ fu_common_dump_raw (G_LOG_DOMAIN, title,
+ helper->buf, helper->bufsz);
+ }
usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
if (!g_usb_device_control_transfer (usb_device,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
@@ -237,24 +273,33 @@
G_USB_DEVICE_RECIPIENT_INTERFACE,
FU_HID_REPORT_SET,
wvalue, priv->interface,
- buf, bufsz,
+ helper->buf, helper->bufsz,
&actual_len,
- timeout,
+ helper->timeout,
NULL, error)) {
g_prefix_error (error, "failed to SetReport: ");
return FALSE;
}
- if ((flags & FU_HID_DEVICE_FLAG_ALLOW_TRUNC) == 0 && actual_len != bufsz) {
+ if ((helper->flags & FU_HID_DEVICE_FLAG_ALLOW_TRUNC) == 0 && actual_len != helper->bufsz) {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"wrote %" G_GSIZE_FORMAT ", requested %" G_GSIZE_FORMAT " bytes",
- actual_len, bufsz);
+ actual_len, helper->bufsz);
return FALSE;
}
+#endif
return TRUE;
}
+static gboolean
+fu_hid_device_set_report_internal_cb (FuDevice *device, gpointer user_data, GError **error)
+{
+ FuHidDevice *self = FU_HID_DEVICE (device);
+ FuHidDeviceRetryHelper *helper = (FuHidDeviceRetryHelper *) user_data;
+ return fu_hid_device_set_report_internal (self, helper, error);
+}
+
/**
- * fu_hid_device_get_report:
+ * fu_hid_device_set_report:
* @self: A #FuHidDevice
* @value: low byte of wValue
* @buf: (nullable): a mutable buffer of data to send
@@ -263,14 +308,14 @@
* @flags: #FuHidDeviceFlags e.g. %FU_HID_DEVICE_FLAG_ALLOW_TRUNC
* @error: a #GError or %NULL
*
- * Calls GetReport on the hardware.
+ * Calls SetReport on the hardware.
*
* Returns: %TRUE for success
*
* Since: 1.4.0
**/
gboolean
-fu_hid_device_get_report (FuHidDevice *self,
+fu_hid_device_set_report (FuHidDevice *self,
guint8 value,
guint8 *buf,
gsize bufsz,
@@ -278,21 +323,56 @@
FuHidDeviceFlags flags,
GError **error)
{
+ FuHidDeviceRetryHelper helper;
FuHidDevicePrivate *priv = GET_PRIVATE (self);
- GUsbDevice *usb_device;
- gsize actual_len = 0;
- guint16 wvalue = (FU_HID_REPORT_TYPE_INPUT << 8) | value;
g_return_val_if_fail (FU_HID_DEVICE (self), FALSE);
g_return_val_if_fail (buf != NULL, FALSE);
g_return_val_if_fail (bufsz != 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* create helper */
+ helper.value = value;
+ helper.buf = buf;
+ helper.bufsz = bufsz;
+ helper.timeout = timeout;
+ helper.flags = priv->flags | flags;
/* special case */
- if (flags & FU_HID_DEVICE_FLAG_IS_FEATURE)
- wvalue = (FU_HID_REPORT_TYPE_FEATURE << 8) | value;
+ if (flags & FU_HID_DEVICE_FLAG_RETRY_FAILURE) {
+ return fu_device_retry (FU_DEVICE (self),
+ fu_hid_device_set_report_internal_cb,
+ FU_HID_DEVICE_RETRIES,
+ &helper,
+ error);
+ }
- if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL)
- fu_common_dump_raw (G_LOG_DOMAIN, "HID::GetReport", buf, actual_len);
+ /* just one */
+ return fu_hid_device_set_report_internal (self, &helper, error);
+}
+
+static gboolean
+fu_hid_device_get_report_internal (FuHidDevice *self,
+ FuHidDeviceRetryHelper *helper,
+ GError **error)
+{
+#ifdef HAVE_GUSB
+ FuHidDevicePrivate *priv = GET_PRIVATE (self);
+ GUsbDevice *usb_device;
+ gsize actual_len = 0;
+ guint16 wvalue = (FU_HID_REPORT_TYPE_INPUT << 8) | helper->value;
+
+ /* special case */
+ if (helper->flags & FU_HID_DEVICE_FLAG_IS_FEATURE)
+ wvalue = (FU_HID_REPORT_TYPE_FEATURE << 8) | helper->value;
+
+ if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL) {
+ g_autofree gchar *title = NULL;
+ title = g_strdup_printf ("HID::GetReport [wValue=0x%04x, wIndex=%u]",
+ wvalue, priv->interface);
+ fu_common_dump_raw (G_LOG_DOMAIN, title,
+ helper->buf, actual_len);
+ }
usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
if (!g_usb_device_control_transfer (usb_device,
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
@@ -300,24 +380,90 @@
G_USB_DEVICE_RECIPIENT_INTERFACE,
FU_HID_REPORT_GET,
wvalue, priv->interface,
- buf, bufsz,
+ helper->buf, helper->bufsz,
&actual_len, /* actual length */
- timeout,
+ helper->timeout,
NULL, error)) {
g_prefix_error (error, "failed to GetReport: ");
return FALSE;
}
- if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL)
- fu_common_dump_raw (G_LOG_DOMAIN, "HID::GetReport", buf, actual_len);
- if ((flags & FU_HID_DEVICE_FLAG_ALLOW_TRUNC) == 0 && actual_len != bufsz) {
+ if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL) {
+ g_autofree gchar *title = NULL;
+ title = g_strdup_printf ("HID::GetReport [wValue=0x%04x, wIndex=%u]",
+ wvalue, priv->interface);
+ fu_common_dump_raw (G_LOG_DOMAIN, title, helper->buf, actual_len);
+ }
+ if ((helper->flags & FU_HID_DEVICE_FLAG_ALLOW_TRUNC) == 0 && actual_len != helper->bufsz) {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"read %" G_GSIZE_FORMAT ", requested %" G_GSIZE_FORMAT " bytes",
- actual_len, bufsz);
+ actual_len, helper->bufsz);
return FALSE;
}
+#endif
return TRUE;
}
+static gboolean
+fu_hid_device_get_report_internal_cb (FuDevice *device, gpointer user_data, GError **error)
+{
+ FuHidDevice *self = FU_HID_DEVICE (device);
+ FuHidDeviceRetryHelper *helper = (FuHidDeviceRetryHelper *) user_data;
+ return fu_hid_device_get_report_internal (self, helper, error);
+}
+
+/**
+ * fu_hid_device_get_report:
+ * @self: A #FuHidDevice
+ * @value: low byte of wValue
+ * @buf: (nullable): a mutable buffer of data to send
+ * @bufsz: Size of @buf
+ * @timeout: timeout in ms
+ * @flags: #FuHidDeviceFlags e.g. %FU_HID_DEVICE_FLAG_ALLOW_TRUNC
+ * @error: a #GError or %NULL
+ *
+ * Calls GetReport on the hardware.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 1.4.0
+ **/
+gboolean
+fu_hid_device_get_report (FuHidDevice *self,
+ guint8 value,
+ guint8 *buf,
+ gsize bufsz,
+ guint timeout,
+ FuHidDeviceFlags flags,
+ GError **error)
+{
+ FuHidDeviceRetryHelper helper;
+ FuHidDevicePrivate *priv = GET_PRIVATE (self);
+
+ g_return_val_if_fail (FU_HID_DEVICE (self), FALSE);
+ g_return_val_if_fail (buf != NULL, FALSE);
+ g_return_val_if_fail (bufsz != 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* create helper */
+ helper.value = value;
+ helper.buf = buf;
+ helper.bufsz = bufsz;
+ helper.timeout = timeout;
+ helper.flags = priv->flags | flags;
+
+ /* special case */
+ if (flags & FU_HID_DEVICE_FLAG_RETRY_FAILURE) {
+ return fu_device_retry (FU_DEVICE (self),
+ fu_hid_device_get_report_internal_cb,
+ FU_HID_DEVICE_RETRIES,
+ &helper,
+ error);
+ }
+
+ /* just one */
+ return fu_hid_device_get_report_internal (self, &helper, error);
+}
+
static void
fu_hid_device_init (FuHidDevice *self)
{
@@ -346,14 +492,14 @@
static void
fu_hid_device_class_init (FuHidDeviceClass *klass)
{
- FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass);
+ FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->get_property = fu_hid_device_get_property;
object_class->set_property = fu_hid_device_set_property;
- klass_usb_device->open = fu_hid_device_open;
- klass_usb_device->close = fu_hid_device_close;
+ klass_device->open = fu_hid_device_open;
+ klass_device->close = fu_hid_device_close;
pspec = g_param_spec_uint ("interface", NULL, NULL,
0x00, 0xff, 0x00,
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-hid-device.h fwupd-1.5.8/libfwupdplugin/fu-hid-device.h
--- fwupd-1.4.5/libfwupdplugin/fu-hid-device.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-hid-device.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2020 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -28,6 +28,9 @@
* @FU_HID_DEVICE_FLAG_NONE: No flags set
* @FU_HID_DEVICE_FLAG_ALLOW_TRUNC: Allow truncated reads and writes
* @FU_HID_DEVICE_FLAG_IS_FEATURE: Use %FU_HID_REPORT_TYPE_FEATURE for wValue
+ * @FU_HID_DEVICE_FLAG_RETRY_FAILURE: Retry up to 10 times on failure
+ * @FU_HID_DEVICE_FLAG_NO_KERNEL_UNBIND: Do not unbind the kernel driver on open
+ * @FU_HID_DEVICE_FLAG_NO_KERNEL_REBIND: Do not rebind the kernel driver on close
*
* Flags used when calling fu_hid_device_get_report() and fu_hid_device_set_report().
**/
@@ -35,10 +38,16 @@
FU_HID_DEVICE_FLAG_NONE = 0,
FU_HID_DEVICE_FLAG_ALLOW_TRUNC = 1 << 0,
FU_HID_DEVICE_FLAG_IS_FEATURE = 1 << 1,
+ FU_HID_DEVICE_FLAG_RETRY_FAILURE = 1 << 2,
+ FU_HID_DEVICE_FLAG_NO_KERNEL_UNBIND = 1 << 3,
+ FU_HID_DEVICE_FLAG_NO_KERNEL_REBIND = 1 << 4,
+ /*< private >*/
FU_HID_DEVICE_FLAG_LAST
} FuHidDeviceFlags;
FuHidDevice *fu_hid_device_new (GUsbDevice *usb_device);
+void fu_hid_device_add_flag (FuHidDevice *self,
+ FuHidDeviceFlags flag);
void fu_hid_device_set_interface (FuHidDevice *self,
guint8 interface);
guint8 fu_hid_device_get_interface (FuHidDevice *self);
@@ -48,11 +57,13 @@
gsize bufsz,
guint timeout,
FuHidDeviceFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_hid_device_get_report (FuHidDevice *self,
guint8 value,
guint8 *buf,
gsize bufsz,
guint timeout,
FuHidDeviceFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-hwids.c fwupd-1.5.8/libfwupdplugin/fu-hwids.c
--- fwupd-1.4.5/libfwupdplugin/fu-hwids.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-hwids.c 2021-03-31 20:08:32.000000000 +0000
@@ -21,6 +21,7 @@
GObject parent_instance;
GHashTable *hash_dmi_hw; /* BiosVersion->"1.2.3 " */
GHashTable *hash_dmi_display; /* BiosVersion->"1.2.3" */
+ GHashTable *hash_smbios_override; /* BiosVersion->"1.2.3" */
GHashTable *hash_guid; /* a-c-b-d->1 */
GPtrArray *array_guids; /* a-c-b-d */
};
@@ -78,6 +79,39 @@
return self->array_guids;
}
+/**
+ * fu_hwids_get_keys:
+ * @self: A #FuHwids
+ *
+ * Returns all the defined HWID keys.
+ *
+ * Returns: (transfer container) (element-type utf8): All the known keys,
+ * e.g. %FU_HWIDS_KEY_FAMILY
+ *
+ * Since: 1.5.6
+ **/
+GPtrArray *
+fu_hwids_get_keys (FuHwids *self)
+{
+ GPtrArray *array = g_ptr_array_new ();
+ const gchar *keys[] = {
+ FU_HWIDS_KEY_BIOS_VENDOR,
+ FU_HWIDS_KEY_BIOS_VERSION,
+ FU_HWIDS_KEY_BIOS_MAJOR_RELEASE,
+ FU_HWIDS_KEY_BIOS_MINOR_RELEASE,
+ FU_HWIDS_KEY_MANUFACTURER,
+ FU_HWIDS_KEY_FAMILY,
+ FU_HWIDS_KEY_PRODUCT_NAME,
+ FU_HWIDS_KEY_PRODUCT_SKU,
+ FU_HWIDS_KEY_ENCLOSURE_KIND,
+ FU_HWIDS_KEY_BASEBOARD_MANUFACTURER,
+ FU_HWIDS_KEY_BASEBOARD_PRODUCT,
+ NULL };
+ for (guint i = 0; keys[i] != NULL; i++)
+ g_ptr_array_add (array, (gpointer) keys[i]);
+ return array;
+}
+
static gchar *
fu_hwids_get_guid_for_str (const gchar *str, GError **error)
{
@@ -197,6 +231,26 @@
}
/**
+ * fu_hwids_add_smbios_override:
+ * @self: A #FuHwids
+ * @key: A key, e.g. %FU_HWIDS_KEY_PRODUCT_SKU
+ * @value: (nullable): A new value, e.g. "ExampleModel" or %NULL
+ *
+ * Sets SMBIOS override values so you can emulate another system.
+ *
+ * This function has no effect if called after fu_hwids_setup()
+ *
+ * Since: 1.5.6
+ **/
+void
+fu_hwids_add_smbios_override (FuHwids *self, const gchar *key, const gchar *value)
+{
+ g_return_if_fail (FU_IS_HWIDS (self));
+ g_return_if_fail (key != NULL);
+ g_hash_table_insert (self->hash_smbios_override, g_strdup (key), g_strdup (value));
+}
+
+/**
* fu_hwids_get_replace_values:
* @self: A #FuHwids
* @keys: A key, e.g. `HardwareID-3` or %FU_HWIDS_KEY_PRODUCT_SKU
@@ -214,6 +268,10 @@
g_auto(GStrv) split = NULL;
g_autoptr(GString) str = g_string_new (NULL);
+ g_return_val_if_fail (FU_IS_HWIDS (self), NULL);
+ g_return_val_if_fail (keys != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
/* do any replacements */
keys = fu_hwids_get_replace_keys (self, keys);
@@ -251,7 +309,13 @@
gchar *
fu_hwids_get_guid (FuHwids *self, const gchar *keys, GError **error)
{
- g_autofree gchar *tmp = fu_hwids_get_replace_values (self, keys, error);
+ g_autofree gchar *tmp = NULL;
+
+ g_return_val_if_fail (FU_IS_HWIDS (self), NULL);
+ g_return_val_if_fail (keys != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ tmp = fu_hwids_get_replace_values (self, keys, error);
if (tmp == NULL)
return NULL;
return fu_hwids_get_guid_for_str (tmp, error);
@@ -280,21 +344,10 @@
guint8 type, guint8 offset,
GError **error)
{
- g_autoptr(GBytes) data = NULL;
- const guint8 *data_raw;
- gsize data_sz = 0;
- data = fu_smbios_get_data (smbios, type, error);
- if (data == NULL)
+ guint tmp = fu_smbios_get_integer (smbios, type, offset, error);
+ if (tmp == G_MAXUINT)
return NULL;
- data_raw = g_bytes_get_data (data, &data_sz);
- if (offset >= data_sz) {
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "offset bigger than data");
- return NULL;
- }
- return g_strdup_printf ("%02x", data_raw[offset]);
+ return g_strdup_printf ("%02x", tmp);
}
static gchar *
@@ -302,27 +355,16 @@
guint8 type, guint8 offset,
GError **error)
{
- g_autoptr(GBytes) data = NULL;
- const guint8 *data_raw;
- gsize data_sz = 0;
- data = fu_smbios_get_data (smbios, type, error);
- if (data == NULL)
- return NULL;
- data_raw = g_bytes_get_data (data, &data_sz);
- if (offset >= data_sz) {
- g_set_error_literal (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "offset bigger than data");
+ guint tmp = fu_smbios_get_integer (smbios, type, offset, error);
+ if (tmp == G_MAXUINT)
return NULL;
- }
- return g_strdup_printf ("%x", data_raw[offset]);
+ return g_strdup_printf ("%x", tmp);
}
/**
* fu_hwids_setup:
* @self: A #FuHwids
- * @smbios: A #FuSmbios
+ * @smbios: (nullable): A #FuSmbios or %NULL
* @error: A #GError or %NULL
*
* Reads all the SMBIOS values from the hardware.
@@ -366,25 +408,39 @@
};
g_return_val_if_fail (FU_IS_HWIDS (self), FALSE);
- g_return_val_if_fail (FU_IS_SMBIOS (smbios), FALSE);
+ g_return_val_if_fail (FU_IS_SMBIOS (smbios) || smbios == NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* get all DMI data */
for (guint i = 0; map[i].key != NULL; i++) {
- const gchar *contents_hdr;
+ const gchar *contents_hdr = NULL;
g_autofree gchar *contents = NULL;
g_autofree gchar *contents_safe = NULL;
g_autoptr(GError) error_local = NULL;
- /* get the data from a SMBIOS table */
- contents = map[i].func (smbios, map[i].type, map[i].offset, &error_local);
- if (contents == NULL) {
- g_debug ("ignoring %s: %s", map[i].key, error_local->message);
+ /* get the data from a SMBIOS table unless an override exists */
+ if (g_hash_table_lookup_extended (self->hash_smbios_override,
+ map[i].key, NULL,
+ (gpointer *) &contents_hdr)) {
+ if (contents_hdr == NULL) {
+ g_debug ("ignoring %s", map[i].key);
+ continue;
+ }
+ } else if (smbios != NULL) {
+ contents = map[i].func (smbios, map[i].type,
+ map[i].offset, &error_local);
+ if (contents == NULL) {
+ g_debug ("ignoring %s: %s", map[i].key, error_local->message);
+ continue;
+ }
+ contents_hdr = contents;
+ } else {
+ g_debug ("ignoring %s", map[i].key);
continue;
}
- g_debug ("smbios property %s=%s", map[i].key, contents);
+ g_debug ("smbios property %s=%s", map[i].key, contents_hdr);
/* weirdly, remove leading zeros */
- contents_hdr = contents;
while (contents_hdr[0] == '0' &&
map[i].func != fu_hwids_convert_padded_integer_cb)
contents_hdr++;
@@ -432,6 +488,7 @@
g_hash_table_unref (self->hash_dmi_hw);
g_hash_table_unref (self->hash_dmi_display);
+ g_hash_table_unref (self->hash_smbios_override);
g_hash_table_unref (self->hash_guid);
g_ptr_array_unref (self->array_guids);
@@ -450,6 +507,7 @@
{
self->hash_dmi_hw = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
self->hash_dmi_display = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ self->hash_smbios_override = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
self->hash_guid = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
self->array_guids = g_ptr_array_new_with_free_func (g_free);
}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-hwids.h fwupd-1.5.8/libfwupdplugin/fu-hwids.h
--- fwupd-1.4.5/libfwupdplugin/fu-hwids.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-hwids.h 2021-03-31 20:08:32.000000000 +0000
@@ -27,20 +27,26 @@
#define FU_HWIDS_KEY_PRODUCT_SKU "ProductSku"
FuHwids *fu_hwids_new (void);
-
+GPtrArray *fu_hwids_get_keys (FuHwids *self);
const gchar *fu_hwids_get_value (FuHwids *self,
const gchar *key);
+void fu_hwids_add_smbios_override (FuHwids *self,
+ const gchar *key,
+ const gchar *value);
const gchar *fu_hwids_get_replace_keys (FuHwids *self,
const gchar *key);
gchar *fu_hwids_get_replace_values (FuHwids *self,
const gchar *keys,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gchar *fu_hwids_get_guid (FuHwids *self,
const gchar *keys,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GPtrArray *fu_hwids_get_guids (FuHwids *self);
gboolean fu_hwids_has_guid (FuHwids *self,
const gchar *guid);
gboolean fu_hwids_setup (FuHwids *self,
FuSmbios *smbios,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-ihex-firmware.c fwupd-1.5.8/libfwupdplugin/fu-ihex-firmware.c
--- fwupd-1.4.5/libfwupdplugin/fu-ihex-firmware.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-ihex-firmware.c 2021-03-31 20:08:32.000000000 +0000
@@ -30,14 +30,6 @@
G_DEFINE_TYPE (FuIhexFirmware, fu_ihex_firmware, FU_TYPE_FIRMWARE)
-#define DFU_INHX32_RECORD_TYPE_DATA 0x00
-#define DFU_INHX32_RECORD_TYPE_EOF 0x01
-#define DFU_INHX32_RECORD_TYPE_EXTENDED_SEGMENT 0x02
-#define DFU_INHX32_RECORD_TYPE_START_SEGMENT 0x03
-#define DFU_INHX32_RECORD_TYPE_EXTENDED_LINEAR 0x04
-#define DFU_INHX32_RECORD_TYPE_START_LINEAR 0x05
-#define DFU_INHX32_RECORD_TYPE_SIGNATURE 0xfd
-
/**
* fu_ihex_firmware_get_records:
* @self: A #FuIhexFirmware
@@ -62,36 +54,108 @@
fu_ihex_firmware_record_free (FuIhexFirmwareRecord *rcd)
{
g_string_free (rcd->buf, TRUE);
+ g_byte_array_unref (rcd->data);
g_free (rcd);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuIhexFirmwareRecord, fu_ihex_firmware_record_free)
static FuIhexFirmwareRecord *
-fu_ihex_firmware_record_new (guint ln, const gchar *buf)
+fu_ihex_firmware_record_new (guint ln, const gchar *line,
+ FwupdInstallFlags flags, GError **error)
{
- FuIhexFirmwareRecord *rcd = g_new0 (FuIhexFirmwareRecord, 1);
+ g_autoptr(FuIhexFirmwareRecord) rcd = NULL;
+ gsize linesz = strlen (line);
+ guint line_end;
+ guint16 addr16 = 0;
+
+ /* check starting token */
+ if (line[0] != ':') {
+ g_autofree gchar *strsafe = fu_common_strsafe (line, 5);
+ if (strsafe != NULL) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "invalid starting token: %s",
+ strsafe);
+ return NULL;
+ }
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "invalid starting token");
+ return NULL;
+ }
+
+ /* length, 16-bit address, type */
+ rcd = g_new0 (FuIhexFirmwareRecord, 1);
rcd->ln = ln;
- rcd->buf = g_string_new (buf);
- return rcd;
+ rcd->data = g_byte_array_new ();
+ rcd->buf = g_string_new (line);
+ if (!fu_firmware_strparse_uint8_safe (line, linesz, 1, &rcd->byte_cnt, error))
+ return NULL;
+ if (!fu_firmware_strparse_uint16_safe (line, linesz, 3, &addr16, error))
+ return NULL;
+ rcd->addr = addr16;
+ if (!fu_firmware_strparse_uint8_safe (line, linesz, 7, &rcd->record_type, error))
+ return NULL;
+
+ /* position of checksum */
+ line_end = 9 + rcd->byte_cnt * 2;
+ if (line_end > (guint) rcd->buf->len) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "line malformed, length: %u",
+ line_end);
+ return NULL;
+ }
+
+ /* verify checksum */
+ if ((flags & FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM) == 0) {
+ guint8 checksum = 0;
+ for (guint i = 1; i < line_end + 2; i += 2) {
+ guint8 data_tmp = 0;
+ if (!fu_firmware_strparse_uint8_safe (line, linesz, i, &data_tmp, error))
+ return NULL;
+ checksum += data_tmp;
+ }
+ if (checksum != 0) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "invalid checksum (0x%02x)",
+ checksum);
+ return NULL;
+ }
+ }
+
+ /* add data */
+ for (guint i = 9; i < line_end; i += 2) {
+ guint8 tmp_c = 0;
+ if (!fu_firmware_strparse_uint8_safe (line, linesz, i, &tmp_c, error))
+ return NULL;
+ fu_byte_array_append_uint8 (rcd->data, tmp_c);
+ }
+ return g_steal_pointer (&rcd);
}
static const gchar *
fu_ihex_firmware_record_type_to_string (guint8 record_type)
{
- if (record_type == DFU_INHX32_RECORD_TYPE_DATA)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_DATA)
return "DATA";
- if (record_type == DFU_INHX32_RECORD_TYPE_EOF)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_EOF)
return "EOF";
- if (record_type == DFU_INHX32_RECORD_TYPE_EXTENDED_SEGMENT)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_SEGMENT)
return "EXTENDED_SEGMENT";
- if (record_type == DFU_INHX32_RECORD_TYPE_START_SEGMENT)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_START_SEGMENT)
return "START_SEGMENT";
- if (record_type == DFU_INHX32_RECORD_TYPE_EXTENDED_LINEAR)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_LINEAR)
return "EXTENDED_LINEAR";
- if (record_type == DFU_INHX32_RECORD_TYPE_START_LINEAR)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_START_LINEAR)
return "ADDR32";
- if (record_type == DFU_INHX32_RECORD_TYPE_SIGNATURE)
+ if (record_type == FU_IHEX_FIRMWARE_RECORD_TYPE_SIGNATURE)
return "SIGNATURE";
return NULL;
}
@@ -108,9 +172,15 @@
for (guint ln = 0; lines[ln] != NULL; ln++) {
g_autoptr(FuIhexFirmwareRecord) rcd = NULL;
g_strdelimit (lines[ln], "\r\x1a", '\0');
+ if (g_str_has_prefix (lines[ln], ";"))
+ continue;
if (lines[ln][0] == '\0')
continue;
- rcd = fu_ihex_firmware_record_new (ln + 1, lines[ln]);
+ rcd = fu_ihex_firmware_record_new (ln + 1, lines[ln], flags, error);
+ if (rcd == NULL) {
+ g_prefix_error (error, "invalid line %u: ", ln + 1);
+ return FALSE;
+ }
g_ptr_array_add (self->records, g_steal_pointer (&rcd));
}
return TRUE;
@@ -126,6 +196,7 @@
{
FuIhexFirmware *self = FU_IHEX_FIRMWARE (firmware);
gboolean got_eof = FALSE;
+ gboolean got_sig = FALSE;
guint32 abs_addr = 0x0;
guint32 addr_last = 0x0;
guint32 img_addr = G_MAXUINT32;
@@ -133,87 +204,31 @@
g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (NULL);
g_autoptr(GBytes) img_bytes = NULL;
g_autoptr(GByteArray) buf = g_byte_array_new ();
- g_autoptr(GByteArray) buf_signature = g_byte_array_new ();
/* parse records */
for (guint k = 0; k < self->records->len; k++) {
FuIhexFirmwareRecord *rcd = g_ptr_array_index (self->records, k);
- const gchar *line = rcd->buf->str;
- guint32 addr;
- guint8 byte_cnt;
- guint8 record_type;
- guint line_end;
-
- /* ignore comments */
- if (g_str_has_prefix (line, ";"))
- continue;
+ guint16 addr16 = 0;
+ guint32 addr = rcd->addr + seg_addr + abs_addr;
+ guint32 len_hole;
- /* ignore blank lines */
- if (rcd->buf->len == 0)
- continue;
-
- /* check starting token */
- if (line[0] != ':') {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "invalid starting token on line %u: %s",
- rcd->ln, line);
- return FALSE;
- }
-
- /* check there's enough data for the smallest possible record */
- if (rcd->buf->len < 11) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "line %u is incomplete, length %u",
- rcd->ln, (guint) rcd->buf->len);
- return FALSE;
- }
-
- /* length, 16-bit address, type */
- byte_cnt = fu_firmware_strparse_uint8 (line + 1);
- addr = fu_firmware_strparse_uint16 (line + 3);
- record_type = fu_firmware_strparse_uint8 (line + 7);
- g_debug ("%s:", fu_ihex_firmware_record_type_to_string (record_type));
- g_debug (" addr_start:\t0x%04x", addr);
- g_debug (" length:\t0x%02x", byte_cnt);
- addr += seg_addr;
- addr += abs_addr;
+ g_debug ("%s:", fu_ihex_firmware_record_type_to_string (rcd->record_type));
+ g_debug (" length:\t0x%02x", rcd->data->len);
g_debug (" addr:\t0x%08x", addr);
- /* position of checksum */
- line_end = 9 + byte_cnt * 2;
- if (line_end > (guint) rcd->buf->len) {
+ /* sanity check */
+ if (rcd->record_type != FU_IHEX_FIRMWARE_RECORD_TYPE_EOF &&
+ rcd->data->len == 0) {
g_set_error (error,
FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "line %u malformed, length: %u",
- rcd->ln, line_end);
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "record 0x%x had zero size", k);
return FALSE;
}
- /* verify checksum */
- if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
- guint8 checksum = 0;
- for (guint i = 1; i < line_end + 2; i += 2) {
- guint8 data_tmp = fu_firmware_strparse_uint8 (line + i);
- checksum += data_tmp;
- }
- if (checksum != 0) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "line %u has invalid checksum (0x%02x)",
- rcd->ln, checksum);
- return FALSE;
- }
- }
-
/* process different record types */
- switch (record_type) {
- case DFU_INHX32_RECORD_TYPE_DATA:
+ switch (rcd->record_type) {
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_DATA:
/* base address for element */
if (img_addr == G_MAXUINT32)
img_addr = addr;
@@ -230,37 +245,32 @@
return FALSE;
}
- /* parse bytes from line */
- g_debug ("writing data 0x%08x", (guint32) addr);
- for (guint i = 9; i < line_end; i += 2) {
- /* any holes in the hex record */
- guint32 len_hole = addr - addr_last;
- guint8 data_tmp;
- if (addr_last > 0 && len_hole > 0x100000) {
- g_set_error (error,
- FWUPD_ERROR,
- FWUPD_ERROR_INVALID_FILE,
- "hole of 0x%x bytes too large to fill on line %u",
- (guint) len_hole,
- rcd->ln);
- return FALSE;
- }
- if (addr_last > 0x0 && len_hole > 1) {
- g_debug ("filling address 0x%08x to 0x%08x on line %u",
- addr_last + 1, addr_last + len_hole - 1, rcd->ln);
- for (guint j = 1; j < len_hole; j++) {
- /* although 0xff might be clearer,
- * we can't write 0xffff to pic14 */
- fu_byte_array_append_uint8 (buf, 0x00);
- }
+ /* any holes in the hex record */
+ len_hole = addr - addr_last;
+ if (addr_last > 0 && len_hole > 0x100000) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "hole of 0x%x bytes too large to fill on line %u",
+ (guint) len_hole,
+ rcd->ln);
+ return FALSE;
+ }
+ if (addr_last > 0x0 && len_hole > 1) {
+ g_debug ("filling address 0x%08x to 0x%08x on line %u",
+ addr_last + 1, addr_last + len_hole - 1, rcd->ln);
+ for (guint j = 1; j < len_hole; j++) {
+ /* although 0xff might be clearer,
+ * we can't write 0xffff to pic14 */
+ fu_byte_array_append_uint8 (buf, 0x00);
}
- /* write into buf */
- data_tmp = fu_firmware_strparse_uint8 (line + i);
- fu_byte_array_append_uint8 (buf, (gchar) data_tmp);
- addr_last = addr++;
}
+ addr_last = addr + rcd->data->len - 1;
+
+ /* write into buf */
+ g_byte_array_append (buf, rcd->data->data, rcd->data->len);
break;
- case DFU_INHX32_RECORD_TYPE_EOF:
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_EOF:
if (got_eof) {
g_set_error_literal (error,
FWUPD_ERROR,
@@ -271,29 +281,50 @@
}
got_eof = TRUE;
break;
- case DFU_INHX32_RECORD_TYPE_EXTENDED_LINEAR:
- abs_addr = fu_firmware_strparse_uint16 (line + 9) << 16;
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_LINEAR:
+ if (!fu_common_read_uint16_safe (rcd->data->data, rcd->data->len,
+ 0x0, &addr16, G_BIG_ENDIAN, error))
+ return FALSE;
+ abs_addr = (guint32) addr16 << 16;
g_debug (" abs_addr:\t0x%02x on line %u", abs_addr, rcd->ln);
break;
- case DFU_INHX32_RECORD_TYPE_START_LINEAR:
- abs_addr = fu_firmware_strparse_uint32 (line + 9);
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_START_LINEAR:
+ if (!fu_common_read_uint32_safe (rcd->data->data, rcd->data->len,
+ 0x0, &abs_addr, G_BIG_ENDIAN, error))
+ return FALSE;
g_debug (" abs_addr:\t0x%08x on line %u", abs_addr, rcd->ln);
break;
- case DFU_INHX32_RECORD_TYPE_EXTENDED_SEGMENT:
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_SEGMENT:
+ if (!fu_common_read_uint16_safe (rcd->data->data, rcd->data->len,
+ 0x0, &addr16, G_BIG_ENDIAN, error))
+ return FALSE;
/* segment base address, so ~1Mb addressable */
- seg_addr = fu_firmware_strparse_uint16 (line + 9) * 16;
+ seg_addr = (guint32) addr16 * 16;
g_debug (" seg_addr:\t0x%08x on line %u", seg_addr, rcd->ln);
break;
- case DFU_INHX32_RECORD_TYPE_START_SEGMENT:
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_START_SEGMENT:
/* initial content of the CS:IP registers */
- seg_addr = fu_firmware_strparse_uint32 (line + 9);
+ if (!fu_common_read_uint32_safe (rcd->data->data, rcd->data->len,
+ 0x0, &seg_addr, G_BIG_ENDIAN, error))
+ return FALSE;
g_debug (" seg_addr:\t0x%02x on line %u", seg_addr, rcd->ln);
break;
- case DFU_INHX32_RECORD_TYPE_SIGNATURE:
- for (guint i = 9; i < line_end; i += 2) {
- guint8 tmp_c = fu_firmware_strparse_uint8 (line + i);
- fu_byte_array_append_uint8 (buf_signature, tmp_c);
+ case FU_IHEX_FIRMWARE_RECORD_TYPE_SIGNATURE:
+ if (got_sig) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_FILE,
+ "duplicate signature, perhaps "
+ "corrupt file");
+ return FALSE;
+ }
+ if (rcd->data->len > 0) {
+ g_autoptr(GBytes) data_sig = g_bytes_new (rcd->data->data, rcd->data->len);
+ g_autoptr(FuFirmwareImage) img_sig = fu_firmware_image_new (data_sig);
+ fu_firmware_image_set_id (img_sig, FU_FIRMWARE_IMAGE_ID_SIGNATURE);
+ fu_firmware_add_image (firmware, img_sig);
}
+ got_sig = TRUE;
break;
default:
/* vendors sneak in nonstandard sections past the EOF */
@@ -303,7 +334,7 @@
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"invalid ihex record type %i on line %u",
- record_type, rcd->ln);
+ rcd->record_type, rcd->ln);
return FALSE;
}
}
@@ -323,14 +354,6 @@
if (img_addr != G_MAXUINT32)
fu_firmware_image_set_addr (img, img_addr);
fu_firmware_add_image (firmware, img);
-
- /* add optional signature */
- if (buf_signature->len > 0) {
- g_autoptr(GBytes) data_sig = g_bytes_new (buf_signature->data, buf_signature->len);
- g_autoptr(FuFirmwareImage) img_sig = fu_firmware_image_new (data_sig);
- fu_firmware_image_set_id (img_sig, FU_FIRMWARE_IMAGE_ID_SIGNATURE);
- fu_firmware_add_image (firmware, img_sig);
- }
return TRUE;
}
@@ -364,7 +387,7 @@
const guint chunk_size = 16;
gsize len;
guint32 address_offset_last = 0x0;
- guint8 record_type = DFU_INHX32_RECORD_TYPE_DATA;
+ guint8 record_type = FU_IHEX_FIRMWARE_RECORD_TYPE_DATA;
g_autoptr(GBytes) bytes = NULL;
/* get data */
@@ -375,7 +398,7 @@
/* special case */
if (g_strcmp0 (fu_firmware_image_get_id (img),
FU_FIRMWARE_IMAGE_ID_SIGNATURE) == 0)
- record_type = DFU_INHX32_RECORD_TYPE_SIGNATURE;
+ record_type = FU_IHEX_FIRMWARE_RECORD_TYPE_SIGNATURE;
/* get number of chunks */
data = g_bytes_get_data (bytes, &len);
@@ -389,7 +412,7 @@
guint8 buf[2];
fu_common_write_uint16 (buf, address_offset, G_BIG_ENDIAN);
fu_ihex_firmware_emit_chunk (str, 0x0,
- DFU_INHX32_RECORD_TYPE_EXTENDED_LINEAR,
+ FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_LINEAR,
buf, 2);
address_offset_last = address_offset;
}
@@ -416,7 +439,7 @@
}
/* add EOF */
- fu_ihex_firmware_emit_chunk (str, 0x0, DFU_INHX32_RECORD_TYPE_EOF, NULL, 0);
+ fu_ihex_firmware_emit_chunk (str, 0x0, FU_IHEX_FIRMWARE_RECORD_TYPE_EOF, NULL, 0);
return g_bytes_new (str->str, str->len);
}
@@ -432,6 +455,7 @@
fu_ihex_firmware_init (FuIhexFirmware *self)
{
self->records = g_ptr_array_new_with_free_func ((GFreeFunc) fu_ihex_firmware_record_free);
+ fu_firmware_add_flag (FU_FIRMWARE (self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
}
static void
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-ihex-firmware.h fwupd-1.5.8/libfwupdplugin/fu-ihex-firmware.h
--- fwupd-1.4.5/libfwupdplugin/fu-ihex-firmware.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-ihex-firmware.h 2021-03-31 20:08:32.000000000 +0000
@@ -14,7 +14,19 @@
typedef struct {
guint ln;
GString *buf;
+ guint8 byte_cnt;
+ guint32 addr;
+ guint8 record_type;
+ GByteArray *data;
} FuIhexFirmwareRecord;
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_DATA 0x00
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_EOF 0x01
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_SEGMENT 0x02
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_START_SEGMENT 0x03
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_EXTENDED_LINEAR 0x04
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_START_LINEAR 0x05
+#define FU_IHEX_FIRMWARE_RECORD_TYPE_SIGNATURE 0xfd
+
FuFirmware *fu_ihex_firmware_new (void);
GPtrArray *fu_ihex_firmware_get_records (FuIhexFirmware *self);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-io-channel.c fwupd-1.5.8/libfwupdplugin/fu-io-channel.c
--- fwupd-1.4.5/libfwupdplugin/fu-io-channel.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-io-channel.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -61,6 +61,7 @@
fu_io_channel_shutdown (FuIOChannel *self, GError **error)
{
g_return_val_if_fail (FU_IS_IO_CHANNEL (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!g_close (self->fd, error))
return FALSE;
self->fd = -1;
@@ -159,6 +160,7 @@
gsize idx = 0;
g_return_val_if_fail (FU_IS_IO_CHANNEL (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* flush pending reads */
if (flags & FU_IO_CHANNEL_FLAG_FLUSH_INPUT) {
@@ -489,7 +491,12 @@
fu_io_channel_new_file (const gchar *filename, GError **error)
{
#ifdef HAVE_POLL_H
- gint fd = g_open (filename, O_RDWR | O_NONBLOCK, S_IRWXU);
+ gint fd;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ fd = g_open (filename, O_RDWR | O_NONBLOCK, S_IRWXU);
if (fd < 0) {
g_set_error (error,
FWUPD_ERROR,
@@ -499,6 +506,8 @@
}
return fu_io_channel_unix_new (fd);
#else
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-io-channel.h fwupd-1.5.8/libfwupdplugin/fu-io-channel.h
--- fwupd-1.4.5/libfwupdplugin/fu-io-channel.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-io-channel.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Richard Hughes
+ * Copyright (C) 2017 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -32,41 +32,49 @@
FuIOChannel *fu_io_channel_unix_new (gint fd);
FuIOChannel *fu_io_channel_new_file (const gchar *filename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gint fu_io_channel_unix_get_fd (FuIOChannel *self);
gboolean fu_io_channel_shutdown (FuIOChannel *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_io_channel_write_raw (FuIOChannel *self,
const guint8 *data,
gsize datasz,
guint timeout_ms,
FuIOChannelFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_io_channel_read_raw (FuIOChannel *self,
guint8 *buf,
gsize bufsz,
gsize *bytes_read,
guint timeout_ms,
FuIOChannelFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_io_channel_write_bytes (FuIOChannel *self,
GBytes *bytes,
guint timeout_ms,
FuIOChannelFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_io_channel_write_byte_array (FuIOChannel *self,
GByteArray *buf,
guint timeout_ms,
FuIOChannelFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GBytes *fu_io_channel_read_bytes (FuIOChannel *self,
gssize max_size,
guint timeout_ms,
FuIOChannelFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
GByteArray *fu_io_channel_read_byte_array (FuIOChannel *self,
gssize max_size,
guint timeout_ms,
FuIOChannelFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-plugin.c fwupd-1.5.8/libfwupdplugin/fu-plugin.c
--- fwupd-1.4.5/libfwupdplugin/fu-plugin.c 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-plugin.c 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2018 Richard Hughes
+ * Copyright (C) 2016 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -36,12 +36,10 @@
typedef struct {
GModule *module;
- GUsbContext *usb_ctx;
- gboolean enabled;
guint order;
guint priority;
GPtrArray *rules[FU_PLUGIN_RULE_LAST];
- gchar *name;
+ GPtrArray *devices; /* (nullable) (element-type FuDevice) */
gchar *build_hash;
FuHwids *hwids;
FuQuirks *quirks;
@@ -50,9 +48,9 @@
GPtrArray *udev_subsystems;
FuSmbios *smbios;
GType device_gtype;
- GHashTable *devices; /* platform_id:GObject */
- GRWLock devices_mutex;
- GHashTable *report_metadata; /* key:value */
+ GHashTable *cache; /* (nullable): platform_id:GObject */
+ GRWLock cache_mutex;
+ GHashTable *report_metadata; /* (nullable): key:value */
FuPluginData *data;
} FuPluginPrivate;
@@ -65,12 +63,13 @@
SIGNAL_SET_COLDPLUG_DELAY,
SIGNAL_CHECK_SUPPORTED,
SIGNAL_ADD_FIRMWARE_GTYPE,
+ SIGNAL_SECURITY_CHANGED,
SIGNAL_LAST
};
static guint signals[SIGNAL_LAST] = { 0 };
-G_DEFINE_TYPE_WITH_PRIVATE (FuPlugin, fu_plugin, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE (FuPlugin, fu_plugin, FWUPD_TYPE_PLUGIN)
#define GET_PRIVATE(o) (fu_plugin_get_instance_private (o))
typedef const gchar *(*FuPluginGetNameFunc) (void);
@@ -98,12 +97,8 @@
GBytes *blob_fw,
FwupdInstallFlags flags,
GError **error);
-typedef gboolean (*FuPluginUsbDeviceAddedFunc) (FuPlugin *self,
- FuUsbDevice *device,
- GError **error);
-typedef gboolean (*FuPluginUdevDeviceAddedFunc) (FuPlugin *self,
- FuUdevDevice *device,
- GError **error);
+typedef void (*FuPluginSecurityAttrsFunc) (FuPlugin *self,
+ FuSecurityAttrs *attrs);
/**
* fu_plugin_is_open:
@@ -135,9 +130,8 @@
const gchar *
fu_plugin_get_name (FuPlugin *self)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
- return priv->name;
+ return fwupd_plugin_get_name (FWUPD_PLUGIN (self));
}
/**
@@ -152,11 +146,8 @@
void
fu_plugin_set_name (FuPlugin *self, const gchar *name)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_PLUGIN (self));
- g_return_if_fail (name != NULL);
- g_free (priv->name);
- priv->name = g_strdup (name);
+ fwupd_plugin_set_name (FWUPD_PLUGIN (self), name);
}
/**
@@ -175,6 +166,11 @@
FuPluginPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_PLUGIN (self));
g_return_if_fail (build_hash != NULL);
+
+ /* not changed */
+ if (g_strcmp0 (priv->build_hash, build_hash) == 0)
+ return;
+
g_free (priv->build_hash);
priv->build_hash = g_strdup (build_hash);
}
@@ -212,11 +208,13 @@
fu_plugin_cache_lookup (FuPlugin *self, const gchar *id)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
- g_autoptr(GRWLockReaderLocker) locker = g_rw_lock_reader_locker_new (&priv->devices_mutex);
+ g_autoptr(GRWLockReaderLocker) locker = g_rw_lock_reader_locker_new (&priv->cache_mutex);
g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
g_return_val_if_fail (id != NULL, NULL);
g_return_val_if_fail (locker != NULL, NULL);
- return g_hash_table_lookup (priv->devices, id);
+ if (priv->cache == NULL)
+ return NULL;
+ return g_hash_table_lookup (priv->cache, id);
}
/**
@@ -233,11 +231,17 @@
fu_plugin_cache_add (FuPlugin *self, const gchar *id, gpointer dev)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
- g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->devices_mutex);
+ g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->cache_mutex);
g_return_if_fail (FU_IS_PLUGIN (self));
g_return_if_fail (id != NULL);
g_return_if_fail (locker != NULL);
- g_hash_table_insert (priv->devices, g_strdup (id), g_object_ref (dev));
+ if (priv->cache == NULL) {
+ priv->cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) g_object_unref);
+ }
+ g_hash_table_insert (priv->cache, g_strdup (id), g_object_ref (dev));
}
/**
@@ -253,11 +257,13 @@
fu_plugin_cache_remove (FuPlugin *self, const gchar *id)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
- g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->devices_mutex);
+ g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->cache_mutex);
g_return_if_fail (FU_IS_PLUGIN (self));
g_return_if_fail (id != NULL);
g_return_if_fail (locker != NULL);
- g_hash_table_remove (priv->devices, id);
+ if (priv->cache == NULL)
+ return;
+ g_hash_table_remove (priv->cache, id);
}
/**
@@ -307,7 +313,8 @@
* fu_plugin_get_usb_context:
* @self: A #FuPlugin
*
- * Gets the shared USB context that all plugins can use.
+ * This used to get the shared USB context that all plugins can use; it now
+ * returns %NULL;
*
* Returns: (transfer none): a #GUsbContext.
*
@@ -316,9 +323,8 @@
GUsbContext *
fu_plugin_get_usb_context (FuPlugin *self)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
- return priv->usb_ctx;
+ return NULL;
}
/**
@@ -326,15 +332,13 @@
* @self: A #FuPlugin
* @usb_ctx: A #FGUsbContext
*
- * Sets the shared USB context for a plugin
+ * This used to set the shared USB context for a plugin. It now does nothing.
*
* Since: 0.8.0
**/
void
fu_plugin_set_usb_context (FuPlugin *self, GUsbContext *usb_ctx)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
- g_set_object (&priv->usb_ctx, usb_ctx);
}
/**
@@ -351,9 +355,8 @@
gboolean
fu_plugin_get_enabled (FuPlugin *self)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
- return priv->enabled;
+ return !fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
}
/**
@@ -368,9 +371,13 @@
void
fu_plugin_set_enabled (FuPlugin *self, gboolean enabled)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
g_return_if_fail (FU_IS_PLUGIN (self));
- priv->enabled = enabled;
+ if (enabled) {
+ fwupd_plugin_remove_flag (FWUPD_PLUGIN (self),
+ FWUPD_PLUGIN_FLAG_DISABLED);
+ } else {
+ fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
+ }
}
/**
@@ -414,6 +421,10 @@
FuPluginPrivate *priv = GET_PRIVATE (self);
FuPluginInitFunc func = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
priv->module = g_module_open (filename, 0);
if (priv->module == NULL) {
g_set_error (error,
@@ -421,23 +432,57 @@
G_IO_ERROR_FAILED,
"failed to open plugin %s: %s",
filename, g_module_error ());
+ fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_FAILED_OPEN);
+ fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_USER_WARNING);
return FALSE;
}
/* set automatically */
- if (priv->name == NULL)
- priv->name = fu_plugin_guess_name_from_fn (filename);
+ if (fu_plugin_get_name (self) == NULL) {
+ g_autofree gchar *str = fu_plugin_guess_name_from_fn (filename);
+ fu_plugin_set_name (self, str);
+ }
/* optional */
g_module_symbol (priv->module, "fu_plugin_init", (gpointer *) &func);
if (func != NULL) {
- g_debug ("performing init() on %s", filename);
+ g_debug ("init(%s)", filename);
func (self);
}
return TRUE;
}
+/* order of usefulness to the user */
+static const gchar *
+fu_plugin_build_device_update_error (FuPlugin *self)
+{
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_NO_HARDWARE))
+ return "Not updatable as required hardware was not found";
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_LEGACY_BIOS))
+ return "Not updatable in legacy BIOS mode";
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED))
+ return "Not updatable as UEFI capsule updates not enabled in firmware setup";
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED))
+ return "Not updatable as requires unlock";
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED))
+ return "Not updatable as efivarfs was not found";
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND))
+ return "Not updatable as UEFI ESP partition not detected";
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
+ return "Not updatable as plugin was disabled";
+ return NULL;
+}
+
+static void
+fu_plugin_ensure_devices (FuPlugin *self)
+{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
+ if (priv->devices != NULL)
+ return;
+ priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+}
+
/**
* fu_plugin_device_add:
* @self: A #FuPlugin
@@ -456,6 +501,7 @@
void
fu_plugin_device_add (FuPlugin *self, FuDevice *device)
{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
GPtrArray *children;
g_autoptr(GError) error = NULL;
@@ -468,6 +514,25 @@
return;
}
+ /* add to array */
+ fu_plugin_ensure_devices (self);
+ g_ptr_array_add (priv->devices, g_object_ref (device));
+
+ /* proxy to device where required */
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE)) {
+ g_debug ("plugin %s has _CLEAR_UPDATABLE, so removing from %s",
+ fu_plugin_get_name (self),
+ fu_device_get_id (device));
+ fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE);
+ }
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_USER_WARNING) &&
+ fu_device_get_update_error (device) == NULL) {
+ const gchar *tmp = fu_plugin_build_device_update_error (self);
+ g_debug ("setting %s update error to '%s' from %s",
+ fu_device_get_id (device), tmp, fu_plugin_get_name (self));
+ fu_device_set_update_error (device, tmp);
+ }
+
g_debug ("emit added from %s: %s",
fu_plugin_get_name (self),
fu_device_get_id (device));
@@ -485,6 +550,26 @@
}
/**
+ * fu_plugin_get_devices:
+ * @self: A #FuPlugin
+ *
+ * Returns all devices added by the plugin using fu_plugin_device_add() and
+ * not yet removed with fu_plugin_device_remove().
+ *
+ * Returns: (transfer none) (element-type FuDevice): devices
+ *
+ * Since: 1.5.6
+ **/
+GPtrArray *
+fu_plugin_get_devices (FuPlugin *self)
+{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
+ g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
+ fu_plugin_ensure_devices (self);
+ return priv->devices;
+}
+
+/**
* fu_plugin_device_register:
* @self: A #FuPlugin
* @device: A #FuDevice
@@ -530,9 +615,15 @@
void
fu_plugin_device_remove (FuPlugin *self, FuDevice *device)
{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
+
g_return_if_fail (FU_IS_PLUGIN (self));
g_return_if_fail (FU_IS_DEVICE (device));
+ /* remove from array */
+ if (priv->devices != NULL)
+ g_ptr_array_remove (priv->devices, device);
+
g_debug ("emit removed from %s: %s",
fu_plugin_get_name (self),
fu_device_get_id (device));
@@ -556,6 +647,21 @@
}
/**
+ * fu_plugin_security_changed:
+ * @self: A #FuPlugin
+ *
+ * Informs the daemon that the HSI state may have changed.
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_plugin_security_changed (FuPlugin *self)
+{
+ g_return_if_fail (FU_IS_PLUGIN (self));
+ g_signal_emit (self, signals[SIGNAL_SECURITY_CHANGED], 0);
+}
+
+/**
* fu_plugin_check_hwid:
* @self: A #FuPlugin
* @hwid: A Hardware ID GUID, e.g. `6de5d951-d755-576b-bd09-c5cf66b27234`
@@ -647,10 +753,9 @@
for (guint i = 0; i < hwids->len; i++) {
const gchar *hwid = g_ptr_array_index (hwids, i);
const gchar *value;
- g_autofree gchar *key = g_strdup_printf ("HwId=%s", hwid);
/* does prefixed quirk exist */
- value = fu_quirks_lookup_by_id (priv->quirks, key, FU_QUIRKS_FLAGS);
+ value = fu_quirks_lookup_by_id (priv->quirks, hwid, FU_QUIRKS_FLAGS);
if (value != NULL) {
g_auto(GStrv) quirks = g_strsplit (value, ",", -1);
if (g_strv_contains ((const gchar * const *) quirks, flag))
@@ -955,7 +1060,7 @@
*
* Set the minimum time that should be waited in-between the call to
* fu_plugin_coldplug_prepare() and fu_plugin_coldplug(). This is usually going
- * to be the minimum hardware initialisation time from a datasheet.
+ * to be the minimum hardware initialization time from a datasheet.
*
* It is better to use this function rather than using a sleep() in the plugin
* itself as then only one delay is done in the daemon rather than waiting for
@@ -1024,6 +1129,32 @@
locker = fu_device_locker_new (device, error);
if (locker == NULL)
return FALSE;
+
+ /* back the old firmware up to /var/lib/fwupd */
+ if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL)) {
+ g_autoptr(GBytes) fw_old = NULL;
+ g_autofree gchar *path = NULL;
+ g_autofree gchar *fn = NULL;
+ g_autofree gchar *localstatedir = NULL;
+
+ fw_old = fu_device_dump_firmware (device, error);
+ if (fw_old == NULL) {
+ g_prefix_error (error, "failed to backup old firmware: ");
+ return FALSE;
+ }
+ localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
+ fn = g_strdup_printf ("%s.bin", fu_device_get_version (device));
+ path = g_build_filename (localstatedir,
+ "backup",
+ fu_device_get_id (device),
+ fu_device_get_serial (device) != NULL ?
+ fu_device_get_serial (device) :
+ "default",
+ fn, NULL);
+ if (!fu_common_set_contents_bytes (path, fw_old, error))
+ return FALSE;
+ }
+
return fu_device_write_firmware (device, fw, flags, error);
}
@@ -1085,7 +1216,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1096,11 +1227,11 @@
g_module_symbol (priv->module, "fu_plugin_startup", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing startup() on %s", priv->name);
+ g_debug ("startup(%s)", fu_plugin_get_name (self));
if (!func (self, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for startup()",
- priv->name);
+ g_critical ("unset plugin error in startup(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1108,7 +1239,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to startup using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1125,7 +1256,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1136,17 +1267,17 @@
g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
if (func == NULL) {
if (device_func != NULL) {
- g_debug ("running superclassed %s() on %s",
- symbol_name + 10, priv->name);
+ g_debug ("running superclassed %s(%s)",
+ symbol_name + 10, fu_plugin_get_name (self));
return device_func (self, device, error);
}
return TRUE;
}
- g_debug ("performing %s() on %s", symbol_name + 10, priv->name);
+ g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
if (!func (self, device, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for %s()",
- priv->name, symbol_name + 10);
+ g_critical ("unset plugin error in %s(%s)",
+ fu_plugin_get_name (self), symbol_name + 10);
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1154,7 +1285,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to %s using %s: ",
- symbol_name + 10, priv->name);
+ symbol_name + 10, fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1170,7 +1301,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1181,11 +1312,11 @@
g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing %s() on %s", symbol_name + 10, priv->name);
+ g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
if (!func (self, flags, device, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for %s()",
- priv->name, symbol_name + 10);
+ g_critical ("unset plugin error in %s(%s)",
+ fu_plugin_get_name (self), symbol_name + 10);
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1193,7 +1324,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to %s using %s: ",
- symbol_name + 10, priv->name);
+ symbol_name + 10, fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1209,7 +1340,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1220,11 +1351,11 @@
g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing %s() on %s", symbol_name + 10, priv->name);
+ g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
if (!func (self, devices, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for %s()",
- priv->name, symbol_name + 10);
+ g_critical ("unset plugin error in for %s(%s)",
+ fu_plugin_get_name (self), symbol_name + 10);
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1232,7 +1363,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to %s using %s: ",
- symbol_name + 10, priv->name);
+ symbol_name + 10, fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1257,7 +1388,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1268,18 +1399,18 @@
g_module_symbol (priv->module, "fu_plugin_coldplug", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing coldplug() on %s", priv->name);
+ g_debug ("coldplug(%s)", fu_plugin_get_name (self));
if (!func (self, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for coldplug()",
- priv->name);
+ g_critical ("unset plugin error in coldplug(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"unspecified error");
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
- "failed to coldplug using %s: ", priv->name);
+ "failed to coldplug using %s: ", fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1304,7 +1435,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1315,11 +1446,11 @@
g_module_symbol (priv->module, "fu_plugin_recoldplug", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing recoldplug() on %s", priv->name);
+ g_debug ("recoldplug(%s)", fu_plugin_get_name (self));
if (!func (self, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for recoldplug()",
- priv->name);
+ g_critical ("unset plugin error in recoldplug(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1327,7 +1458,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to recoldplug using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1352,7 +1483,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1363,11 +1494,11 @@
g_module_symbol (priv->module, "fu_plugin_coldplug_prepare", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing coldplug_prepare() on %s", priv->name);
+ g_debug ("coldplug_prepare(%s)", fu_plugin_get_name (self));
if (!func (self, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for coldplug_prepare()",
- priv->name);
+ g_critical ("unset plugin error in coldplug_prepare(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1375,7 +1506,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to coldplug_prepare using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1400,7 +1531,7 @@
g_autoptr(GError) error_local = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1411,11 +1542,11 @@
g_module_symbol (priv->module, "fu_plugin_coldplug_cleanup", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing coldplug_cleanup() on %s", priv->name);
+ g_debug ("coldplug_cleanup(%s)", fu_plugin_get_name (self));
if (!func (self, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for coldplug_cleanup()",
- priv->name);
+ g_critical ("unset plugin error in coldplug_cleanup(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1423,7 +1554,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to coldplug_cleanup using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1472,6 +1603,8 @@
/**
* fu_plugin_runner_update_prepare:
* @self: a #FuPlugin
+ * @flags: #FwupdInstallFlags
+ * @device: a #FuDevice
* @error: a #GError or NULL
*
* Runs the update_prepare routine for the plugin
@@ -1492,6 +1625,8 @@
/**
* fu_plugin_runner_update_cleanup:
* @self: a #FuPlugin
+ * @flags: #FwupdInstallFlags
+ * @device: a #FuDevice
* @error: a #GError or NULL
*
* Runs the update_cleanup routine for the plugin
@@ -1554,6 +1689,7 @@
/**
* fu_plugin_runner_update_reload:
* @self: a #FuPlugin
+ * @device: A #FuDevice
* @error: a #GError or NULL
*
* Runs reload routine for a device
@@ -1565,11 +1701,10 @@
gboolean
fu_plugin_runner_update_reload (FuPlugin *self, FuDevice *device, GError **error)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
g_autoptr(FuDeviceLocker) locker = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1580,6 +1715,34 @@
}
/**
+ * fu_plugin_runner_add_security_attrs:
+ * @self: a #FuPlugin
+ * @attrs: a #FuSecurityAttrs
+ *
+ * Runs the `add_security_attrs()` routine for the plugin
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_plugin_runner_add_security_attrs (FuPlugin *self, FuSecurityAttrs *attrs)
+{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
+ FuPluginSecurityAttrsFunc func = NULL;
+ const gchar *symbol_name = "fu_plugin_add_security_attrs";
+
+ /* no object loaded */
+ if (priv->module == NULL)
+ return;
+
+ /* optional, but gets called even for disabled plugins */
+ g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
+ if (func == NULL)
+ return;
+ g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
+ func (self, attrs);
+}
+
+/**
* fu_plugin_add_udev_subsystem:
* @self: a #FuPlugin
* @subsystem: a subsystem name, e.g. `pciport`
@@ -1594,6 +1757,8 @@
fu_plugin_add_udev_subsystem (FuPlugin *self, const gchar *subsystem)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
+ if (priv->udev_subsystems == NULL)
+ priv->udev_subsystems = g_ptr_array_new_with_free_func (g_free);
for (guint i = 0; i < priv->udev_subsystems->len; i++) {
const gchar *subsystem_tmp = g_ptr_array_index (priv->udev_subsystems, i);
if (g_strcmp0 (subsystem_tmp, subsystem) == 0)
@@ -1610,7 +1775,7 @@
*
* Sets the device #GType which is used when creating devices.
*
- * If this method is used then fu_plugin_usb_device_added() is not called, and
+ * If this method is used then fu_plugin_backend_device_added() is not called, and
* instead the object is created in the daemon for the plugin.
*
* Plugins can use this method only in fu_plugin_init()
@@ -1624,14 +1789,55 @@
priv->device_gtype = device_gtype;
}
+static gchar *
+fu_common_string_uncamelcase (const gchar *str)
+{
+ GString *tmp = g_string_new (NULL);
+ for (guint i = 0; str[i] != '\0'; i++) {
+ if (g_ascii_islower (str[i]) ||
+ g_ascii_isdigit (str[i])) {
+ g_string_append_c (tmp, str[i]);
+ continue;
+ }
+ if (i > 0)
+ g_string_append_c (tmp, '-');
+ g_string_append_c (tmp, g_ascii_tolower (str[i]));
+ }
+ return g_string_free (tmp, FALSE);
+}
+
+/**
+ * fu_plugin_add_possible_quirk_key:
+ * @self: a #FuPlugin
+ * @possible_key: A quirk string, e.g. `DfuVersion`
+ *
+ * Adds a possible quirk key. If added by a plugin it should be namespaced
+ * using the plugin name, where possible.
+ *
+ * Plugins can use this method only in fu_plugin_init()
+ *
+ * Since: 1.5.8
+ **/
+void
+fu_plugin_add_possible_quirk_key (FuPlugin *self, const gchar *possible_key)
+{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
+ g_return_if_fail (FU_IS_PLUGIN (self));
+ g_return_if_fail (possible_key != NULL);
+ if (priv->quirks == NULL)
+ return;
+ fu_quirks_add_possible_key (priv->quirks, possible_key);
+}
+
/**
* fu_plugin_add_firmware_gtype:
* @self: a #FuPlugin
- * @id: A string describing the type
- * @gtype: a #GType `FU_TYPE_DEVICE`
+ * @id: (nullable): An optional string describing the type, e.g. "ihex"
+ * @gtype: a #GType e.g. `FU_TYPE_FOO_FIRMWARE`
+ *
+ * Adds a firmware #GType which is used when creating devices. If @id is not
+ * specified then it is guessed using the #GType name.
*
- * Adds a firmware #GType which is used when creating devices.
- * *
* Plugins can use this method only in fu_plugin_init()
*
* Since: 1.3.3
@@ -1639,7 +1845,17 @@
void
fu_plugin_add_firmware_gtype (FuPlugin *self, const gchar *id, GType gtype)
{
- g_signal_emit (self, signals[SIGNAL_ADD_FIRMWARE_GTYPE], 0, id, gtype);
+ g_autofree gchar *id_safe = NULL;
+ if (id != NULL) {
+ id_safe = g_strdup (id);
+ } else {
+ g_autoptr(GString) str = g_string_new (g_type_name (gtype));
+ if (g_str_has_prefix (str->str, "Fu"))
+ g_string_erase (str, 0, 2);
+ fu_common_string_replace (str, "Firmware", "");
+ id_safe = fu_common_string_uncamelcase (str->str);
+ }
+ g_signal_emit (self, signals[SIGNAL_ADD_FIRMWARE_GTYPE], 0, id_safe, gtype);
}
static gboolean
@@ -1656,7 +1872,7 @@
}
static gboolean
-fu_plugin_usb_device_added (FuPlugin *self, FuUsbDevice *device, GError **error)
+fu_plugin_backend_device_added (FuPlugin *self, FuDevice *device, GError **error)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
GType device_gtype = fu_device_get_specialized_gtype (FU_DEVICE (device));
@@ -1675,7 +1891,7 @@
/* there are a lot of different devices that match, but not all respond
* well to opening -- so limit some ones with issued updates */
- if (fu_device_has_flag (dev, FWUPD_DEVICE_FLAG_ONLY_SUPPORTED)) {
+ if (fu_device_has_internal_flag (dev, FU_DEVICE_INTERNAL_FLAG_ONLY_SUPPORTED)) {
if (!fu_device_probe (dev, error))
return FALSE;
fu_device_convert_instance_ids (dev);
@@ -1691,57 +1907,7 @@
if (locker == NULL)
return FALSE;
fu_plugin_device_add (self, dev);
- return TRUE;
-}
-
-static gboolean
-fu_plugin_udev_device_changed (FuPlugin *self, FuUdevDevice *device, GError **error)
-{
- g_autoptr(FuDeviceLocker) locker = NULL;
-
- /* open */
- locker = fu_device_locker_new (FU_DEVICE (device), error);
- if (locker == NULL)
- return FALSE;
- return fu_device_rescan (FU_DEVICE (device), error);
-}
-
-static gboolean
-fu_plugin_udev_device_added (FuPlugin *self, FuUdevDevice *device, GError **error)
-{
- FuPluginPrivate *priv = GET_PRIVATE (self);
- GType device_gtype = fu_device_get_specialized_gtype (FU_DEVICE (device));
- g_autoptr(FuDevice) dev = NULL;
- g_autoptr(FuDeviceLocker) locker = NULL;
-
- /* fall back to plugin default */
- if (device_gtype == G_TYPE_INVALID)
- device_gtype = priv->device_gtype;
-
- /* create new device and incorporate existing properties */
- dev = g_object_new (device_gtype, NULL);
- fu_device_incorporate (FU_DEVICE (dev), FU_DEVICE (device));
- if (!fu_plugin_runner_device_created (self, dev, error))
- return FALSE;
-
- /* there are a lot of different devices that match, but not all respond
- * well to opening -- so limit some ones with issued updates */
- if (fu_device_has_flag (dev, FWUPD_DEVICE_FLAG_ONLY_SUPPORTED)) {
- if (!fu_device_probe (dev, error))
- return FALSE;
- fu_device_convert_instance_ids (dev);
- if (!fu_plugin_check_supported_device (self, dev)) {
- g_autofree gchar *guids = fu_device_get_guids_as_str (dev);
- g_debug ("%s has no updates, so ignoring device", guids);
- return TRUE;
- }
- }
-
- /* open and add */
- locker = fu_device_locker_new (dev, error);
- if (locker == NULL)
- return FALSE;
- fu_plugin_device_add (self, FU_DEVICE (dev));
+ fu_plugin_runner_device_added (self, dev);
return TRUE;
}
@@ -1751,7 +1917,7 @@
* @device: a #FuUsbDevice
* @error: a #GError or NULL
*
- * Call the usb_device_added routine for the plugin
+ * Call the backend_device_added routine for the plugin
*
* Returns: #TRUE for success, #FALSE for failure
*
@@ -1760,44 +1926,7 @@
gboolean
fu_plugin_runner_usb_device_added (FuPlugin *self, FuUsbDevice *device, GError **error)
{
- FuPluginPrivate *priv = GET_PRIVATE (self);
- FuPluginUsbDeviceAddedFunc func = NULL;
- g_autoptr(GError) error_local = NULL;
-
- /* not enabled */
- if (!priv->enabled)
- return TRUE;
-
- /* no object loaded */
- if (priv->module == NULL)
- return TRUE;
-
- /* optional */
- g_module_symbol (priv->module, "fu_plugin_usb_device_added", (gpointer *) &func);
- if (func == NULL) {
- if (priv->device_gtype != G_TYPE_INVALID ||
- fu_device_get_specialized_gtype (FU_DEVICE (device)) != G_TYPE_INVALID) {
- if (!fu_plugin_usb_device_added (self, device, error))
- return FALSE;
- }
- return TRUE;
- }
- g_debug ("performing usb_device_added() on %s", priv->name);
- if (!func (self, device, &error_local)) {
- if (error_local == NULL) {
- g_critical ("unset error in plugin %s for usb_device_added()",
- priv->name);
- g_set_error_literal (&error_local,
- FWUPD_ERROR,
- FWUPD_ERROR_INTERNAL,
- "unspecified error");
- }
- g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
- "failed to add device using on %s: ",
- priv->name);
- return FALSE;
- }
- return TRUE;
+ return fu_plugin_runner_backend_device_added (self, FU_DEVICE (device), error);
}
/**
@@ -1806,7 +1935,7 @@
* @device: a #FuUdevDevice
* @error: a #GError or NULL
*
- * Call the udev_device_added routine for the plugin
+ * Call the backend_device_added routine for the plugin
*
* Returns: #TRUE for success, #FALSE for failure
*
@@ -1815,12 +1944,34 @@
gboolean
fu_plugin_runner_udev_device_added (FuPlugin *self, FuUdevDevice *device, GError **error)
{
+ return fu_plugin_runner_backend_device_added (self, FU_DEVICE (device), error);
+}
+
+/**
+ * fu_plugin_runner_backend_device_added:
+ * @self: a #FuPlugin
+ * @device: a #FuDevice
+ * @error: a #GError or NULL
+ *
+ * Call the backend_device_added routine for the plugin
+ *
+ * Returns: #TRUE for success, #FALSE for failure
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_plugin_runner_backend_device_added (FuPlugin *self, FuDevice *device, GError **error)
+{
FuPluginPrivate *priv = GET_PRIVATE (self);
- FuPluginUdevDeviceAddedFunc func = NULL;
+ FuPluginDeviceFunc func = NULL;
g_autoptr(GError) error_local = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1828,20 +1979,23 @@
return TRUE;
/* optional */
- g_module_symbol (priv->module, "fu_plugin_udev_device_added", (gpointer *) &func);
+ g_module_symbol (priv->module, "fu_plugin_backend_device_added", (gpointer *) &func);
if (func == NULL) {
if (priv->device_gtype != G_TYPE_INVALID ||
- fu_device_get_specialized_gtype (FU_DEVICE (device)) != G_TYPE_INVALID) {
- if (!fu_plugin_udev_device_added (self, device, error))
- return FALSE;
+ fu_device_get_specialized_gtype (device) != G_TYPE_INVALID) {
+ return fu_plugin_backend_device_added (self, device, error);
}
- return TRUE;
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INTERNAL,
+ "No device GType set");
+ return FALSE;
}
- g_debug ("performing udev_device_added() on %s", priv->name);
+ g_debug ("backend_device_added(%s)", fu_plugin_get_name (self));
if (!func (self, device, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for udev_device_added()",
- priv->name);
+ g_critical ("unset plugin error in backend_device_added(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1849,7 +2003,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to add device using on %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -1861,7 +2015,7 @@
* @device: a #FuUdevDevice
* @error: a #GError or NULL
*
- * Call the udev_device_changed routine for the plugin
+ * Call the backend_device_changed routine for the plugin
*
* Returns: #TRUE for success, #FALSE for failure
*
@@ -1870,12 +2024,34 @@
gboolean
fu_plugin_runner_udev_device_changed (FuPlugin *self, FuUdevDevice *device, GError **error)
{
+ return fu_plugin_runner_backend_device_changed (self, FU_DEVICE (device), error);
+}
+
+/**
+ * fu_plugin_runner_backend_device_changed:
+ * @self: a #FuPlugin
+ * @device: a #FuDevice
+ * @error: a #GError or NULL
+ *
+ * Call the backend_device_changed routine for the plugin
+ *
+ * Returns: #TRUE for success, #FALSE for failure
+ *
+ * Since: 1.5.6
+ **/
+gboolean
+fu_plugin_runner_backend_device_changed (FuPlugin *self, FuDevice *device, GError **error)
+{
FuPluginPrivate *priv = GET_PRIVATE (self);
- FuPluginUdevDeviceAddedFunc func = NULL;
+ FuPluginDeviceFunc func = NULL;
g_autoptr(GError) error_local = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -1883,20 +2059,14 @@
return TRUE;
/* optional */
- g_module_symbol (priv->module, "fu_plugin_udev_device_changed", (gpointer *) &func);
- if (func == NULL) {
- if (priv->device_gtype != G_TYPE_INVALID ||
- fu_device_get_specialized_gtype (FU_DEVICE (device)) != G_TYPE_INVALID) {
- if (!fu_plugin_udev_device_changed (self, device, error))
- return FALSE;
- }
+ g_module_symbol (priv->module, "fu_plugin_backend_device_changed", (gpointer *) &func);
+ if (func == NULL)
return TRUE;
- }
- g_debug ("performing udev_device_changed() on %s", priv->name);
+ g_debug ("udev_device_changed(%s)", fu_plugin_get_name (self));
if (!func (self, device, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for udev_device_changed()",
- priv->name);
+ g_critical ("unset plugin error in udev_device_changed(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -1904,13 +2074,42 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to change device on %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
}
/**
+ * fu_plugin_runner_device_added:
+ * @self: a #FuPlugin
+ * @device: a #FuDevice
+ *
+ * Call the device_added routine for the plugin
+ *
+ * Since: 1.5.0
+ **/
+void
+fu_plugin_runner_device_added (FuPlugin *self, FuDevice *device)
+{
+ FuPluginPrivate *priv = GET_PRIVATE (self);
+ FuPluginDeviceRegisterFunc func = NULL;
+
+ /* not enabled */
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
+ return;
+ if (priv->module == NULL)
+ return;
+
+ /* optional */
+ g_module_symbol (priv->module, "fu_plugin_device_added", (gpointer *) &func);
+ if (func == NULL)
+ return;
+ g_debug ("fu_plugin_device_added(%s)", fu_plugin_get_name (self));
+ func (self, device);
+}
+
+/**
* fu_plugin_runner_device_removed:
* @self: a #FuPlugin
* @device: a #FuDevice
@@ -1925,7 +2124,7 @@
g_autoptr(GError) error_local= NULL;
if (!fu_plugin_runner_device_generic (self, device,
- "fu_plugin_device_removed",
+ "fu_plugin_backend_device_removed",
NULL,
&error_local))
g_warning ("%s", error_local->message);
@@ -1947,19 +2146,15 @@
FuPluginDeviceRegisterFunc func = NULL;
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return;
if (priv->module == NULL)
return;
- /* don't notify plugins on their own devices */
- if (g_strcmp0 (fu_device_get_plugin (device), fu_plugin_get_name (self)) == 0)
- return;
-
/* optional */
g_module_symbol (priv->module, "fu_plugin_device_registered", (gpointer *) &func);
if (func != NULL) {
- g_debug ("performing fu_plugin_device_registered() on %s", priv->name);
+ g_debug ("fu_plugin_device_registered(%s)", fu_plugin_get_name (self));
func (self, device);
}
}
@@ -1982,8 +2177,12 @@
FuPluginPrivate *priv = GET_PRIVATE (self);
FuPluginDeviceFunc func = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
if (priv->module == NULL)
return TRUE;
@@ -1992,7 +2191,7 @@
g_module_symbol (priv->module, "fu_plugin_device_created", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing fu_plugin_device_created() on %s", priv->name);
+ g_debug ("fu_plugin_device_created(%s)", fu_plugin_get_name (self));
return func (self, device, error);
}
@@ -2020,8 +2219,12 @@
GPtrArray *checksums;
g_autoptr(GError) error_local = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -2031,6 +2234,14 @@
/* optional */
g_module_symbol (priv->module, "fu_plugin_verify", (gpointer *) &func);
if (func == NULL) {
+ if (!fu_device_has_flag (device, FWUPD_DEVICE_FLAG_CAN_VERIFY)) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "device %s does not support verification",
+ fu_device_get_id (device));
+ return FALSE;
+ }
return fu_plugin_device_read_firmware (self, device, error);
}
@@ -2046,12 +2257,12 @@
return FALSE;
/* run vfunc */
- g_debug ("performing verify() on %s", priv->name);
+ g_debug ("verify(%s)", fu_plugin_get_name (self));
if (!func (self, device, flags, &error_local)) {
g_autoptr(GError) error_attach = NULL;
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for verify()",
- priv->name);
+ g_critical ("unset plugin error in verify(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -2059,7 +2270,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to verify using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
/* make the device "work" again, but don't prefix the error */
if (!fu_plugin_runner_device_generic (self, device,
"fu_plugin_update_attach",
@@ -2099,6 +2310,10 @@
{
guint64 flags;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* final check */
flags = fu_device_get_flags (device);
if ((flags & FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION) == 0) {
@@ -2119,6 +2334,12 @@
/* update with correct flags */
fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION);
+
+ /* allow it to be updatable again */
+ if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN)) {
+ fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN);
+ fu_device_add_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE);
+ }
fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
return TRUE;
}
@@ -2140,6 +2361,10 @@
{
guint64 flags;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* final check */
flags = fu_device_get_flags (device);
if ((flags & FWUPD_DEVICE_FLAG_LOCKED) == 0) {
@@ -2159,8 +2384,7 @@
return FALSE;
/* update with correct flags */
- flags = fu_device_get_flags (device);
- fu_device_set_flags (device, flags &= ~FWUPD_DEVICE_FLAG_LOCKED);
+ fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_LOCKED);
fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
return TRUE;
}
@@ -2190,8 +2414,12 @@
FuPluginUpdateFunc update_func;
g_autoptr(GError) error_local = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled) {
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED)) {
g_debug ("plugin not enabled, skipping");
return TRUE;
}
@@ -2205,15 +2433,15 @@
/* optional */
g_module_symbol (priv->module, "fu_plugin_update", (gpointer *) &update_func);
if (update_func == NULL) {
- g_debug ("running superclassed write_firmware() on %s", priv->name);
+ g_debug ("superclassed write_firmware(%s)", fu_plugin_get_name (self));
return fu_plugin_device_write_firmware (self, device, blob_fw, flags, error);
}
/* online */
if (!update_func (self, device, blob_fw, flags, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for update()",
- priv->name);
+ g_critical ("unset plugin error in update(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -2255,8 +2483,12 @@
FuPluginDeviceFunc func = NULL;
g_autoptr(GError) error_local = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -2267,11 +2499,11 @@
g_module_symbol (priv->module, "fu_plugin_clear_results", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing clear_result() on %s", priv->name);
+ g_debug ("clear_result(%s)", fu_plugin_get_name (self));
if (!func (self, device, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for clear_result()",
- priv->name);
+ g_critical ("unset plugin error in clear_result(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -2279,7 +2511,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to clear_result using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -2304,8 +2536,12 @@
FuPluginDeviceFunc func = NULL;
g_autoptr(GError) error_local = NULL;
+ g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
+ g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/* not enabled */
- if (!priv->enabled)
+ if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
return TRUE;
/* no object loaded */
@@ -2316,11 +2552,11 @@
g_module_symbol (priv->module, "fu_plugin_get_results", (gpointer *) &func);
if (func == NULL)
return TRUE;
- g_debug ("performing get_results() on %s", priv->name);
+ g_debug ("get_results(%s)", fu_plugin_get_name (self));
if (!func (self, device, &error_local)) {
if (error_local == NULL) {
- g_critical ("unset error in plugin %s for get_results()",
- priv->name);
+ g_critical ("unset plugin error in get_results(%s)",
+ fu_plugin_get_name (self));
g_set_error_literal (&error_local,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
@@ -2328,7 +2564,7 @@
}
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
"failed to get_results using %s: ",
- priv->name);
+ fu_plugin_get_name (self));
return FALSE;
}
return TRUE;
@@ -2421,6 +2657,8 @@
fu_plugin_add_rule (FuPlugin *self, FuPluginRule rule, const gchar *name)
{
FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
+ if (priv->rules[rule] == NULL)
+ priv->rules[rule] = g_ptr_array_new_with_free_func (g_free);
g_ptr_array_add (priv->rules[rule], g_strdup (name));
g_signal_emit (self, signals[SIGNAL_RULES_CHANGED], 0);
}
@@ -2432,7 +2670,7 @@
*
* Gets the plugin IDs that should be run after this plugin.
*
- * Returns: (element-type utf8) (transfer none): the list of plugin names, e.g. ['appstream']
+ * Returns: (element-type utf8) (transfer none) (nullable): the list of plugin names, e.g. ['appstream']
*
* Since: 1.0.0
**/
@@ -2460,6 +2698,8 @@
fu_plugin_has_rule (FuPlugin *self, FuPluginRule rule, const gchar *name)
{
FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
+ if (priv->rules[rule] == NULL)
+ return FALSE;
for (guint i = 0; i < priv->rules[rule]->len; i++) {
const gchar *tmp = g_ptr_array_index (priv->rules[rule], i);
if (g_strcmp0 (tmp, name) == 0)
@@ -2486,6 +2726,12 @@
fu_plugin_add_report_metadata (FuPlugin *self, const gchar *key, const gchar *value)
{
FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
+ if (priv->report_metadata == NULL) {
+ priv->report_metadata = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+ }
g_hash_table_insert (priv->report_metadata, g_strdup (key), g_strdup (value));
}
@@ -2495,7 +2741,7 @@
*
* Returns the list of additional metadata to be added when filing a report.
*
- * Returns: (transfer none): the map of report metadata
+ * Returns: (transfer none) (nullable): the map of report metadata
*
* Since: 1.0.4
**/
@@ -2571,9 +2817,7 @@
gint
fu_plugin_name_compare (FuPlugin *plugin1, FuPlugin *plugin2)
{
- FuPluginPrivate *priv1 = fu_plugin_get_instance_private (plugin1);
- FuPluginPrivate *priv2 = fu_plugin_get_instance_private (plugin2);
- return g_strcmp0 (priv1->name, priv2->name);
+ return g_strcmp0 (fu_plugin_get_name (plugin1), fu_plugin_get_name (plugin2));
}
/**
@@ -2628,6 +2872,12 @@
G_STRUCT_OFFSET (FuPluginClass, recoldplug),
NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ signals[SIGNAL_SECURITY_CHANGED] =
+ g_signal_new ("security-changed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (FuPluginClass, security_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
signals[SIGNAL_SET_COLDPLUG_DELAY] =
g_signal_new ("set-coldplug-delay",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
@@ -2658,14 +2908,7 @@
fu_plugin_init (FuPlugin *self)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
- priv->enabled = TRUE;
- priv->udev_subsystems = g_ptr_array_new_with_free_func (g_free);
- priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_object_unref);
- g_rw_lock_init (&priv->devices_mutex);
- priv->report_metadata = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- for (guint i = 0; i < FU_PLUGIN_RULE_LAST; i++)
- priv->rules[i] = g_ptr_array_new_with_free_func (g_free);
+ g_rw_lock_init (&priv->cache_mutex);
}
static void
@@ -2675,20 +2918,23 @@
FuPluginPrivate *priv = GET_PRIVATE (self);
FuPluginInitFunc func = NULL;
+ g_rw_lock_clear (&priv->cache_mutex);
+
/* optional */
if (priv->module != NULL) {
g_module_symbol (priv->module, "fu_plugin_destroy", (gpointer *) &func);
if (func != NULL) {
- g_debug ("performing destroy() on %s", priv->name);
+ g_debug ("destroy(%s)", fu_plugin_get_name (self));
func (self);
}
}
- for (guint i = 0; i < FU_PLUGIN_RULE_LAST; i++)
- g_ptr_array_unref (priv->rules[i]);
-
- if (priv->usb_ctx != NULL)
- g_object_unref (priv->usb_ctx);
+ for (guint i = 0; i < FU_PLUGIN_RULE_LAST; i++) {
+ if (priv->rules[i] != NULL)
+ g_ptr_array_unref (priv->rules[i]);
+ }
+ if (priv->devices != NULL)
+ g_ptr_array_unref (priv->devices);
if (priv->hwids != NULL)
g_object_unref (priv->hwids);
if (priv->quirks != NULL)
@@ -2701,18 +2947,20 @@
g_hash_table_unref (priv->runtime_versions);
if (priv->compile_versions != NULL)
g_hash_table_unref (priv->compile_versions);
- g_hash_table_unref (priv->devices);
- g_hash_table_unref (priv->report_metadata);
- g_rw_lock_clear (&priv->devices_mutex);
+ if (priv->report_metadata != NULL)
+ g_hash_table_unref (priv->report_metadata);
+ if (priv->cache != NULL)
+ g_hash_table_unref (priv->cache);
g_free (priv->build_hash);
- g_free (priv->name);
g_free (priv->data);
/* Must happen as the last step to avoid prematurely
* freeing memory held by the plugin */
-#ifndef RUNNING_ON_VALGRIND
+#ifdef RUNNING_ON_VALGRIND
+ if (priv->module != NULL && RUNNING_ON_VALGRIND == 0)
+#else
if (priv->module != NULL)
- g_module_close (priv->module);
#endif
+ g_module_close (priv->module);
G_OBJECT_CLASS (fu_plugin_parent_class)->finalize (object);
}
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-plugin.h fwupd-1.5.8/libfwupdplugin/fu-plugin.h
--- fwupd-1.4.5/libfwupdplugin/fu-plugin.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-plugin.h 2021-03-31 20:08:32.000000000 +0000
@@ -7,8 +7,11 @@
#pragma once
#include
+#ifdef HAVE_GUSB
#include
+#endif
+#include "fu-bluez-device.h"
#include "fu-common.h"
#include "fu-common-guid.h"
#include "fu-common-version.h"
@@ -21,14 +24,20 @@
#ifdef HAVE_GUDEV
#include "fu-udev-device.h"
#endif
-#include "fwupd-common.h"
+#include
+#include
#define FU_TYPE_PLUGIN (fu_plugin_get_type ())
-G_DECLARE_DERIVABLE_TYPE (FuPlugin, fu_plugin, FU, PLUGIN, GObject)
+G_DECLARE_DERIVABLE_TYPE (FuPlugin, fu_plugin, FU, PLUGIN, FwupdPlugin)
+
+#define fu_plugin_get_flags(p) fwupd_plugin_get_flags(FWUPD_PLUGIN(p))
+#define fu_plugin_has_flag(p,f) fwupd_plugin_has_flag(FWUPD_PLUGIN(p),f)
+#define fu_plugin_add_flag(p,f) fwupd_plugin_add_flag(FWUPD_PLUGIN(p),f)
+#define fu_plugin_remove_flag(p,f) fwupd_plugin_remove_flag(FWUPD_PLUGIN(p),f)
struct _FuPluginClass
{
- GObjectClass parent_class;
+ FwupdPluginClass parent_class;
/* signals */
void (* device_added) (FuPlugin *self,
FuDevice *device);
@@ -49,8 +58,9 @@
gboolean (* add_firmware_gtype) (FuPlugin *self,
const gchar *id,
GType gtype);
+ void (* security_changed) (FuPlugin *self);
/*< private >*/
- gpointer padding[21];
+ gpointer padding[20];
};
/**
@@ -95,9 +105,11 @@
FuPluginData *fu_plugin_get_data (FuPlugin *self);
FuPluginData *fu_plugin_alloc_data (FuPlugin *self,
gsize data_sz);
-gboolean fu_plugin_get_enabled (FuPlugin *self);
+gboolean fu_plugin_get_enabled (FuPlugin *self)
+G_DEPRECATED_FOR(fu_plugin_has_flag);
void fu_plugin_set_enabled (FuPlugin *self,
- gboolean enabled);
+ gboolean enabled)
+G_DEPRECATED_FOR(fu_plugin_add_flag);
void fu_plugin_set_build_hash (FuPlugin *self,
const gchar *build_hash);
GUsbContext *fu_plugin_get_usb_context (FuPlugin *self);
@@ -108,6 +120,7 @@
void fu_plugin_device_register (FuPlugin *self,
FuDevice *device);
void fu_plugin_request_recoldplug (FuPlugin *self);
+void fu_plugin_security_changed (FuPlugin *self);
void fu_plugin_set_coldplug_delay (FuPlugin *self,
guint duration);
void fu_plugin_set_device_gtype (FuPlugin *self,
@@ -115,6 +128,8 @@
void fu_plugin_add_firmware_gtype (FuPlugin *self,
const gchar *id,
GType gtype);
+void fu_plugin_add_possible_quirk_key (FuPlugin *self,
+ const gchar *possible_key);
gpointer fu_plugin_cache_lookup (FuPlugin *self,
const gchar *id);
void fu_plugin_cache_remove (FuPlugin *self,
@@ -126,7 +141,9 @@
const gchar *hwid);
gchar *fu_plugin_get_hwid_replace_value (FuPlugin *self,
const gchar *keys,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+GPtrArray *fu_plugin_get_devices (FuPlugin *self);
GPtrArray *fu_plugin_get_hwids (FuPlugin *self);
const gchar *fu_plugin_get_dmi_value (FuPlugin *self,
const gchar *dmi_id);
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-plugin-private.h fwupd-1.5.8/libfwupdplugin/fu-plugin-private.h
--- fwupd-1.4.5/libfwupdplugin/fu-plugin-private.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-plugin-private.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2018 Richard Hughes
+ * Copyright (C) 2016 Richard Hughes
*
* SPDX-License-Identifier: LGPL-2.1+
*/
@@ -8,6 +8,7 @@
#include "fu-quirks.h"
#include "fu-plugin.h"
+#include "fu-security-attrs.h"
#include "fu-smbios.h"
FuPlugin *fu_plugin_new (void);
@@ -43,52 +44,82 @@
GHashTable *fu_plugin_get_report_metadata (FuPlugin *self);
gboolean fu_plugin_open (FuPlugin *self,
const gchar *filename,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_startup (FuPlugin *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_coldplug (FuPlugin *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_coldplug_prepare (FuPlugin *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_coldplug_cleanup (FuPlugin *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_recoldplug (FuPlugin *self,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_update_prepare (FuPlugin *self,
FwupdInstallFlags flags,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_update_cleanup (FuPlugin *self,
FwupdInstallFlags flags,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_composite_prepare (FuPlugin *self,
GPtrArray *devices,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_composite_cleanup (FuPlugin *self,
GPtrArray *devices,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_update_attach (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_update_detach (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_update_reload (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+G_DEPRECATED_FOR(fu_plugin_runner_backend_device_added)
gboolean fu_plugin_runner_usb_device_added (FuPlugin *self,
FuUsbDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+G_DEPRECATED_FOR(fu_plugin_runner_backend_device_added)
gboolean fu_plugin_runner_udev_device_added (FuPlugin *self,
FuUdevDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+G_DEPRECATED_FOR(fu_plugin_runner_backend_device_changed)
gboolean fu_plugin_runner_udev_device_changed (FuPlugin *self,
FuUdevDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_plugin_runner_backend_device_added (FuPlugin *self,
+ FuDevice *device,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+gboolean fu_plugin_runner_backend_device_changed (FuPlugin *self,
+ FuDevice *device,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_device_created (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fu_plugin_runner_device_added (FuPlugin *self,
+ FuDevice *device);
void fu_plugin_runner_device_removed (FuPlugin *self,
FuDevice *device);
void fu_plugin_runner_device_register (FuPlugin *self,
@@ -97,23 +128,30 @@
FuDevice *device,
GBytes *blob_fw,
FwupdInstallFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_verify (FuPlugin *self,
FuDevice *device,
FuPluginVerifyFlags flags,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_activate (FuPlugin *self,
FuDevice *device,
GError **error);
gboolean fu_plugin_runner_unlock (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_clear_results (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_plugin_runner_get_results (FuPlugin *self,
FuDevice *device,
- GError **error);
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+void fu_plugin_runner_add_security_attrs (FuPlugin *self,
+ FuSecurityAttrs*attrs);
gint fu_plugin_name_compare (FuPlugin *plugin1,
FuPlugin *plugin2);
gint fu_plugin_order_compare (FuPlugin *plugin1,
diff -Nru fwupd-1.4.5/libfwupdplugin/fu-plugin-vfuncs.h fwupd-1.5.8/libfwupdplugin/fu-plugin-vfuncs.h
--- fwupd-1.4.5/libfwupdplugin/fu-plugin-vfuncs.h 2021-01-26 16:06:40.000000000 +0000
+++ fwupd-1.5.8/libfwupdplugin/fu-plugin-vfuncs.h 2021-03-31 20:08:32.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Richard Hughes
+ * Copyright (C) 2016 Richard Hughes