mirror of
https://git.proxmox.com/git/fwupd
synced 2025-06-28 23:36:07 +00:00
elantp: Add support for writing the firmware image
This allows for fuzzing.
This commit is contained in:
parent
9b304fdfbd
commit
ae3ad67710
@ -303,6 +303,7 @@ def _build(bld: Builder) -> None:
|
|||||||
("ccgx", "ccgx-dmc", "ccgx-dmc*.bin"),
|
("ccgx", "ccgx-dmc", "ccgx-dmc*.bin"),
|
||||||
("cros-ec", "cros-ec", "cros-ec*"),
|
("cros-ec", "cros-ec", "cros-ec*"),
|
||||||
("ebitdo", "ebitdo", "ebitdo*"),
|
("ebitdo", "ebitdo", "ebitdo*"),
|
||||||
|
("elantp", "elantp", "elantp*"),
|
||||||
("hailuck", "hailuck-kbd", "ihex*"),
|
("hailuck", "hailuck-kbd", "ihex*"),
|
||||||
("pixart-rf", "pxi", "pixart*"),
|
("pixart-rf", "pxi", "pixart*"),
|
||||||
("solokey", "solokey", "solokey*"),
|
("solokey", "solokey", "solokey*"),
|
||||||
|
@ -20,7 +20,7 @@ struct _FuElantpFirmware {
|
|||||||
G_DEFINE_TYPE (FuElantpFirmware, fu_elantp_firmware, FU_TYPE_FIRMWARE)
|
G_DEFINE_TYPE (FuElantpFirmware, fu_elantp_firmware, FU_TYPE_FIRMWARE)
|
||||||
|
|
||||||
/* firmware block update */
|
/* firmware block update */
|
||||||
#define ETP_IAP_START_ADDR 0x0083
|
#define ETP_IAP_START_ADDR_WRDS 0x008
|
||||||
|
|
||||||
guint16
|
guint16
|
||||||
fu_elantp_firmware_get_module_id (FuElantpFirmware *self)
|
fu_elantp_firmware_get_module_id (FuElantpFirmware *self)
|
||||||
@ -60,15 +60,31 @@ fu_elantp_firmware_parse (FuFirmware *firmware,
|
|||||||
g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (fw);
|
g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (fw);
|
||||||
|
|
||||||
/* presumably in words */
|
/* presumably in words */
|
||||||
if (!fu_common_read_uint16_safe (buf, bufsz, ETP_IAP_START_ADDR * 2,
|
if (!fu_common_read_uint16_safe (buf, bufsz, ETP_IAP_START_ADDR_WRDS * 2,
|
||||||
&iap_addr_wrds, G_LITTLE_ENDIAN, error))
|
&iap_addr_wrds, G_LITTLE_ENDIAN, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (iap_addr_wrds < ETP_IAP_START_ADDR_WRDS || iap_addr_wrds > 0x7FFF) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"IAP address invalid: 0x%x",
|
||||||
|
iap_addr_wrds);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
self->iap_addr = iap_addr_wrds * 2;
|
self->iap_addr = iap_addr_wrds * 2;
|
||||||
|
|
||||||
/* read module ID */
|
/* read module ID */
|
||||||
if (!fu_common_read_uint16_safe (buf, bufsz, self->iap_addr,
|
if (!fu_common_read_uint16_safe (buf, bufsz, self->iap_addr,
|
||||||
&module_id_wrds, G_LITTLE_ENDIAN, error))
|
&module_id_wrds, G_LITTLE_ENDIAN, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (module_id_wrds > 0x7FFF) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"module ID address invalid: 0x%x",
|
||||||
|
module_id_wrds);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
if (!fu_common_read_uint16_safe (buf, bufsz, module_id_wrds * 2,
|
if (!fu_common_read_uint16_safe (buf, bufsz, module_id_wrds * 2,
|
||||||
&self->module_id, G_LITTLE_ENDIAN, error))
|
&self->module_id, G_LITTLE_ENDIAN, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -78,6 +94,54 @@ fu_elantp_firmware_parse (FuFirmware *firmware,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_elantp_firmware_build (FuFirmware *firmware, XbNode *n, GError **error)
|
||||||
|
{
|
||||||
|
FuElantpFirmware *self = FU_ELANTP_FIRMWARE (firmware);
|
||||||
|
guint64 tmp;
|
||||||
|
|
||||||
|
/* two simple properties */
|
||||||
|
tmp = xb_node_query_text_as_uint (n, "module_id", NULL);
|
||||||
|
if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT16)
|
||||||
|
self->module_id = tmp;
|
||||||
|
tmp = xb_node_query_text_as_uint (n, "iap_addr", NULL);
|
||||||
|
if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT16)
|
||||||
|
self->iap_addr = tmp;
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
fu_elantp_firmware_write (FuFirmware *firmware, GError **error)
|
||||||
|
{
|
||||||
|
FuElantpFirmware *self = FU_ELANTP_FIRMWARE (firmware);
|
||||||
|
g_autoptr(GByteArray) buf = g_byte_array_new ();
|
||||||
|
g_autoptr(GBytes) blob = NULL;
|
||||||
|
|
||||||
|
/* only one image supported */
|
||||||
|
blob = fu_firmware_get_image_default_bytes (firmware, error);
|
||||||
|
if (blob == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* lets build a simple firmware like this:
|
||||||
|
* ------ 0x0
|
||||||
|
* HEADER (containing IAP offset and module ID)
|
||||||
|
* ------ ~0x10a
|
||||||
|
* DATA
|
||||||
|
* ------
|
||||||
|
*/
|
||||||
|
fu_byte_array_set_size (buf, self->iap_addr + 0x2 + 0x2);
|
||||||
|
fu_common_write_uint16 (buf->data + ETP_IAP_START_ADDR_WRDS * 2,
|
||||||
|
self->iap_addr / 2, G_LITTLE_ENDIAN);
|
||||||
|
fu_common_write_uint16 (buf->data + self->iap_addr,
|
||||||
|
(self->iap_addr + 2) / 2, G_LITTLE_ENDIAN);
|
||||||
|
fu_common_write_uint16 (buf->data + self->iap_addr + 0x2,
|
||||||
|
self->module_id, G_LITTLE_ENDIAN);
|
||||||
|
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 void
|
static void
|
||||||
fu_elantp_firmware_init (FuElantpFirmware *self)
|
fu_elantp_firmware_init (FuElantpFirmware *self)
|
||||||
{
|
{
|
||||||
@ -88,6 +152,8 @@ fu_elantp_firmware_class_init (FuElantpFirmwareClass *klass)
|
|||||||
{
|
{
|
||||||
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
|
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
|
||||||
klass_firmware->parse = fu_elantp_firmware_parse;
|
klass_firmware->parse = fu_elantp_firmware_parse;
|
||||||
|
klass_firmware->build = fu_elantp_firmware_build;
|
||||||
|
klass_firmware->write = fu_elantp_firmware_write;
|
||||||
klass_firmware->to_string = fu_elantp_firmware_to_string;
|
klass_firmware->to_string = fu_elantp_firmware_to_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ shared_module('fu_plugin_elantp',
|
|||||||
sources : [
|
sources : [
|
||||||
'fu-plugin-elantp.c',
|
'fu-plugin-elantp.c',
|
||||||
'fu-elantp-common.c',
|
'fu-elantp-common.c',
|
||||||
'fu-elantp-firmware.c',
|
'fu-elantp-firmware.c', # fuzzing
|
||||||
'fu-elantp-hid-device.c',
|
'fu-elantp-hid-device.c',
|
||||||
'fu-elantp-i2c-device.c',
|
'fu-elantp-i2c-device.c',
|
||||||
],
|
],
|
||||||
|
7
src/fuzzing/elantp.builder.xml
Normal file
7
src/fuzzing/elantp.builder.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<firmware gtype="FuElantpFirmware">
|
||||||
|
<iap_addr>0xe00</iap_addr>
|
||||||
|
<module_id>0x2</module_id>
|
||||||
|
<image>
|
||||||
|
<data>aGVsbG8gd29ybGQ=</data> <!-- base64 -->
|
||||||
|
</image>
|
||||||
|
</firmware>
|
BIN
src/fuzzing/firmware/elantp.bin
Normal file
BIN
src/fuzzing/firmware/elantp.bin
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user