Add some more debugging to the SREC and IHEX parsers

Additionally, change the reported line to be indexed from 1 (rather than 0) as
most text editors show line 1 as the first line.
This commit is contained in:
Richard Hughes 2019-09-17 13:41:19 +01:00
parent 33cb526248
commit 3901fa6bae
2 changed files with 55 additions and 46 deletions

View File

@ -66,7 +66,7 @@ fu_ihex_firmware_parse (FuFirmware *firmware,
g_auto(GStrv) lines = NULL; g_auto(GStrv) lines = NULL;
g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (NULL); g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (NULL);
g_autoptr(GBytes) img_bytes = NULL; g_autoptr(GBytes) img_bytes = NULL;
g_autoptr(GString) buf = g_string_new (NULL); g_autoptr(GByteArray) buf = g_byte_array_new ();
g_autoptr(GByteArray) buf_signature = g_byte_array_new (); g_autoptr(GByteArray) buf_signature = g_byte_array_new ();
g_return_val_if_fail (fw != NULL, FALSE); g_return_val_if_fail (fw != NULL, FALSE);
@ -163,9 +163,10 @@ fu_ihex_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"invalid address 0x%x, last was 0x%x", "invalid address 0x%x, last was 0x%x on line %u",
(guint) addr, (guint) addr,
(guint) addr_last); (guint) addr_last,
ln + 1);
return FALSE; return FALSE;
} }
@ -179,22 +180,23 @@ fu_ihex_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"hole of 0x%x bytes too large to fill", "hole of 0x%x bytes too large to fill on line %u",
(guint) len_hole); (guint) len_hole,
ln + 1);
return FALSE; return FALSE;
} }
if (addr_last > 0x0 && len_hole > 1) { if (addr_last > 0x0 && len_hole > 1) {
g_debug ("filling address 0x%08x to 0x%08x", g_debug ("filling address 0x%08x to 0x%08x on line %u",
addr_last + 1, addr_last + len_hole - 1); addr_last + 1, addr_last + len_hole - 1, ln + 1);
for (guint j = 1; j < len_hole; j++) { for (guint j = 1; j < len_hole; j++) {
/* although 0xff might be clearer, /* although 0xff might be clearer,
* we can't write 0xffff to pic14 */ * we can't write 0xffff to pic14 */
g_string_append_c (buf, 0x00); fu_byte_array_append_uint8 (buf, 0x00);
} }
} }
/* write into buf */ /* write into buf */
data_tmp = fu_firmware_strparse_uint8 (line + i); data_tmp = fu_firmware_strparse_uint8 (line + i);
g_string_append_c (buf, (gchar) data_tmp); fu_byte_array_append_uint8 (buf, (gchar) data_tmp);
addr_last = addr++; addr_last = addr++;
} }
break; break;
@ -211,21 +213,21 @@ fu_ihex_firmware_parse (FuFirmware *firmware,
break; break;
case DFU_INHX32_RECORD_TYPE_EXTENDED_LINEAR: case DFU_INHX32_RECORD_TYPE_EXTENDED_LINEAR:
abs_addr = fu_firmware_strparse_uint16 (line + 9) << 16; abs_addr = fu_firmware_strparse_uint16 (line + 9) << 16;
g_debug (" abs_addr:\t0x%02x", abs_addr); g_debug (" abs_addr:\t0x%02x on line %u", abs_addr, ln + 1);
break; break;
case DFU_INHX32_RECORD_TYPE_START_LINEAR: case DFU_INHX32_RECORD_TYPE_START_LINEAR:
abs_addr = fu_firmware_strparse_uint32 (line + 9); abs_addr = fu_firmware_strparse_uint32 (line + 9);
g_debug (" abs_addr:\t0x%08x", abs_addr); g_debug (" abs_addr:\t0x%08x on line %u", abs_addr, ln + 1);
break; break;
case DFU_INHX32_RECORD_TYPE_EXTENDED_SEGMENT: case DFU_INHX32_RECORD_TYPE_EXTENDED_SEGMENT:
/* segment base address, so ~1Mb addressable */ /* segment base address, so ~1Mb addressable */
seg_addr = fu_firmware_strparse_uint16 (line + 9) * 16; seg_addr = fu_firmware_strparse_uint16 (line + 9) * 16;
g_debug (" seg_addr:\t0x%08x", seg_addr); g_debug (" seg_addr:\t0x%08x on line %u", seg_addr, ln + 1);
break; break;
case DFU_INHX32_RECORD_TYPE_START_SEGMENT: case DFU_INHX32_RECORD_TYPE_START_SEGMENT:
/* initial content of the CS:IP registers */ /* initial content of the CS:IP registers */
seg_addr = fu_firmware_strparse_uint32 (line + 9); seg_addr = fu_firmware_strparse_uint32 (line + 9);
g_debug (" seg_addr:\t0x%02x", seg_addr); g_debug (" seg_addr:\t0x%02x on line %u", seg_addr, ln + 1);
break; break;
case DFU_INHX32_RECORD_TYPE_SIGNATURE: case DFU_INHX32_RECORD_TYPE_SIGNATURE:
for (guint i = 9; i < line_end; i += 2) { for (guint i = 9; i < line_end; i += 2) {
@ -240,8 +242,8 @@ fu_ihex_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"invalid ihex record type %i", "invalid ihex record type %i on line %u",
record_type); record_type, ln + 1);
return FALSE; return FALSE;
} }
} }
@ -256,7 +258,7 @@ fu_ihex_firmware_parse (FuFirmware *firmware,
} }
/* add single image */ /* add single image */
img_bytes = g_bytes_new (buf->str, buf->len); img_bytes = g_bytes_new (buf->data, buf->len);
fu_firmware_image_set_bytes (img, img_bytes); fu_firmware_image_set_bytes (img, img_bytes);
if (img_addr != G_MAXUINT32) if (img_addr != G_MAXUINT32)
fu_firmware_image_set_addr (img, img_addr); fu_firmware_image_set_addr (img, img_addr);

View File

@ -38,7 +38,7 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_auto(GStrv) lines = NULL; g_auto(GStrv) lines = NULL;
g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (NULL); g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (NULL);
g_autoptr(GBytes) img_bytes = NULL; g_autoptr(GBytes) img_bytes = NULL;
g_autoptr(GString) outbuf = g_string_new (NULL); g_autoptr(GByteArray) outbuf = g_byte_array_new ();
/* parse records */ /* parse records */
data = g_bytes_get_data (fw, &sz); data = g_bytes_get_data (fw, &sz);
@ -63,7 +63,7 @@ fu_srec_firmware_parse (FuFirmware *firmware,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"invalid starting token, got '%c' at line %u", "invalid starting token, got '%c' at line %u",
line[0], ln); line[0], ln + 1);
return FALSE; return FALSE;
} }
@ -73,7 +73,7 @@ fu_srec_firmware_parse (FuFirmware *firmware,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"record incomplete at line %u, length %u", "record incomplete at line %u, length %u",
ln, (guint) linesz); ln + 1, (guint) linesz);
return FALSE; return FALSE;
} }
@ -86,7 +86,7 @@ fu_srec_firmware_parse (FuFirmware *firmware,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"count incomplete at line %u, " "count incomplete at line %u, "
"length %u, expected %u", "length %u, expected %u",
ln, (guint) linesz - 4, (guint) rec_count * 2); ln + 1, (guint) linesz - 4, (guint) rec_count * 2);
return FALSE; return FALSE;
} }
@ -104,7 +104,7 @@ fu_srec_firmware_parse (FuFirmware *firmware,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"checksum incorrect line %u, " "checksum incorrect line %u, "
"expected %02x, got %02x", "expected %02x, got %02x",
ln, rec_csum_expected, rec_csum); ln + 1, rec_csum_expected, rec_csum);
return FALSE; return FALSE;
} }
} }
@ -114,10 +114,11 @@ fu_srec_firmware_parse (FuFirmware *firmware,
case 0: case 0:
addrsz = 2; addrsz = 2;
if (got_hdr) { if (got_hdr) {
g_set_error_literal (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"duplicate header record"); "duplicate header record at line %u",
ln + 1);
return FALSE; return FALSE;
} }
got_hdr = TRUE; got_hdr = TRUE;
@ -154,8 +155,8 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"invalid srec record type S%c", "invalid srec record type S%c at line %u",
line[1]); line[1], ln + 1);
return FALSE; return FALSE;
} }
@ -174,6 +175,10 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_assert_not_reached (); g_assert_not_reached ();
} }
g_debug ("line %03u S%u addr:0x%04x datalen:0x%02x",
ln + 1, rec_kind, rec_addr32,
(guint) rec_count - addrsz - 1);
/* header */ /* header */
if (rec_kind == 0) { if (rec_kind == 0) {
g_autoptr(GString) modname = g_string_new (NULL); g_autoptr(GString) modname = g_string_new (NULL);
@ -181,8 +186,8 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"invalid header record address, got %04x", "invalid header record address, got %04x at line %u",
rec_addr32); rec_addr32, ln + 1);
return FALSE; return FALSE;
} }
@ -204,8 +209,8 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"count record was not valid, got 0x%02x expected 0x%02x", "count record was not valid, got 0x%02x expected 0x%02x at line %u",
(guint) rec_addr32, (guint) data_cnt); (guint) rec_addr32, (guint) data_cnt, ln + 1);
return FALSE; return FALSE;
} }
} }
@ -214,10 +219,11 @@ fu_srec_firmware_parse (FuFirmware *firmware,
if (rec_kind == 1 || rec_kind == 2 || rec_kind == 3) { if (rec_kind == 1 || rec_kind == 2 || rec_kind == 3) {
/* invalid */ /* invalid */
if (!got_hdr) { if (!got_hdr) {
g_set_error_literal (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"missing header record"); "missing header record at line %u",
ln + 1);
return FALSE; return FALSE;
} }
/* does not make sense */ /* does not make sense */
@ -225,14 +231,15 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"invalid address 0x%x, last was 0x%x", "invalid address 0x%x, last was 0x%x at line %u",
(guint) rec_addr32, (guint) rec_addr32,
(guint) addr32_last); (guint) addr32_last,
ln + 1);
return FALSE; return FALSE;
} }
if (rec_addr32 < addr_start) { if (rec_addr32 < addr_start) {
g_debug ("ignoring data at 0x%x as before start address 0x%x", g_debug ("ignoring data at 0x%x as before start address 0x%x at line %u",
(guint) rec_addr32, (guint) addr_start); (guint) rec_addr32, (guint) addr_start, ln + 1);
} else { } else {
guint bytecnt = 0; guint bytecnt = 0;
guint32 len_hole = rec_addr32 - addr32_last; guint32 len_hole = rec_addr32 - addr32_last;
@ -242,21 +249,21 @@ fu_srec_firmware_parse (FuFirmware *firmware,
g_set_error (error, g_set_error (error,
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
"hole of 0x%x bytes too large to fill", "hole of 0x%x bytes too large to fill at line %u",
(guint) len_hole); (guint) len_hole, ln + 1);
return FALSE; return FALSE;
} }
if (addr32_last > 0x0 && len_hole > 1) { if (addr32_last > 0x0 && len_hole > 1) {
g_debug ("filling address 0x%08x to 0x%08x", g_debug ("filling address 0x%08x to 0x%08x at line %u",
addr32_last + 1, addr32_last + len_hole - 1); addr32_last + 1, addr32_last + len_hole - 1, ln + 1);
for (guint j = 0; j < len_hole; j++) for (guint j = 0; j < len_hole; j++)
g_string_append_c (outbuf, 0xff); fu_byte_array_append_uint8 (outbuf, 0xff);
} }
/* add data */ /* add data */
for (guint8 i = 4 + (addrsz * 2); i <= rec_count * 2; i += 2) { for (guint8 i = 4 + (addrsz * 2); i <= rec_count * 2; i += 2) {
guint8 tmp = fu_firmware_strparse_uint8 (line + i); guint8 tmp = fu_firmware_strparse_uint8 (line + i);
g_string_append_c (outbuf, tmp); fu_byte_array_append_uint8 (outbuf, tmp);
bytecnt++; bytecnt++;
} }
if (img_address == 0x0) if (img_address == 0x0)
@ -277,7 +284,7 @@ fu_srec_firmware_parse (FuFirmware *firmware,
} }
/* add single image */ /* add single image */
img_bytes = g_bytes_new (outbuf->str, outbuf->len); img_bytes = g_bytes_new (outbuf->data, outbuf->len);
fu_firmware_image_set_bytes (img, img_bytes); fu_firmware_image_set_bytes (img, img_bytes);
fu_firmware_image_set_addr (img, img_address); fu_firmware_image_set_addr (img, img_address);
fu_firmware_add_image (firmware, img); fu_firmware_add_image (firmware, img);