예제 #1
0
/**
 * dfu_image_to_dfuse: (skip)
 * @image: a #DfuImage
 *
 * Packs a DfuSe image
 *
 * Returns: (transfer full): the packed data
 **/
static GBytes *
dfu_image_to_dfuse (DfuImage *image)
{
	DfuSeImagePrefix *im;
	GPtrArray *elements;
	guint32 length_total = 0;
	guint32 offset = sizeof (DfuSeImagePrefix);
	guint8 *buf;
	g_autoptr(GPtrArray) element_array = NULL;

	/* get total size */
	element_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
	elements = dfu_image_get_elements (image);
	for (guint i = 0; i < elements->len; i++) {
		DfuElement *element = g_ptr_array_index (elements, i);
		GBytes *bytes = dfu_element_to_dfuse (element);
		g_ptr_array_add (element_array, bytes);
		length_total += (guint32) g_bytes_get_size (bytes);
	}

	/* add prefix */
	buf = g_malloc0 (length_total + sizeof (DfuSeImagePrefix));
	im = (DfuSeImagePrefix *) buf;
	memcpy (im->sig, "Target", 6);
	im->alt_setting = dfu_image_get_alt_setting (image);
	if (dfu_image_get_name (image) != NULL) {
		im->target_named = GUINT32_TO_LE (0x01);
		memcpy (im->target_name, dfu_image_get_name (image), 255);
	}
	im->target_size = GUINT32_TO_LE (length_total);
	im->elements = GUINT32_TO_LE (elements->len);

	/* copy data */
	for (guint i = 0; i < element_array->len; i++) {
		gsize length;
		GBytes *bytes = g_ptr_array_index (element_array, i);
		const guint8 *data = g_bytes_get_data (bytes, &length);
		memcpy (buf + offset, data, length);
		offset += (guint32) length;
	}
	return g_bytes_new_take (buf, length_total + sizeof (DfuSeImagePrefix));
}
예제 #2
0
/**
 * dfu_target_download:
 * @target: a #DfuTarget
 * @image: a #DfuImage
 * @flags: flags to use, e.g. %DFU_TARGET_TRANSFER_FLAG_VERIFY
 * @cancellable: a #GCancellable, or %NULL
 * @error: a #GError, or %NULL
 *
 * Downloads firmware from the host to the target, optionally verifying
 * the transfer.
 *
 * Return value: %TRUE for success
 *
 * Since: 0.5.4
 **/
gboolean
dfu_target_download (DfuTarget *target, DfuImage *image,
		     DfuTargetTransferFlags flags,
		     GCancellable *cancellable,
		     GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	DfuElement *element;
	GPtrArray *elements;
	gboolean ret;
	guint i;

	g_return_val_if_fail (DFU_IS_TARGET (target), FALSE);
	g_return_val_if_fail (DFU_IS_IMAGE (image), FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	/* ensure populated */
	if (!dfu_target_setup (target, error))
		return NULL;

	/* can the target do this? */
	if (!dfu_device_can_download (priv->device)) {
		g_set_error_literal (error,
				     DFU_ERROR,
				     DFU_ERROR_NOT_SUPPORTED,
				     "target cannot do downloading");
		return FALSE;
	}

	/* use correct alt */
	if (!dfu_target_use_alt_setting (target, error))
		return FALSE;

	/* mark these as all erased */
	if (dfu_device_has_dfuse_support (priv->device))
		g_hash_table_remove_all (priv->sectors_erased);

	/* download all elements in the image to the device */
	elements = dfu_image_get_elements (image);
	if (elements->len == 0) {
		g_set_error_literal (error,
				     DFU_ERROR,
				     DFU_ERROR_INVALID_FILE,
				     "no image elements");
		return FALSE;
	}
	for (i = 0; i < elements->len; i++) {
		element = dfu_image_get_element (image, i);
		g_debug ("downloading element at 0x%04x",
			 dfu_element_get_address (element));
		ret = dfu_target_download_element (target,
						   element,
						   flags,
						   cancellable,
						   error);
		if (!ret)
			return FALSE;
	}

	/* attempt to switch back to runtime */
	if ((flags & DFU_TARGET_TRANSFER_FLAG_ATTACH) > 0 ||
	    (flags & DFU_TARGET_TRANSFER_FLAG_WAIT_RUNTIME) > 0) {
		if (!dfu_device_attach (priv->device, error))
			return FALSE;
	}

	/* boot to runtime */
	if (flags & DFU_TARGET_TRANSFER_FLAG_WAIT_RUNTIME) {
		g_debug ("booting to runtime to set auto-boot");
		if (!dfu_device_wait_for_replug (priv->device,
						 DFU_DEVICE_REPLUG_TIMEOUT,
						 cancellable,
						 error))
			return FALSE;
	}

	/* success */
	return TRUE;
}