From e3f380afda978c0573ac816e4b13c1f950e5aea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Thu, 29 Aug 2019 09:35:08 +0100 Subject: [PATCH] unifying: fix incomplete hex file parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new firmware for receivers with the nordic chips is using the 0x04 record type. This was previously not handled when parsing the file, causing wrong behavior when trying to update the device. This patch tries to properly deal with the record types, being them 0x04 or other. Signed-off-by: Filipe LaĆ­ns --- plugins/unifying/fu-unifying-bootloader.c | 49 ++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/plugins/unifying/fu-unifying-bootloader.c b/plugins/unifying/fu-unifying-bootloader.c index b4f471051..5a276dc5d 100644 --- a/plugins/unifying/fu-unifying-bootloader.c +++ b/plugins/unifying/fu-unifying-bootloader.c @@ -8,6 +8,7 @@ #include +#include "fu-firmware-common.h" #include "fu-unifying-common.h" #include "fu-unifying-bootloader.h" #include "fu-unifying-hidpp.h" @@ -57,6 +58,8 @@ fu_unifying_bootloader_parse_requests (FuUnifyingBootloader *self, GBytes *fw, G for (guint i = 0; lines[i] != NULL; i++) { g_autoptr(FuUnifyingBootloaderRequest) payload = NULL; guint8 rec_type = 0x00; + guint16 offset = 0x0000; + gboolean exit = FALSE; /* skip empty lines */ tmp = lines[i]; @@ -75,16 +78,52 @@ fu_unifying_bootloader_parse_requests (FuUnifyingBootloader *self, GBytes *fw, G } payload->addr = ((guint16) fu_unifying_buffer_read_uint8 (tmp + 0x03)) << 8; payload->addr |= fu_unifying_buffer_read_uint8 (tmp + 0x05); + payload->cmd = FU_UNIFYING_BOOTLOADER_CMD_WRITE_RAM_BUFFER; rec_type = fu_unifying_buffer_read_uint8 (tmp + 0x07); - /* record type of 0xFD indicates signature data */ - if (rec_type == 0xFD) { - payload->cmd = FU_UNIFYING_BOOTLOADER_CMD_WRITE_SIGNATURE; - } else { - payload->cmd = FU_UNIFYING_BOOTLOADER_CMD_WRITE_RAM_BUFFER; + switch (rec_type) { + case 0x00: /* data */ + break; + case 0x01: /* EOF */ + exit = TRUE; + break; + case 0x03: /* start segment address */ + /* this is used to specify the start address, + it is doesn't mater in this context so we can + safely ignore it */ + continue; + case 0x04: /* extended linear address */ + offset = fu_firmware_strparse_uint16 (tmp + 0x09); + if (offset != 0x0000) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "extended linear addresses with offset different from 0 are not supported"); + return NULL; + } + continue; + case 0x05: /* start linear address */ + /* this is used to specify the start address, + it is doesn't mater in this context so we can + safely ignore it */ + continue; + case 0xFD: /* custom - vendor */ + /* record type of 0xFD indicates signature data */ + payload->cmd = FU_UNIFYING_BOOTLOADER_CMD_WRITE_SIGNATURE; + break; + default: + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "intel hex file record type %02x not supported", + rec_type); + return NULL; } + if (exit) + break; + /* read the data, but skip the checksum byte */ for (guint j = 0; j < payload->len; j++) { const gchar *ptr = tmp + 0x09 + (j * 2);