mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-03 06:09:51 +00:00
trivial: Allow setting the firmware min and max sizes from quirk files
This commit is contained in:
parent
a62618303f
commit
a417d6c82a
@ -3,6 +3,8 @@
|
||||
Plugin = colorhug
|
||||
Flags = is-bootloader
|
||||
Guid = 40338ceb-b966-4eae-adae-9c32edfcc484
|
||||
FirmwareSizeMin = 0x2000
|
||||
FirmwareSizeMax = 0x8000
|
||||
[DeviceInstanceId=USB\VID_273F&PID_1001]
|
||||
Plugin = colorhug
|
||||
Flags = none
|
||||
@ -17,6 +19,8 @@ Flags = none
|
||||
Summary = An open source display colorimeter
|
||||
Icon = colorimeter-colorhug
|
||||
Guid = 2082b5e0-7a64-478a-b1b2-e3404fab6dad
|
||||
FirmwareSizeMin = 0x2000
|
||||
FirmwareSizeMax = 0x8000
|
||||
[DeviceInstanceId=USB\VID_273F&PID_1005]
|
||||
Plugin = colorhug
|
||||
Flags = is-bootloader
|
||||
@ -28,6 +32,8 @@ Plugin = colorhug
|
||||
Flags = halfsize,none
|
||||
Summary = An open source ambient light sensor
|
||||
Guid = 84f40464-9272-4ef7-9399-cd95f12da696
|
||||
FirmwareSizeMin = 0x1000
|
||||
FirmwareSizeMax = 0x4000
|
||||
[DeviceInstanceId=USB\VID_273F&PID_1006]
|
||||
Plugin = colorhug
|
||||
Flags = halfsize,is-bootloader
|
||||
|
@ -437,25 +437,16 @@ _dfu_firmware_get_default_element_data (DfuFirmware *firmware)
|
||||
return dfu_element_get_contents (element);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_csr_device_download (FuDevice *device, GBytes *blob, GError **error)
|
||||
static GBytes *
|
||||
fu_csr_device_prepare_firmware (FuDevice *device, GBytes *fw, GError **error)
|
||||
{
|
||||
FuCsrDevice *self = FU_CSR_DEVICE (device);
|
||||
GBytes *blob_noftr;
|
||||
const guint8 *data;
|
||||
gsize sz = 0;
|
||||
guint16 idx;
|
||||
g_autoptr(DfuFirmware) dfu_firmware = dfu_firmware_new ();
|
||||
g_autoptr(GBytes) blob_empty = NULL;
|
||||
g_autoptr(GPtrArray) chunks = NULL;
|
||||
|
||||
/* notify UI */
|
||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
|
||||
|
||||
/* parse the file */
|
||||
if (!dfu_firmware_parse_data (dfu_firmware, blob,
|
||||
if (!dfu_firmware_parse_data (dfu_firmware, fw,
|
||||
DFU_FIRMWARE_PARSE_FLAG_NONE, error))
|
||||
return FALSE;
|
||||
return NULL;
|
||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL) {
|
||||
g_autofree gchar *fw_str = NULL;
|
||||
fw_str = dfu_firmware_to_string (dfu_firmware);
|
||||
@ -466,7 +457,7 @@ fu_csr_device_download (FuDevice *device, GBytes *blob, GError **error)
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"expected DFU firmware");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the blob from the firmware file */
|
||||
@ -476,13 +467,27 @@ fu_csr_device_download (FuDevice *device, GBytes *blob, GError **error)
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"firmware contained no data");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return g_bytes_ref (blob_noftr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_csr_device_download (FuDevice *device, GBytes *blob, GError **error)
|
||||
{
|
||||
FuCsrDevice *self = FU_CSR_DEVICE (device);
|
||||
guint16 idx;
|
||||
g_autoptr(GBytes) blob_empty = NULL;
|
||||
g_autoptr(GPtrArray) chunks = NULL;
|
||||
|
||||
/* notify UI */
|
||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
|
||||
|
||||
/* create chunks */
|
||||
data = g_bytes_get_data (blob_noftr, &sz);
|
||||
chunks = fu_chunk_array_new (data, (guint32) sz, 0x0, 0x0,
|
||||
FU_CSR_PACKET_DATA_SIZE - FU_CSR_COMMAND_HEADER_SIZE);
|
||||
chunks = fu_chunk_array_new_from_bytes (blob, 0x0, 0x0,
|
||||
FU_CSR_PACKET_DATA_SIZE - FU_CSR_COMMAND_HEADER_SIZE);
|
||||
|
||||
/* send to hardware */
|
||||
for (idx = 0; idx < chunks->len; idx++) {
|
||||
@ -576,6 +581,7 @@ fu_csr_device_class_init (FuCsrDeviceClass *klass)
|
||||
klass_device->to_string = fu_csr_device_to_string;
|
||||
klass_device->write_firmware = fu_csr_device_download;
|
||||
klass_device->read_firmware = fu_csr_device_upload;
|
||||
klass_device->prepare_firmware = fu_csr_device_prepare_firmware;
|
||||
klass_device->attach = fu_csr_device_attach;
|
||||
klass_usb_device->open = fu_csr_device_open;
|
||||
klass_usb_device->close = fu_csr_device_close;
|
||||
|
@ -899,15 +899,6 @@ lu_device_write_firmware (FuDevice *device, GBytes *fw, GError **error)
|
||||
g_return_val_if_fail (LU_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
/* corrupt */
|
||||
if (g_bytes_get_size (fw) < 0x4000) {
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"firmware is too small");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* call device-specific method */
|
||||
if (klass->write_firmware == NULL) {
|
||||
g_set_error (error,
|
||||
|
@ -1,5 +1,11 @@
|
||||
cargs = ['-DG_LOG_DOMAIN="FuPluginUnifying"']
|
||||
|
||||
install_data([
|
||||
'unifying.quirk',
|
||||
],
|
||||
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
|
||||
)
|
||||
|
||||
shared_module('fu_plugin_unifying',
|
||||
sources : [
|
||||
'fu-plugin-unifying.c',
|
||||
|
19
plugins/unifying/unifying.quirk
Normal file
19
plugins/unifying/unifying.quirk
Normal file
@ -0,0 +1,19 @@
|
||||
# Nordic
|
||||
[DeviceInstanceId=USB\VID_046D&PID_AAAA]
|
||||
Plugin = unifying
|
||||
FirmwareSizeMin = 0x4000
|
||||
|
||||
# Nordic Pico
|
||||
[DeviceInstanceId=USB\VID_046D&PID_AAAE]
|
||||
Plugin = unifying
|
||||
FirmwareSizeMin = 0x4000
|
||||
|
||||
# Nordic
|
||||
[DeviceInstanceId=USB\VID_046D&PID_AAAC]
|
||||
Plugin = unifying
|
||||
FirmwareSizeMin = 0x4000
|
||||
|
||||
# Nordic Pico
|
||||
[DeviceInstanceId=USB\VID_046D&PID_AAAD]
|
||||
Plugin = unifying
|
||||
FirmwareSizeMin = 0x4000
|
125
src/fu-device.c
125
src/fu-device.c
@ -41,6 +41,8 @@ typedef struct {
|
||||
guint order;
|
||||
guint priority;
|
||||
gboolean done_probe;
|
||||
guint64 size_min;
|
||||
guint64 size_max;
|
||||
} FuDevicePrivate;
|
||||
|
||||
enum {
|
||||
@ -549,6 +551,14 @@ fu_device_add_guid_quirks (FuDevice *device, const gchar *guid)
|
||||
if (tmp != NULL)
|
||||
fu_device_add_parent_guid (device, tmp);
|
||||
|
||||
/* firmware size */
|
||||
tmp = fu_quirks_lookup_by_guid (priv->quirks, guid, FU_QUIRKS_FIRMWARE_SIZE_MIN);
|
||||
if (tmp != NULL)
|
||||
fu_device_set_firmware_size_min (device, fu_common_strtoull (tmp));
|
||||
tmp = fu_quirks_lookup_by_guid (priv->quirks, guid, FU_QUIRKS_FIRMWARE_SIZE_MAX);
|
||||
if (tmp != NULL)
|
||||
fu_device_set_firmware_size_max (device, fu_common_strtoull (tmp));
|
||||
|
||||
/* children */
|
||||
tmp = fu_quirks_lookup_by_guid (priv->quirks, guid, FU_QUIRKS_CHILDREN);
|
||||
if (tmp != NULL) {
|
||||
@ -563,6 +573,40 @@ fu_device_add_guid_quirks (FuDevice *device, const gchar *guid)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_device_set_firmware_size_min:
|
||||
* @device: A #FuDevice
|
||||
* @size_min: Size in bytes
|
||||
*
|
||||
* Sets the minimum allowed size of the firmware blob.
|
||||
*
|
||||
* Since: 1.1.2
|
||||
**/
|
||||
void
|
||||
fu_device_set_firmware_size_min (FuDevice *device, guint64 size_min)
|
||||
{
|
||||
FuDevicePrivate *priv = GET_PRIVATE (device);
|
||||
g_return_if_fail (FU_IS_DEVICE (device));
|
||||
priv->size_min = size_min;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_device_set_firmware_size_max:
|
||||
* @device: A #FuDevice
|
||||
* @size_min: Size in bytes
|
||||
*
|
||||
* Sets the maximum allowed size of the firmware blob.
|
||||
*
|
||||
* Since: 1.1.2
|
||||
**/
|
||||
void
|
||||
fu_device_set_firmware_size_max (FuDevice *device, guint64 size_max)
|
||||
{
|
||||
FuDevicePrivate *priv = GET_PRIVATE (device);
|
||||
g_return_if_fail (FU_IS_DEVICE (device));
|
||||
priv->size_max = size_max;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_device_add_guid_safe (FuDevice *device, const gchar *guid)
|
||||
{
|
||||
@ -1169,6 +1213,14 @@ fu_device_to_string (FuDevice *device)
|
||||
fwupd_pad_kv_str (str, "AlternateId", priv->alternate_id);
|
||||
if (priv->equivalent_id != NULL)
|
||||
fwupd_pad_kv_str (str, "EquivalentId", priv->equivalent_id);
|
||||
if (priv->size_min > 0) {
|
||||
g_autofree gchar *sz = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->size_min);
|
||||
fwupd_pad_kv_str (str, "FirmwareSizeMin", sz);
|
||||
}
|
||||
if (priv->size_max > 0) {
|
||||
g_autofree gchar *sz = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->size_max);
|
||||
fwupd_pad_kv_str (str, "FirmwareSizeMax", sz);
|
||||
}
|
||||
keys = g_hash_table_get_keys (priv->metadata);
|
||||
for (GList *l = keys; l != NULL; l = l->next) {
|
||||
const gchar *key = l->data;
|
||||
@ -1258,6 +1310,7 @@ gboolean
|
||||
fu_device_write_firmware (FuDevice *device, GBytes *fw, GError **error)
|
||||
{
|
||||
FuDeviceClass *klass = FU_DEVICE_GET_CLASS (device);
|
||||
g_autoptr(GBytes) fw_new = NULL;
|
||||
|
||||
g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
@ -1271,8 +1324,78 @@ fu_device_write_firmware (FuDevice *device, GBytes *fw, GError **error)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* prepare (e.g. decompress) firmware */
|
||||
fw_new = fu_device_prepare_firmware (device, fw, error);
|
||||
if (fw_new == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* call vfunc */
|
||||
return klass->write_firmware (device, fw, error);
|
||||
return klass->write_firmware (device, fw_new, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_device_prepare_firmware:
|
||||
* @device: A #FuDevice
|
||||
* @fw: A #GBytes
|
||||
* @error: A #GError
|
||||
*
|
||||
* Prepares the firmware by calling an optional device-specific vfunc for the
|
||||
* device, which can do things like decompressing or parsing of the firmware
|
||||
* data.
|
||||
*
|
||||
* For all firmware, this checks the size of the firmware if limits have been
|
||||
* set using fu_device_set_firmware_size_min(), fu_device_set_firmware_size_max()
|
||||
* or using a quirk entry.
|
||||
*
|
||||
* Returns: (return full): A new #GBytes, or %NULL for error
|
||||
*
|
||||
* Since: 1.1.2
|
||||
**/
|
||||
GBytes *
|
||||
fu_device_prepare_firmware (FuDevice *device, GBytes *fw, GError **error)
|
||||
{
|
||||
FuDeviceClass *klass = FU_DEVICE_GET_CLASS (device);
|
||||
FuDevicePrivate *priv = GET_PRIVATE (device);
|
||||
guint64 fw_sz;
|
||||
g_autoptr(GBytes) fw_new = NULL;
|
||||
|
||||
g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (fw != NULL, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
/* optionally subclassed */
|
||||
if (klass->prepare_firmware != NULL) {
|
||||
fw_new = klass->prepare_firmware (device, fw, error);
|
||||
if (fw_new == NULL)
|
||||
return FALSE;
|
||||
} else {
|
||||
fw_new = g_bytes_ref (fw);
|
||||
}
|
||||
|
||||
/* check size */
|
||||
fw_sz = (guint64) g_bytes_get_size (fw_new);
|
||||
if (priv->size_max > 0 && fw_sz > priv->size_max) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"firmware is %04x bytes larger than the allowed "
|
||||
"maximum size of %04x bytes",
|
||||
(guint) (fw_sz - priv->size_max),
|
||||
(guint) priv->size_max);
|
||||
return FALSE;
|
||||
}
|
||||
if (priv->size_min > 0 && fw_sz < priv->size_min) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"firmware is %04x bytes smaller than the allowed "
|
||||
"minimum size of %04x bytes",
|
||||
(guint) (priv->size_min - fw_sz),
|
||||
(guint) priv->size_max);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_steal_pointer (&fw_new);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,8 +37,11 @@ struct _FuDeviceClass
|
||||
GError **error);
|
||||
gboolean (*probe) (FuDevice *device,
|
||||
GError **error);
|
||||
GBytes *(*prepare_firmware) (FuDevice *device,
|
||||
GBytes *fw,
|
||||
GError **error);
|
||||
/*< private >*/
|
||||
gpointer padding[25];
|
||||
gpointer padding[24];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -157,6 +160,10 @@ void fu_device_set_remove_delay (FuDevice *device,
|
||||
FwupdStatus fu_device_get_status (FuDevice *device);
|
||||
void fu_device_set_status (FuDevice *device,
|
||||
FwupdStatus status);
|
||||
void fu_device_set_firmware_size_min (FuDevice *device,
|
||||
guint64 size_min);
|
||||
void fu_device_set_firmware_size_max (FuDevice *device,
|
||||
guint64 size_max);
|
||||
guint fu_device_get_progress (FuDevice *device);
|
||||
void fu_device_set_progress (FuDevice *device,
|
||||
guint progress);
|
||||
@ -170,6 +177,9 @@ FwupdRelease *fu_device_get_release_default (FuDevice *device);
|
||||
gboolean fu_device_write_firmware (FuDevice *device,
|
||||
GBytes *fw,
|
||||
GError **error);
|
||||
GBytes *fu_device_prepare_firmware (FuDevice *device,
|
||||
GBytes *fw,
|
||||
GError **error);
|
||||
GBytes *fu_device_read_firmware (FuDevice *device,
|
||||
GError **error);
|
||||
gboolean fu_device_attach (FuDevice *device,
|
||||
|
@ -181,6 +181,28 @@ gchar *fu_quirks_lookup_by_guids (FuQuirks *self,
|
||||
*/
|
||||
#define FU_QUIRKS_VENDOR "Vendor"
|
||||
|
||||
/**
|
||||
* FU_QUIRKS_FIRMWARE_SIZE_MIN:
|
||||
* @key: the USB device ID, e.g. `DeviceInstanceId=USB\VID_0763&PID_2806`
|
||||
* @value: the vendor, e.g. `0x10000`
|
||||
*
|
||||
* Sets the minimum allowed firmware size.
|
||||
*
|
||||
* Since: 1.1.2
|
||||
*/
|
||||
#define FU_QUIRKS_FIRMWARE_SIZE_MIN "FirmwareSizeMin"
|
||||
|
||||
/**
|
||||
* FU_QUIRKS_FIRMWARE_SIZE_MAX:
|
||||
* @key: the USB device ID, e.g. `DeviceInstanceId=USB\VID_0763&PID_2806`
|
||||
* @value: the vendor, e.g. `0x10000`
|
||||
*
|
||||
* Sets the maximum allowed firmware size.
|
||||
*
|
||||
* Since: 1.1.2
|
||||
*/
|
||||
#define FU_QUIRKS_FIRMWARE_SIZE_MAX "FirmwareSizeMax"
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FU_QUIRKS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user