Esempio n. 1
0
static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev,
				   struct image *firmware_image, int section_index)
{
	uint16_t chunk_size;
	uint8_t data[SECTION_BUFFERSIZE];
	uint8_t *data_ptr = data;
	size_t size_read;

	uint16_t size = (uint16_t)firmware_image->sections[section_index].size;
	uint16_t addr = (uint16_t)firmware_image->sections[section_index].base_address;

	LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr,
		size);

	/* Copy section contents to local buffer */
	int ret = image_read_section(firmware_image, section_index, 0, size, data,
			&size_read);

	if ((ret != ERROR_OK) || (size_read != size)) {
		/* Propagating the return code would return '0' (misleadingly indicating
		 * successful execution of the function) if only the size check fails. */
		return ERROR_FAIL;
	}

	uint16_t bytes_remaining = size;

	/* Send section data in chunks of up to 64 bytes to ULINK */
	while (bytes_remaining > 0) {
		if (bytes_remaining > 64)
			chunk_size = 64;
		else
			chunk_size = bytes_remaining;

		jtag_libusb_control_transfer(libusb_dev,
					     LIBUSB_REQUEST_TYPE_VENDOR | \
					     LIBUSB_ENDPOINT_OUT,
					     USBBLASTER_CTRL_LOAD_FIRM,
					     addr,
					     0,
					     (char *)data_ptr,
					     chunk_size,
					     100);

		bytes_remaining -= chunk_size;
		addr += chunk_size;
		data_ptr += chunk_size;
	}

	return ERROR_OK;
}
Esempio n. 2
0
static int loadDriver(struct ecosflash_flash_bank *info)
{
    size_t buf_cnt;
    size_t image_size;
    struct image image;

    image.base_address_set = 0;
    image.start_address_set = 0;
    struct target *target = info->target;
    int retval;

    if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK)
    {
        return retval;
    }

    info->start_address = image.start_address;

    image_size = 0x0;
    int i;
    for (i = 0; i < image.num_sections; i++)
    {
        void *buffer = malloc(image.sections[i].size);
        if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
        {
            free(buffer);
            image_close(&image);
            return retval;
        }
        target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
        image_size += buf_cnt;
        LOG_DEBUG("%zu bytes written at address 0x%8.8" PRIx32 "",
                  buf_cnt, image.sections[i].base_address);

        free(buffer);
    }

    image_close(&image);

    return ERROR_OK;
}
Esempio n. 3
0
int flash_write_unlock(struct target *target, struct image *image,
		uint32_t *written, int erase, bool unlock)
{
	int retval = ERROR_OK;

	int section;
	uint32_t section_offset;
	struct flash_bank *c;
	int *padding;

	section = 0;
	section_offset = 0;

	if (written)
		*written = 0;

	if (erase)
	{
		/* assume all sectors need erasing - stops any problems
		 * when flash_write is called multiple times */

		flash_set_dirty();
	}

	/* allocate padding array */
	padding = calloc(image->num_sections, sizeof(*padding));

	/* This fn requires all sections to be in ascending order of addresses,
	 * whereas an image can have sections out of order. */
	struct imagesection **sections = malloc(sizeof(struct imagesection *) *
			image->num_sections);
	int i;
	for (i = 0; i < image->num_sections; i++)
	{
		sections[i] = &image->sections[i];
	}

	qsort(sections, image->num_sections, sizeof(struct imagesection *),
			compare_section);

	/* loop until we reach end of the image */
	while (section < image->num_sections)
	{
		uint32_t buffer_size;
		uint8_t *buffer;
		int section_last;
		uint32_t run_address = sections[section]->base_address + section_offset;
		uint32_t run_size = sections[section]->size - section_offset;
		int pad_bytes = 0;

		if (sections[section]->size ==  0)
		{
			LOG_WARNING("empty section %d", section);
			section++;
			section_offset = 0;
			continue;
		}

		/* find the corresponding flash bank */
		retval = get_flash_bank_by_addr(target, run_address, false, &c);
		if (retval != ERROR_OK)
		{
			goto done;
		}
		if (c == NULL)
		{
			section++; /* and skip it */
			section_offset = 0;
			continue;
		}

		/* collect consecutive sections which fall into the same bank */
		section_last = section;
		padding[section] = 0;
		while ((run_address + run_size - 1 < c->base + c->size - 1)
				&& (section_last + 1 < image->num_sections))
		{
			/* sections are sorted */
			assert(sections[section_last + 1]->base_address >= c->base);
			if (sections[section_last + 1]->base_address >= (c->base + c->size))
			{
			  /* Done with this bank */
			  break;
			}

			/* FIXME This needlessly touches sectors BETWEEN the
			 * sections it's writing.  Without auto erase, it just
			 * writes ones.  That WILL INVALIDATE data in cases
			 * like Stellaris Tempest chips, corrupting internal
			 * ECC codes; and at least FreeScale suggests issues
			 * with that approach (in HC11 documentation).
			 *
			 * With auto erase enabled, data in those sectors will
			 * be needlessly destroyed; and some of the limited
			 * number of flash erase cycles will be wasted...
			 *
			 * In both cases, the extra writes slow things down.
			 */

			/* if we have multiple sections within our image,
			 * flash programming could fail due to alignment issues
			 * attempt to rebuild a consecutive buffer for the flash loader */
			pad_bytes = (sections[section_last + 1]->base_address) - (run_address + run_size);
			padding[section_last] = pad_bytes;
			run_size += sections[++section_last]->size;
			run_size += pad_bytes;

			if (pad_bytes > 0)
				LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
		}

		if (run_address + run_size - 1 > c->base + c->size - 1)
		{
			/* If we have more than one flash chip back to back, then we limit
			 * the current write operation to the current chip.
			 */
			LOG_DEBUG("Truncate flash run size to the current flash chip.");

			run_size = c->base + c->size - run_address;
			assert(run_size > 0);
		}

		/* If we're applying any sector automagic, then pad this
		 * (maybe-combined) segment to the end of its last sector.
		 */
		if (unlock || erase) {
			int sector;
			uint32_t offset_start = run_address - c->base;
			uint32_t offset_end = offset_start + run_size;
			uint32_t end = offset_end, delta;

			for (sector = 0; sector < c->num_sectors; sector++) {
				end = c->sectors[sector].offset
						+ c->sectors[sector].size;
				if (offset_end <= end)
					break;
			}

			delta = end - offset_end;
			padding[section_last] += delta;
			run_size += delta;
		}

		/* allocate buffer */
		buffer = malloc(run_size);
		if (buffer == NULL)
		{
			LOG_ERROR("Out of memory for flash bank buffer");
			retval = ERROR_FAIL;
			goto done;
		}
		buffer_size = 0;

		/* read sections to the buffer */
		while (buffer_size < run_size)
		{
			size_t size_read;

			size_read = run_size - buffer_size;
			if (size_read > sections[section]->size - section_offset)
			    size_read = sections[section]->size - section_offset;

			/* KLUDGE!
			 *
			 * #¤%#"%¤% we have to figure out the section # from the sorted
			 * list of pointers to sections to invoke image_read_section()...
			 */
			intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
			int t_section_num = diff / sizeof(struct imagesection);

			LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d",
				 (int)section,
(int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read);
			if ((retval = image_read_section(image, t_section_num, section_offset,
					size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
			{
				free(buffer);
				goto done;
			}

			/* see if we need to pad the section */
			while (padding[section]--)
				 (buffer + buffer_size)[size_read++] = 0xff;

			buffer_size += size_read;
			section_offset += size_read;

			if (section_offset >= sections[section]->size)
			{
				section++;
				section_offset = 0;
			}
		}

		retval = ERROR_OK;

		if (unlock)
		{
			retval = flash_unlock_address_range(target, run_address, run_size);
		}
		if (retval == ERROR_OK)
		{
			if (erase)
			{
				/* calculate and erase sectors */
				retval = flash_erase_address_range(target,
						true, run_address, run_size);
			}
		}

		if (retval == ERROR_OK)
		{
			/* write flash sectors */
			retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
		}

		free(buffer);

		if (retval != ERROR_OK)
		{
			/* abort operation */
			goto done;
		}

		if (written != NULL)
			*written += run_size; /* add run size to total written counter */
	}


done:
	free(sections);
	free(padding);

	return retval;
}