/*
 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 */

#include <common.h>
#include <malloc.h>
#include <mmc.h>
#include <chromeos/common.h>
#include <chromeos/firmware_storage.h>
#include <chromeos/os_storage.h>

#define PREFIX "firmware_storage_twostop: "

enum {
	SECTION_RO = 0,
	SECTION_RW_A,
	SECTION_RW_B
};

struct context {
	struct twostop_fmap *fmap;
	int section;
	firmware_storage_t spi_file;
	struct mmc *mmc;
};

static int within_entry(const struct fmap_entry *e, uint32_t offset)
{
	return e->offset <= offset && offset < e->offset + e->length;
}

static int get_section(const struct twostop_fmap *fmap, off_t offset)
{
	if (within_entry(&fmap->readonly.readonly, offset))
		return SECTION_RO;
	else if (within_entry(&fmap->readwrite_a.readwrite_a, offset))
		return SECTION_RW_A;
	else if (within_entry(&fmap->readwrite_b.readwrite_b, offset))
		return SECTION_RW_B;
	else
		return -1;
}

static void set_start_block_and_offset(const struct twostop_fmap *fmap,
		int section, uint32_t offset,
		uint32_t *start_block_ptr, uint32_t *offset_in_block_ptr)
{
	*start_block_ptr = (section == SECTION_RW_A) ?
		fmap->readwrite_a.block_lba :
		fmap->readwrite_b.block_lba;

	*offset_in_block_ptr = offset - ((section == SECTION_RW_A) ?
			fmap->readwrite_a.readwrite_a.offset :
			fmap->readwrite_b.readwrite_b.offset);

	*start_block_ptr += (*offset_in_block_ptr >> 9);
	*offset_in_block_ptr &= 0x1ff;
}

static int read_mmc(struct mmc *mmc,
		uint32_t start_block, uint32_t offset_in_block,
		uint32_t offset, uint32_t count, void *buf);
static int write_mmc(struct mmc *mmc,
		uint32_t start_block, uint32_t offset_in_block,
		uint32_t offset, uint32_t count, void *buf);

static int read_twostop(struct firmware_storage_t *file,
		uint32_t offset, uint32_t count, void *buf)
{
	struct context *cxt = file->context;
	int section = get_section(cxt->fmap, offset);
	uint32_t start_block = 0, offset_in_block = 0;

	VBDEBUG(PREFIX "read(offset=%08x, count=%08x, buffer=%p)\n",
			offset, count, buf);

	if (section < 0)
		return -1;
	else if (section == SECTION_RO)
		return cxt->spi_file.read(&cxt->spi_file, offset, count, buf);
	else {
		set_start_block_and_offset(cxt->fmap, section, offset,
				&start_block, &offset_in_block);
		return read_mmc(cxt->mmc, start_block, offset_in_block,
				offset, count, buf);
	}
}

static int write_twostop(struct firmware_storage_t *file,
		uint32_t offset, uint32_t count, void *buf)
{
	struct context *cxt = file->context;
	int section = get_section(cxt->fmap, offset);
	uint32_t start_block = 0, offset_in_block = 0;

	VBDEBUG(PREFIX "write(offset=%08x, count=%08x, buffer=%p)\n",
			offset, count, buf);

	if (section < 0)
		return -1;
	else if (section == SECTION_RO)
		return cxt->spi_file.write(&cxt->spi_file, offset, count, buf);
	else {
		set_start_block_and_offset(cxt->fmap, section, offset,
				&start_block, &offset_in_block);
		return write_mmc(cxt->mmc, start_block, offset_in_block,
				offset, count, buf);
	}
}

static int read_mmc(struct mmc *mmc,
		uint32_t start_block, uint32_t offset_in_block,
		uint32_t offset, uint32_t count, void *buf)
{
	uint32_t n_block;
	size_t n_byte;
	uint8_t *residual;

	VBDEBUG(PREFIX "read_mmc(start_block=%08x, offset_in_block=%08x)\n",
			start_block, offset_in_block);

	residual = memalign(CACHE_LINE_SIZE, 512);
	n_byte = 0;

	if (offset_in_block) {
		n_byte = MIN(512 - offset_in_block, count);
		mmc->block_dev.block_read(MMC_INTERNAL_DEVICE,
				start_block, 1, residual);
		memcpy(buf, residual + offset_in_block, n_byte);
	}

	offset_in_block += n_byte;
	if (offset_in_block == 512) {
		start_block++;
		offset_in_block = 0;
	}

	while (count > n_byte && (n_block = (count - n_byte) >> 9)) {
		n_block = mmc->block_dev.block_read(MMC_INTERNAL_DEVICE,
				start_block, n_block, buf + n_byte);
		start_block += n_block;
		n_byte += (n_block << 9);
	}

	if (count > n_byte) {
		mmc->block_dev.block_read(MMC_INTERNAL_DEVICE,
				start_block, 1, residual);
		memcpy(buf + n_byte, residual, count - n_byte);
		offset_in_block = count - n_byte;
	}

	free(residual);
	return 0;
}

static int write_mmc(struct mmc *mmc,
		uint32_t start_block, uint32_t offset_in_block,
		uint32_t offset, uint32_t count, void *buf)
{
	uint32_t n_block;
	size_t n_byte;
	uint8_t *residual;

	VBDEBUG(PREFIX "write_mmc(start_block=%08x, offset_in_block=%08x)\n",
			start_block, offset_in_block);

	residual = memalign(CACHE_LINE_SIZE, 512);
	n_byte = 0;

	if (offset_in_block) {
		n_byte = MIN(512 - offset_in_block, count);
		mmc->block_dev.block_read(MMC_INTERNAL_DEVICE,
				start_block, 1, residual);
		memcpy(residual + offset_in_block, buf, n_byte);
		mmc->block_dev.block_write(MMC_INTERNAL_DEVICE,
				start_block, 1, residual);
	}

	offset_in_block += n_byte;
	if (offset_in_block == 512) {
		start_block++;
		offset_in_block = 0;
	}

	while (count > n_byte && (n_block = (count - n_byte) >> 9)) {
		n_block = mmc->block_dev.block_write(MMC_INTERNAL_DEVICE,
				start_block, n_block, buf + n_byte);
		start_block += n_block;
		n_byte += (n_block << 9);
	}

	if (count > n_byte) {
		mmc->block_dev.block_read(MMC_INTERNAL_DEVICE,
				start_block, 1, residual);
		memcpy(residual, buf + n_byte, count - n_byte);
		mmc->block_dev.block_write(MMC_INTERNAL_DEVICE,
				start_block, 1, residual);
		offset_in_block = count - n_byte;
	}

	free(residual);
	return 0;
}

static int close_twostop(firmware_storage_t *file)
{
	struct context *cxt = file->context;
	int ret;

	ret = cxt->spi_file.close(&cxt->spi_file);
	free(cxt);

	return ret;
}

int firmware_storage_open_twostop(firmware_storage_t *file,
		struct twostop_fmap *fmap)
{
	struct context *cxt;

	cxt = malloc(sizeof(*cxt));
	if (!cxt)
		return -1;

	cxt->fmap = fmap;
	cxt->section = SECTION_RO;

	if (firmware_storage_open_spi(&cxt->spi_file)) {
		free(cxt);
		return -1;
	}

	cxt->mmc = find_mmc_device(MMC_INTERNAL_DEVICE);
	if (!cxt->mmc) {
		free(cxt);
		return -1;
	}
	mmc_init(cxt->mmc);

	file->read = read_twostop;
	file->write = write_twostop;
	file->close = close_twostop;
	file->context = (void *)cxt;

	return 0;
}
