From 3a86c7e386237fa1da9e59dd64478c476255e85a Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 23 Sep 2021 10:45:10 +0100 Subject: [PATCH] elantp: Use the recently added FuCfuOffer and FuCfuPayload This increases the amount of parsing we do ahead-of-time. --- libfwupdplugin/fwupdplugin.h | 2 ++ plugins/elanfp/fu-elanfp-device.c | 50 ++++++---------------------- plugins/elanfp/fu-elanfp-firmware.c | 37 ++++++++++++++------ plugins/elanfp/fu-elanfp-firmware.h | 7 ++++ src/fuzzing/elanfp.builder.xml | 30 ++++++++++++----- src/fuzzing/firmware/elanfp.bin | Bin 140 -> 160 bytes 6 files changed, 68 insertions(+), 58 deletions(-) diff --git a/libfwupdplugin/fwupdplugin.h b/libfwupdplugin/fwupdplugin.h index 75c1d19a5..affcb37c6 100644 --- a/libfwupdplugin/fwupdplugin.h +++ b/libfwupdplugin/fwupdplugin.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/plugins/elanfp/fu-elanfp-device.c b/plugins/elanfp/fu-elanfp-device.c index c5b5d6756..e9e331c67 100644 --- a/plugins/elanfp/fu-elanfp-device.c +++ b/plugins/elanfp/fu-elanfp-device.c @@ -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)) diff --git a/plugins/elanfp/fu-elanfp-firmware.c b/plugins/elanfp/fu-elanfp-firmware.c index 829e1e635..edbace0f4 100644 --- a/plugins/elanfp/fu-elanfp-firmware.c +++ b/plugins/elanfp/fu-elanfp-firmware.c @@ -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); } diff --git a/plugins/elanfp/fu-elanfp-firmware.h b/plugins/elanfp/fu-elanfp-firmware.h index 6a6b8812a..9ec5be576 100644 --- a/plugins/elanfp/fu-elanfp-firmware.h +++ b/plugins/elanfp/fu-elanfp-firmware.h @@ -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); diff --git a/src/fuzzing/elanfp.builder.xml b/src/fuzzing/elanfp.builder.xml index 108fbf053..3fe127b2c 100644 --- a/src/fuzzing/elanfp.builder.xml +++ b/src/fuzzing/elanfp.builder.xml @@ -1,19 +1,33 @@ 0x123 - + 0x72 - aGVsbG8gd29ybGQ= + 0x1234 + 0x5678 + 0x1 - + 0x73 - aGVsbG8gd29ybGQ= + 0x1234 + 0x5678 + 0x2 - + 0x74 - aGVsbG8gd29ybGQ= + + + aGVsbG8gd29ybGQ= + 0x8001234 + + - + 0x75 - aGVsbG8gd29ybGQ= + + + aGVsbG8gd29ybGQ= + 0x8001234 + + diff --git a/src/fuzzing/firmware/elanfp.bin b/src/fuzzing/firmware/elanfp.bin index 102487de7ce5a0869ba2aca8551fc6fa57f9e6d9..470010c73fdde01aac8a0b37bcc36dc76e2b4829 100644 GIT binary patch literal 160 zcmWFuHgZ#DWPpPrC@TR-3jlF3lwSblmq7UqP<|R2X{tlPENi;d45q&3OXME!*3DK literal 140 zcmWFuHgZ#DWPpPrC@TR-a|3ZPl%Eadmq7VtP<|