This allows us to 'nest' firmware formats, and removes a ton of duplication.
The aim here is to deprecate FuFirmwareImage -- it's almost always acting
as a 'child' FuFirmware instance, and even copies most of the vfuncs to allow
custom types. If I'm struggling to work out what should be a FuFirmware and
what should be a FuFirmwareImage then a plugin author has no hope.
For simple payloads we were adding bytes into an image and then the image into
a firmware. This gets really messy when most plugins are treating the FuFirmware
*as* the binary firmware file.
The GBytes saved in the FuFirmware would be considered the payload with the
aim of not using FuFirmwareImage in the single-image case.
Rather than trying to guess typos, force each plugin to register the quirk
keys it supports, so we can show a sensible warning if required at startup on
the console.
The best way of not getting something wrong is to not require it in the first
place...
All plugins now use DeviceInstanceId-style quirk matches and we can just drop
the prefix in all files. We were treating HwId=, Guid= and DeviceInstanceId= in
exactly the same way -- they're just converted to GUIDs when building the silo!
Devices may want to support more than one protocol, and for some devices
(e.g. Unifying peripherals stuck in bootloader mode) you might not even be able
to query for the correct protocol anyway.
It is far too easy to forget to set FWUPD_DEVICE_FLAG_NO_GUID_MATCHING for new
plugins, and without it it all works really well *until* a user has two devices
of the same type installed at the same time and then one 'disappears' for hard
to explain reasons. Typically we only need it for replug anyway!
Explicitly opt-in to this rarely-required behaviour, with the default to just
use the physical and logical IDs. Also document the update behavior for each
plugin to explain why the flag is being used.
This allows you to have two identical Unifying plugged in without one of them
being hidden from the user, at the same time allowing a HIDRAW<->USB transition
when going to and from bootloader and runtime modes.
This removes the workaround added in 99eb3f06b6.
Fixes https://github.com/fwupd/fwupd/issues/2915
This allows a device subclass to call the parent method after doing an initial
action, or even deliberately not call the *generic* parent method at all.
It also simplifies the plugins; you no longer have to remember what the plugin
is deriving from and accidentally clobber the wrong superclass method.
At the moment FuChunks are sometimes mutable, and sometimes immutable, and it's
all a bit too low level for comfort.
Before we can do any kind of optimisation or verification we need plugins to
stop reading directly from the C structure. The aim here is to make FuChunk
optionally mutable without making assumptions about the memory model, and also
to be able to introspect it for the docs.
This bootloader is *weird* -- the chip ID is the first two bytes of the serial
number and the data is offset and encoded in UTF-8, not UTF-16.
The sector information is also wrong. Gah!
When this is done, include:
* Including the hash
* Including anything that is not ABI stable in plugins yet
Suggested-by: Simon McVittie <smcv@debian.org>
The end year is legally and functionally redundant, and more importantly causes
cherry-pick conflicts when trying to maintain old branches. Use git for history.
This is probably a case where the device does not adhere to the specification.
Some hardware may be deliberately setting DNLOAD timeout to 0ms, and this patch
will make each request 5ms slower. This is probably a good tradeoff for having
most hardware 'just work' without a quirk entry.
Based on a patch by Zack Lee Yi Wei <zack_lee@chicony.com>, many thanks.
This has better multi-core performance and can run in persistent mode -- which
allows us to construct a test harness of all the parsers (which takes time) and
then just reuse the process for lots of different data.
This is a safer version of g_bytes_new_from_bytes() which returns a GError
if the offsets are invalid rather than emitting a critical warning.
This prevents a critical warning and potential crash when parsing invalid
bcm57xx firmware.
The FWUPD_INSTALL_FLAG_FORCE flag has really unclear semantics, and ignoring a
file CRC, checksum or model ID should only be done when using fwupdtool actually
debugging a plugin or firmware parser.
Use the existing --force flag when we want a "gentle nudge" like reuploading
previously processed reports.
This allows us to handle this in the plugin, which might mean detaching the
*proxy* device. It's also very important as a few plugins reboot the device
in ->attach() to get the new firmware version, which isn't required for a dump.
This partially reverts a58510b246 and does the
detach and attach in the few plugins where actually required.
Conceptually we were trying to stuff subtly different actions into one vfunc:
* Read firmware from the device to update the verification checksums
* Read a firmware blob from the device for debugging
For the first action we might want to mask out the sections of the flash with
serial numbers (so the verification hashes match the ones published on the LVFS)
and for the second we want just a raw ROM file from the hardware with no
pre-processing that we can compare against an external SPI dumper.
Split out ->dump_firmware to get the raw blob, and allow plugins to also
implement ->read_firmware() if they have to mask out specific offsets or remove
specific images from the FuFirmware container.
In the common case when masking is not required, fall back to using a 'binary'
FuFirmware automatically to make most plugins simpler.
At the moment there are commands to convert one file format to another, but not
to 'merge' or alter them. Some firmware files are containers which can store
multiple images, each with optional id, idx and addresses.
This would allow us to, for instance, create a DfuSe file with two different
raw files that are flashed to different addresses on the SPI flash. It would
also allow us to create very small complicated container formats for fuzzing.
This can be used by writing a `firmware.builder.xml` file like:
<?xml version="1.0" encoding="UTF-8"?>
<firmware gtype="FuBcm57xxFirmware">
<version>1.2.3</version>
<image>
<version>4.5.6</version>
<id>header</id>
<idx>456</idx>
<addr>0x456</addr>
<filename>header.bin</filename>
</image>
<image>
<version>7.8.9</version>
<id>payload</id>
<idx>789</idx>
<addr>0x789</addr>
<data>aGVsbG8=</data>
</image>
</firmware>
...and then using something like:
# fwupdtool firmware-convert firmware.builder.xml firmware.dfu builder dfu
As described in DFU protocol (7. Manifestation Phase), after the
firmware reprogramming is done, if bitWillDetach = 1, it doesn't
require the host to issue a USB bus reset, but the device can
generate a detach-attach sequence itself to go back to normal.
Add a quirk flag "no-bus-reset-attach" to skip the bus reset in
dfu_device_attach(), and increase the "RemoveDelay" as well.
For some Poly USB Cameras, it takes a longer time than the
default (FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE) for being detached
to DFU or attached to normal mode. Need to specify the timeout in
"RemoveDelay" quirk key.
Also replace the hard-coded timeout with fu_device_get_remove_delay()
in dfu-tool.c.
Some devices may accumulate the firmware image and perform the
entire reprogramming operation at one time. In this case, the
device enters dfuMANIFEST-SYNC or dfuMANIFEST state after
dfuDNLOAD-IDLE.
The fwupd shall be able to poll the status from the device via
DFU_GETSTATUS until the device completes the reprogramming or
reports an error.
For details, please refer to Section 7. Manifestation Phase and
A.1 Interface State Transition Diagram in the USB DFU protocol.
https://www.usb.org/sites/default/files/DFU_1.1.pdf
For not affecting the other DFU capable devices, introduce a quirk
"manifest-poll" to limit the logic.
The nr_chunks is defined as an unsigned short, the max value is
65536. Assume the transfer_size reported by device is 4096, the
maximum size of DFU firmware supported is 65536 * 4096 = 256MB.
To support larger DFU firmware, we can change the guint16 to
guint32.