Beispiel #1
0
static void test_type(const char *type) {
        CVariant *cv;
        GVariant *gv;
        GBytes *cb, *gb;
        const void *cd, *gd;

        test_generate(type, &cv, &gv);

        cb = test_cv_get_data_as_bytes(cv);
        gb = g_variant_get_data_as_bytes(gv);

        if (g_bytes_compare(cb, gb)) {
                fprintf(stderr, "FAILED: %s\n", type);

                cd = g_bytes_get_data(cb, NULL);
                gd = g_bytes_get_data(gb, NULL);

                fprintf(stderr, "Buffers: %p:%zu %p:%zu\n",
                        cd, g_bytes_get_size(cb),
                        gd, g_bytes_get_size(gb));

                test_print_cv(cv);
                assert(0);
        }

        test_compare(cv, gv);

        g_bytes_unref(gb);
        g_bytes_unref(cb);
        g_variant_unref(gv);
        c_variant_free(cv);
}
Beispiel #2
0
/**
 * dfu_target_download_element:
 **/
static gboolean
dfu_target_download_element (DfuTarget *target,
			     DfuElement *element,
			     DfuTargetTransferFlags flags,
			     GCancellable *cancellable,
			     GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	DfuSector *sector;
	GBytes *bytes;
	guint i;
	guint nr_chunks;
	guint dfuse_sector_offset = 0;
	guint last_sector_id = G_MAXUINT;
	guint old_percentage = G_MAXUINT;
	guint16 transfer_size = dfu_device_get_transfer_size (priv->device);
	g_autoptr(GError) error_local = NULL;

	/* ST uses wBlockNum=0 for DfuSe commands and wBlockNum=1 is reserved */
	if (dfu_device_has_dfuse_support (priv->device))
		dfuse_sector_offset = 2;

	/* round up as we have to transfer incomplete blocks */
	bytes = dfu_element_get_contents (element);
	nr_chunks = ceil ((gdouble) g_bytes_get_size (bytes) /
			  (gdouble) transfer_size);
	if (nr_chunks == 0) {
		g_set_error_literal (error,
				     DFU_ERROR,
				     DFU_ERROR_INVALID_FILE,
				     "zero-length firmware");
		return FALSE;
	}
	for (i = 0; i < nr_chunks + 1; i++) {
		gsize length;
		gsize offset;
		guint percentage;
		g_autoptr(GBytes) bytes_tmp = NULL;

		/* caclulate the offset into the element data */
		offset = i * transfer_size;

		/* for DfuSe devices we need to handle the erase and setting
		 * the address manually */
		if (dfu_device_has_dfuse_support (priv->device)) {

			/* check the sector with this element address is suitable */
			sector = dfu_target_get_sector_for_addr (target, offset);
			if (sector == NULL) {
				g_set_error (error,
					     DFU_ERROR,
					     DFU_ERROR_INVALID_DEVICE,
					     "no memory sector at 0x%04x",
					     (guint) offset);
				return FALSE;
			}
			if (!dfu_sector_has_cap (sector, DFU_SECTOR_CAP_WRITEABLE)) {
				g_set_error (error,
					     DFU_ERROR,
					     DFU_ERROR_INVALID_DEVICE,
					     "memory sector at 0x%04x is not writable",
					     (guint) offset);
				return FALSE;
			}

			/* if it's erasable and not yet blanked */
			if (!dfu_sector_has_cap (sector, DFU_SECTOR_CAP_ERASEABLE) &&
			    g_hash_table_lookup (priv->sectors_erased, sector) == NULL) {
				g_debug ("erasing DfuSe address at 0x%04x", (guint) offset);
				if (!dfu_target_erase_address (target,
							       offset,
							       cancellable,
							       error))
					return FALSE;
				g_hash_table_insert (priv->sectors_erased,
						     sector,
						     GINT_TO_POINTER (1));
			}

			/* manually set the sector address */
			if (dfu_sector_get_id (sector) != last_sector_id) {
				g_debug ("setting DfuSe address to 0x%04x", (guint) offset);
				if (!dfu_target_set_address (target,
							     offset,
							     cancellable,
							     error))
					return FALSE;
				last_sector_id = dfu_sector_get_id (sector);
			}
		}

		/* we have to write one final zero-sized chunk for EOF */
		if (i < nr_chunks) {
			length = g_bytes_get_size (bytes) - offset;
			if (length > transfer_size)
				length = transfer_size;
			bytes_tmp = g_bytes_new_from_bytes (bytes, offset, length);
		} else {
			bytes_tmp = g_bytes_new (NULL, 0);
		}
		g_debug ("writing #%04x chunk of size %" G_GSIZE_FORMAT,
			 i, g_bytes_get_size (bytes_tmp));
		if (!dfu_target_download_chunk (target,
						i + dfuse_sector_offset,
						bytes_tmp,
						cancellable,
						error))
			return FALSE;

		/* update UI */
		percentage = (offset * 100) / g_bytes_get_size (bytes);
		if (percentage != old_percentage) {
			g_signal_emit (target,
				       signals[SIGNAL_PERCENTAGE_CHANGED],
				       0, percentage);
		}

		/* give the target a chance to update */
		g_usleep (dfu_device_get_download_timeout (priv->device) * 1000);

		/* getting the status moves the state machine to DNLOAD-IDLE */
		if (!dfu_device_refresh (priv->device, cancellable, error))
			return FALSE;
	}

	/* verify */
	if (flags & DFU_TARGET_TRANSFER_FLAG_VERIFY) {
		GBytes *bytes_tmp;
		g_autoptr(DfuElement) element_tmp = NULL;
		element_tmp = dfu_target_upload_element (target,
							 dfu_element_get_address (element),
							 g_bytes_get_size (bytes),
							 cancellable,
							 error);
		if (element_tmp == NULL)
			return FALSE;
		bytes_tmp = dfu_element_get_contents (element_tmp);
		if (g_bytes_compare (bytes_tmp, bytes) != 0) {
			g_autofree gchar *bytes_cmp_str = NULL;
			bytes_cmp_str = _g_bytes_compare_verbose (bytes_tmp, bytes);
			g_set_error (error,
				     DFU_ERROR,
				     DFU_ERROR_VERIFY_FAILED,
				     "verify failed: %s",
				     bytes_cmp_str);
			return FALSE;
		}
	}

	return TRUE;
}