Load the Altos USB descriptor from ELF files

This commit is contained in:
Richard Hughes 2016-09-03 14:55:40 +01:00
parent 633944045f
commit 190e60cd6f
2 changed files with 74 additions and 23 deletions

View File

@ -393,6 +393,56 @@ dfu_firmware_set_format (DfuFirmware *firmware, DfuFirmwareFormat format)
priv->format = format;
}
static void
dfu_firmware_parse_altos_vid_pid (DfuFirmware *firmware)
{
DfuFirmwarePrivate *priv = GET_PRIVATE (firmware);
guint32 addr32;
/* find symbol */
addr32 = dfu_firmware_lookup_symbol (firmware, "ao_usb_descriptors");
if (addr32 == 0x0)
return;
/* search each element */
for (guint i = 0; i < priv->images->len; i++) {
DfuImage *image = g_ptr_array_index (priv->images, i);
DfuElement *element;
GBytes *bytes_tmp;
const guint8 *data;
gsize length;
guint32 element_address;
guint16 vid, pid, release;
/* get element data */
element = dfu_image_get_element_default (image);
if (element == NULL)
continue;
/* check address is in this element */
element_address = dfu_element_get_address (element);
if (element_address > addr32)
continue;
bytes_tmp = dfu_element_get_contents (element);
if (bytes_tmp == NULL)
continue;
/* check this element is big enough */
data = g_bytes_get_data (bytes_tmp, &length);
if (addr32 - element_address > length)
continue;
/* read the USB descriptor */
addr32 -= element_address;
memcpy (&vid, &data[addr32 + 8], 2);
memcpy (&pid, &data[addr32 + 10], 2);
memcpy (&release, &data[addr32 + 12], 2);
dfu_firmware_set_vid (firmware, GUINT32_FROM_LE (vid));
dfu_firmware_set_pid (firmware, GUINT32_FROM_LE (pid));
dfu_firmware_set_release (firmware, GUINT32_FROM_LE (release));
}
}
/**
* dfu_firmware_parse_data:
* @firmware: a #DfuFirmware
@ -432,14 +482,30 @@ dfu_firmware_parse_data (DfuFirmware *firmware, GBytes *bytes,
priv->format = dfu_firmware_detect_raw (bytes);
/* handled easily */
if (priv->format == DFU_FIRMWARE_FORMAT_INTEL_HEX)
return dfu_firmware_from_ihex (firmware, bytes, flags, error);
if (priv->format == DFU_FIRMWARE_FORMAT_ELF)
return dfu_firmware_from_elf (firmware, bytes, flags, error);
if (priv->format == DFU_FIRMWARE_FORMAT_DFU ||
priv->format == DFU_FIRMWARE_FORMAT_DFUSE)
return dfu_firmware_from_dfu (firmware, bytes, flags, error);
return dfu_firmware_from_raw (firmware, bytes, flags, error);
switch (priv->format) {
case DFU_FIRMWARE_FORMAT_INTEL_HEX:
if (!dfu_firmware_from_ihex (firmware, bytes, flags, error))
return FALSE;
break;
case DFU_FIRMWARE_FORMAT_ELF:
if (!dfu_firmware_from_elf (firmware, bytes, flags, error))
return FALSE;
break;
case DFU_FIRMWARE_FORMAT_DFU:
case DFU_FIRMWARE_FORMAT_DFUSE:
if (!dfu_firmware_from_dfu (firmware, bytes, flags, error))
return FALSE;
break;
default:
if (!dfu_firmware_from_raw (firmware, bytes, flags, error))
return FALSE;
break;
}
/* get the VID/PID for altos devices */
dfu_firmware_parse_altos_vid_pid (firmware);
return TRUE;
}
/**

View File

@ -289,21 +289,6 @@ dfu_firmware_from_ihex (DfuFirmware *firmware,
return FALSE;
}
/* get the VID/PID for altos devices */
addr32 = dfu_firmware_lookup_symbol (firmware, "ao_usb_descriptors");
if (addr32 != 0x0 &&
addr32 > element_address &&
addr32 - element_address < string->len) {
guint16 vid, pid, release;
addr32 -= element_address;
memcpy (&vid, &string->str[addr32 + 8], 2);
memcpy (&pid, &string->str[addr32 + 10], 2);
memcpy (&release, &string->str[addr32 + 12], 2);
dfu_firmware_set_vid (firmware, GUINT32_FROM_LE (vid));
dfu_firmware_set_pid (firmware, GUINT32_FROM_LE (pid));
dfu_firmware_set_release (firmware, GUINT32_FROM_LE (release));
}
/* add single image */
contents = g_bytes_new (string->str, string->len);
dfu_element_set_contents (element, contents);