unifying: fix incomplete hex file parsing

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 <lains@archlinux.org>
This commit is contained in:
Filipe Laíns 2019-08-29 09:35:08 +01:00 committed by Richard Hughes
parent 4250d9da62
commit e3f380afda

View File

@ -8,6 +8,7 @@
#include <string.h>
#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);