Пример #1
0
/**
 * dfu_image_from_dfuse: (skip)
 * @data: data buffer
 * @length: length of @data we can access
 * @consumed: (out): the number of bytes we consued
 * @error: a #GError, or %NULL
 *
 * Unpacks an image from DfuSe data.
 *
 * Returns: a #DfuImage, or %NULL for error
 **/
static DfuImage *
dfu_image_from_dfuse (const guint8 *data,
		      guint32 length,
		      guint32 *consumed,
		      GError **error)
{
	DfuSeImagePrefix *im;
	guint32 elements;
	guint32 offset = sizeof(DfuSeImagePrefix);
	g_autoptr(DfuImage) image = NULL;

	g_assert_cmpint(sizeof(DfuSeImagePrefix), ==, 274);

	/* check input buffer size */
	if (length < sizeof(DfuSeImagePrefix)) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INTERNAL,
			     "invalid image data size %u",
			     (guint32) length);
		return NULL;
	}

	/* verify image signature */
	im = (DfuSeImagePrefix *) data;
	if (memcmp (im->sig, "Target", 6) != 0) {
		g_set_error_literal (error,
				     FWUPD_ERROR,
				     FWUPD_ERROR_INVALID_FILE,
				     "invalid DfuSe target signature");
		return NULL;
	}

	/* create new image */
	image = dfu_image_new ();
	dfu_image_set_alt_setting (image, im->alt_setting);
	if (GUINT32_FROM_LE (im->target_named) == 0x01)
		dfu_image_set_name (image, im->target_name);

	/* parse elements */
	length -= offset;
	elements = GUINT32_FROM_LE (im->elements);
	for (guint j = 0; j < elements; j++) {
		guint32 consumed_local;
		g_autoptr(DfuElement) element = NULL;
		element = dfu_element_from_dfuse (data + offset, length,
						  &consumed_local, error);
		if (element == NULL)
			return NULL;
		dfu_image_add_element (image, element);
		offset += consumed_local;
		length -= consumed_local;
	}

	/* return size */
	if (consumed != NULL)
		*consumed = offset;

	return g_object_ref (image);
}
Пример #2
0
/**
 * dfu_firmware_from_raw: (skip)
 * @firmware: a #DfuFirmware
 * @bytes: data to parse
 * @flags: some #DfuFirmwareParseFlags
 * @error: a #GError, or %NULL
 *
 * Unpacks into a firmware object from raw data.
 *
 * Returns: %TRUE for success
 **/
gboolean
dfu_firmware_from_raw (DfuFirmware *firmware,
		       GBytes *bytes,
		       DfuFirmwareParseFlags flags,
		       GError **error)
{
	g_autoptr(DfuElement) element = NULL;
	g_autoptr(DfuImage) image = NULL;
	image = dfu_image_new ();
	element = dfu_element_new ();
	dfu_element_set_contents (element, bytes);
	dfu_image_add_element (image, element);
	dfu_firmware_add_image (firmware, image);
	return TRUE;
}
Пример #3
0
/**
 * dfu_target_upload:
 * @target: a #DfuTarget
 * @flags: flags to use, e.g. %DFU_TARGET_TRANSFER_FLAG_VERIFY
 * @cancellable: a #GCancellable, or %NULL
 * @error: a #GError, or %NULL
 *
 * Uploads firmware from the target to the host.
 *
 * Return value: (transfer full): the uploaded image, or %NULL for error
 *
 * Since: 0.5.4
 **/
DfuImage *
dfu_target_upload (DfuTarget *target,
		   DfuTargetTransferFlags flags,
		   GCancellable *cancellable,
		   GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	DfuSector *sector;
	guint i;
	guint32 last_sector_id = G_MAXUINT;
	g_autoptr(DfuImage) image = NULL;

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

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

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

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

	/* no open?! */
	if (priv->sectors->len == 0) {
		g_set_error_literal (error,
				     DFU_ERROR,
				     DFU_ERROR_NOT_SUPPORTED,
				     "no sectors defined for target");
		return NULL;
	}

	/* create a new image */
	image = dfu_image_new ();
	dfu_image_set_name (image, priv->alt_name);
	dfu_image_set_alt_setting (image, priv->alt_setting);

	/* get all the sectors for the device */
	for (i = 0; i < priv->sectors->len; i++) {
		g_autoptr(DfuElement) element = NULL;

		/* only upload to the start of any zone:sector */
		sector = g_ptr_array_index (priv->sectors, i);
		if (dfu_sector_get_id (sector) == last_sector_id)
			continue;

		/* get the first element from the hardware */
		g_debug ("starting upload from 0x%08x (0x%04x)",
			 dfu_sector_get_address (sector),
			 dfu_sector_get_size_left (sector));
		element = dfu_target_upload_element (target,
						     dfu_sector_get_address (sector),
						     dfu_sector_get_size_left (sector),
						     cancellable,
						     error);
		if (element == NULL)
			return NULL;

		/* this element was uploaded okay */
		dfu_image_add_element (image, element);

		/* ignore sectors until one of these changes */
		last_sector_id = dfu_sector_get_id (sector);
	}

	/* do host reset */
	if ((flags & DFU_TARGET_TRANSFER_FLAG_ATTACH) > 0 ||
	    (flags & DFU_TARGET_TRANSFER_FLAG_WAIT_RUNTIME) > 0) {
		if (!dfu_device_attach (priv->device, error))
			return NULL;
	}

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

	/* success */
	return g_object_ref (image);
}