Beispiel #1
0
static void *spi_flash_read(FlashOps *me, uint32_t offset, uint32_t size)
{
	SpiFlash *flash = container_of(me, SpiFlash, ops);
	uint8_t *data = flash->cache + offset;

	assert(offset + size <= flash->rom_size);

	if (flash->spi->start(flash->spi)) {
		printf("%s: Failed to start flash transaction.\n", __func__);
		return NULL;
	}

	uint32_t command = swap_bytes32((ReadCommand << 24) | offset);

	if (flash->spi->transfer(flash->spi, NULL, &command, sizeof(command))) {
		printf("%s: Failed to send read command.\n", __func__);
		flash->spi->stop(flash->spi);
		return NULL;
	}

	if (flash->spi->transfer(flash->spi, data, NULL, size)) {
		printf("%s: Failed to receive %u bytes.\n", __func__, size);
		flash->spi->stop(flash->spi);
		return NULL;
	}

	if (flash->spi->stop(flash->spi)) {
		printf("%s: Failed to stop transaction.\n", __func__);
		return NULL;
	}

	return data;
}
Beispiel #2
0
static uint64_t swap_bytes64(uint64_t i)
{
    uint64_t res = swap_bytes32(i);
    res <<= 32;
    res |= swap_bytes32(i >> 32);
    return res;
}
Beispiel #3
0
void fix_endianness(globals_t *vars, value_t *data_value)
{
    if (!vars->options.reverse_endianness) {
        return;
    }
    if (data_value->flags.u64b) {
        data_value->uint64_value = swap_bytes64(data_value->uint64_value);
    } else if (data_value->flags.u32b) {
        data_value->uint32_value = swap_bytes32(data_value->uint32_value);
    } else if (data_value->flags.u16b) {
        data_value->uint16_value = swap_bytes16(data_value->uint16_value);
    }
    return;
}
Beispiel #4
0
// swap endianness of 2, 4 or 8 byte word in-place.
void swap_bytes_var(void *p, size_t num)
{
    switch (num) {
    case sizeof(uint16_t): ; // empty statement to cheat the compiler
        uint16_t i16 = swap_bytes16(*((uint16_t *)p));
        memcpy(p, &i16, sizeof(uint16_t));
        return;
    case sizeof(uint32_t): ;
        uint32_t i32 = swap_bytes32(*((uint32_t *)p));
        memcpy(p, &i32, sizeof(uint32_t));
        return;
    case sizeof(uint64_t): ;
        uint64_t i64 = swap_bytes64(*((uint64_t *)p));
        memcpy(p, &i64, sizeof(uint64_t));
        return;
    }
    assert(false);
    return;
}
Beispiel #5
0
/*
 * Write or erase the flash. To write, pass a buffer and size; to erase,
 * pass null for the buffer.
 * This function is guaranteed to be invoked with data not spanning across
 * writeable/erasable boundaries (page size/block size).
 */
static int spi_flash_modify(SpiFlash *flash, const void *buffer,
			    uint32_t offset, uint32_t size, uint8_t opcode,
			    const char *opname)
{
	union {
		uint8_t bytes[4]; // We're using 3 byte addresses.
		uint32_t whole;
	} command;

	int stop_needed = 0;
	uint32_t rv = -1;

	do {
		/* Each write or erase command requires a 'write enable' (WREN)
		 * first. */
		if (flash->spi->start(flash->spi)) {
			printf("%s: Failed to start WREN transaction.\n",
			       __func__);
			break;
		}

		command.bytes[0] = WriteEnableCommand;
		if (flash->spi->transfer(flash->spi, NULL, &command, 1)) {
			printf("%s: Failed to send write enable command.\n",
			       __func__);
			stop_needed = 1;
			break;
		}

		/*
		 * CS needs to be deasserted before any other command can be
		 * issued after WREN.
		 */
		if (toggle_cs(flash, "WREN"))
			break;

		stop_needed = 1;
		command.whole = swap_bytes32((opcode << 24) | offset);
		if (flash->spi->transfer(flash->spi, NULL, &command, 4)) {
			printf("%s: Failed to send %s command.\n",
			       __func__, opname);
			break;
		}

		if (buffer &&
		    flash->spi->transfer(flash->spi, NULL, buffer, size)) {
			printf("%s: Failed to write data.\n", __func__);
			break;
		}

		stop_needed = 1;
		if (!operation_failed(flash, opname))
			rv = size;

	} while(0);

	if (stop_needed && flash->spi->stop(flash->spi))
		printf("%s: Failed to stop.\n", __func__);

	return rv;
}