elantp: Use the recently added FuCfuOffer and FuCfuPayload

This increases the amount of parsing we do ahead-of-time.
This commit is contained in:
Richard Hughes 2021-09-23 10:45:10 +01:00
parent 10549674b1
commit 3a86c7e386
6 changed files with 68 additions and 58 deletions

View File

@ -11,6 +11,8 @@
#include <libfwupdplugin/fu-archive.h>
#include <libfwupdplugin/fu-backend.h>
#include <libfwupdplugin/fu-bluez-device.h>
#include <libfwupdplugin/fu-cfu-offer.h>
#include <libfwupdplugin/fu-cfu-payload.h>
#include <libfwupdplugin/fu-chunk.h>
#include <libfwupdplugin/fu-common-cab.h>
#include <libfwupdplugin/fu-common-guid.h>

View File

@ -108,7 +108,6 @@ fu_elanfp_iap_send_command(FuElanfpDevice *self,
error))
return FALSE;
}
if (!g_usb_device_control_transfer(usb_device,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
@ -265,48 +264,16 @@ fu_elanfp_device_setup(FuDevice *device, GError **error)
static gboolean
fu_elanfp_device_write_payload(FuElanfpDevice *self,
GBytes *fw,
FuFirmware *payload,
FuProgress *progress,
GError **error)
{
guint32 offset = 0;
gsize bufsz = 0;
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
g_autoptr(GPtrArray) chunks = NULL;
/* process into chunks */
chunks = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
while (offset < bufsz) {
guint32 chunk_addr = 0;
guint8 chunk_size = 0;
g_autoptr(FuChunk) chk = NULL;
g_autoptr(GBytes) blob = NULL;
/* read chunk header */
if (!fu_common_read_uint32_safe(buf,
bufsz,
offset,
&chunk_addr,
G_LITTLE_ENDIAN,
error))
return FALSE;
if (!fu_common_read_uint8_safe(buf, bufsz, offset + 0x4, &chunk_size, error))
return FALSE;
offset += 0x5;
blob = fu_common_bytes_new_offset(fw, offset, chunk_size, error);
if (blob == NULL) {
g_prefix_error(error, "memory copy for offer fail: ");
return FALSE;
}
chk = fu_chunk_bytes_new(blob);
fu_chunk_set_address(chk, chunk_addr);
g_ptr_array_add(chunks, g_steal_pointer(&chk));
/* next! */
offset += chunk_size;
}
/* write each chunk */
chunks = fu_firmware_get_chunks(payload, error);
if (chunks == NULL)
return FALSE;
fu_progress_set_id(progress, G_STRLOC);
fu_progress_set_steps(progress, chunks->len);
for (guint i = 0; i < chunks->len; i++) {
@ -395,8 +362,11 @@ fu_elanfp_device_write_firmware(FuDevice *device,
const gchar *tag;
guint8 offer_idx;
guint8 payload_idx;
} items[] = {{"A", 0x72, 0x74}, {"B", 0x73, 0x75}, {NULL, 0x0, 0x0}};
g_autoptr(GBytes) payload = NULL;
} items[] = {
{"A", FU_ELANTP_FIRMWARE_IDX_CFU_OFFER_A, FU_ELANTP_FIRMWARE_IDX_CFU_PAYLOAD_A},
{"B", FU_ELANTP_FIRMWARE_IDX_CFU_OFFER_B, FU_ELANTP_FIRMWARE_IDX_CFU_PAYLOAD_B},
{NULL, FU_ELANTP_FIRMWARE_IDX_END, FU_ELANTP_FIRMWARE_IDX_END}};
g_autoptr(FuFirmware) payload = NULL;
/* progress */
fu_progress_set_id(progress, G_STRLOC);
@ -442,7 +412,7 @@ fu_elanfp_device_write_firmware(FuDevice *device,
fu_progress_step_done(progress);
/* send payload */
payload = fu_firmware_get_image_by_idx_bytes(firmware, items[i].payload_idx, error);
payload = fu_firmware_get_image_by_idx(firmware, items[i].payload_idx, error);
if (payload == NULL)
return FALSE;
if (!fu_elanfp_device_write_payload(self, payload, fu_progress_get_child(progress), error))

View File

@ -17,8 +17,6 @@ struct _FuElanfpFirmware {
G_DEFINE_TYPE(FuElanfpFirmware, fu_elanfp_firmware, FU_TYPE_FIRMWARE)
#define FU_ELANTP_FIRMWARE_IDX_END 0xFF
static void
fu_elanfp_firmware_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
{
@ -90,6 +88,23 @@ fu_elanfp_firmware_parse(FuFirmware *firmware,
G_LITTLE_ENDIAN,
error))
return FALSE;
/* done */
if (fwtype == FU_ELANTP_FIRMWARE_IDX_END)
break;
switch (fwtype) {
case FU_ELANTP_FIRMWARE_IDX_CFU_OFFER_A:
case FU_ELANTP_FIRMWARE_IDX_CFU_OFFER_B:
img = fu_cfu_offer_new();
break;
case FU_ELANTP_FIRMWARE_IDX_CFU_PAYLOAD_A:
case FU_ELANTP_FIRMWARE_IDX_CFU_PAYLOAD_B:
img = fu_cfu_payload_new();
break;
default:
img = fu_firmware_new();
break;
}
fu_firmware_set_idx(img, fwtype);
if (!fu_common_read_uint32_safe(buf,
bufsz,
@ -109,13 +124,10 @@ fu_elanfp_firmware_parse(FuFirmware *firmware,
blob = fu_common_bytes_new_offset(fw, start_addr, length, error);
if (blob == NULL)
return FALSE;
fu_firmware_set_bytes(img, blob);
if (!fu_firmware_parse(img, blob, flags, error))
return FALSE;
fu_firmware_add_image(firmware, img);
/* done */
if (fwtype == FU_ELANTP_FIRMWARE_IDX_END)
break;
offset += 0x10;
}
@ -141,11 +153,14 @@ fu_elanfp_firmware_write(FuFirmware *firmware, GError **error)
offset += 0x10 + ((imgs->len + 1) * 0x10);
for (guint i = 0; i < imgs->len; i++) {
FuFirmware *img = g_ptr_array_index(imgs, i);
g_autoptr(GBytes) blob = fu_firmware_write(img, error);
if (blob == NULL)
return NULL;
fu_byte_array_append_uint32(buf, fu_firmware_get_idx(img), G_LITTLE_ENDIAN);
fu_byte_array_append_uint32(buf, 0x0, G_LITTLE_ENDIAN); /* reserved */
fu_byte_array_append_uint32(buf, offset, G_LITTLE_ENDIAN);
fu_byte_array_append_uint32(buf, fu_firmware_get_size(img), G_LITTLE_ENDIAN);
offset += fu_firmware_get_size(img);
fu_byte_array_append_uint32(buf, g_bytes_get_size(blob), G_LITTLE_ENDIAN);
offset += g_bytes_get_size(blob);
}
/* end of index */
@ -157,7 +172,9 @@ fu_elanfp_firmware_write(FuFirmware *firmware, GError **error)
/* data */
for (guint i = 0; i < imgs->len; i++) {
FuFirmware *img = g_ptr_array_index(imgs, i);
g_autoptr(GBytes) blob = fu_firmware_get_bytes(img, error);
g_autoptr(GBytes) blob = fu_firmware_write(img, error);
if (blob == NULL)
return NULL;
fu_byte_array_append_bytes(buf, blob);
}

View File

@ -11,5 +11,12 @@
#define FU_TYPE_ELANFP_FIRMWARE (fu_elanfp_firmware_get_type())
G_DECLARE_FINAL_TYPE(FuElanfpFirmware, fu_elanfp_firmware, FU, ELANFP_FIRMWARE, FuFirmware)
#define FU_ELANTP_FIRMWARE_IDX_FIRMWAREVERSION 0x00
#define FU_ELANTP_FIRMWARE_IDX_CFU_OFFER_A 0x72
#define FU_ELANTP_FIRMWARE_IDX_CFU_OFFER_B 0x73
#define FU_ELANTP_FIRMWARE_IDX_CFU_PAYLOAD_A 0x74
#define FU_ELANTP_FIRMWARE_IDX_CFU_PAYLOAD_B 0x75
#define FU_ELANTP_FIRMWARE_IDX_END 0xFF
FuFirmware *
fu_elanfp_firmware_new(void);

View File

@ -1,19 +1,33 @@
<firmware gtype="FuElanfpFirmware">
<format_version>0x123</format_version>
<firmware>
<firmware gtype="FuCfuOffer">
<idx>0x72</idx>
<data>aGVsbG8gd29ybGQ=</data>
<version_raw>0x1234</version_raw>
<product_id>0x5678</product_id>
<bank>0x1</bank>
</firmware>
<firmware>
<firmware gtype="FuCfuOffer">
<idx>0x73</idx>
<data>aGVsbG8gd29ybGQ=</data>
<version_raw>0x1234</version_raw>
<product_id>0x5678</product_id>
<bank>0x2</bank>
</firmware>
<firmware>
<firmware gtype="FuCfuPayload">
<idx>0x74</idx>
<data>aGVsbG8gd29ybGQ=</data>
<chunks>
<chunk>
<data>aGVsbG8gd29ybGQ=</data>
<addr>0x8001234</addr>
</chunk>
</chunks>
</firmware>
<firmware>
<firmware gtype="FuCfuPayload">
<idx>0x75</idx>
<data>aGVsbG8gd29ybGQ=</data>
<chunks>
<chunk>
<data>aGVsbG8gd29ybGQ=</data>
<addr>0x8001234</addr>
</chunk>
</chunks>
</firmware>
</firmware>

Binary file not shown.