/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2014 The ChromiumOS Authors.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <arch/early_variables.h>
#include <assert.h>
#include <commonlib/region.h>
#include <console/console.h>
#include <string.h>
#include <vb2_api.h>
#include <vboot_nvstorage.h>
#include <vboot/vboot_common.h>
#include <vboot/vbnv.h>
#include <vboot/vbnv_layout.h>

#define BLOB_SIZE VB2_NVDATA_SIZE

struct vbnv_flash_ctx {
	/* VBNV flash is initialized */
	int initialized;

	/* Offset of the current nvdata in flash */
	int blob_offset;

	/* Offset of the topmost nvdata blob in flash */
	int top_offset;

	/* Region to store and retrieve the VBNV contents. */
	struct region_device vbnv_dev;

	/* Cache of the current nvdata */
	uint8_t cache[BLOB_SIZE];
};
static struct vbnv_flash_ctx vbnv_flash CAR_GLOBAL;

/*
 * This code assumes that flash is erased to 1-bits, and write operations can
 * only change 1-bits to 0-bits. So if the new contents only change 1-bits to
 * 0-bits, we can reuse the current blob.
 */
static inline uint8_t erase_value(void)
{
	return 0xff;
}

static inline int can_overwrite(uint8_t current, uint8_t new)
{
	return (current & new) == new;
}

static int init_vbnv(void)
{
	struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash);
	struct region_device *rdev = &ctx->vbnv_dev;
	uint8_t buf[BLOB_SIZE];
	uint8_t empty_blob[BLOB_SIZE];
	int used_below, empty_above;
	int offset;
	int i;

	if (vboot_named_region_device_rw("RW_NVRAM", rdev) ||
	    region_device_sz(rdev) < BLOB_SIZE) {
		printk(BIOS_ERR, "%s: failed to locate NVRAM\n", __func__);
		return 1;
	}

	/* Prepare an empty blob to compare against. */
	for (i = 0; i < BLOB_SIZE; i++)
		empty_blob[i] = erase_value();

	ctx->top_offset = region_device_sz(rdev) - BLOB_SIZE;

	/* Binary search for the border between used and empty */
	used_below = 0;
	empty_above = region_device_sz(rdev) / BLOB_SIZE;

	while (used_below + 1 < empty_above) {
		int guess = (used_below + empty_above) / 2;
		if (rdev_readat(rdev, buf, guess * BLOB_SIZE, BLOB_SIZE) < 0) {
			printk(BIOS_ERR, "failed to read nvdata\n");
			return 1;
		}
		if (!memcmp(buf, empty_blob, BLOB_SIZE))
			empty_above = guess;
		else
			used_below = guess;
	}

	/*
	 * Offset points to the last non-empty blob.  Or if all blobs are empty
	 * (nvram is totally erased), point to the first blob.
	 */
	offset = used_below * BLOB_SIZE;

	/* reread the nvdata and write it to the cache */
	if (rdev_readat(rdev, ctx->cache, offset, BLOB_SIZE) < 0) {
		printk(BIOS_ERR, "failed to read nvdata\n");
		return 1;
	}

	ctx->blob_offset = offset;
	ctx->initialized = 1;

	return 0;
}

static int erase_nvram(void)
{
	struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash);
	const struct region_device *rdev = &ctx->vbnv_dev;

	if (rdev_eraseat(rdev, 0, region_device_sz(rdev)) < 0) {
		printk(BIOS_ERR, "failed to erase nvram\n");
		return 1;
	}

	printk(BIOS_INFO, "nvram is cleared\n");
	return 0;
}

void read_vbnv_flash(uint8_t *vbnv_copy)
{
	struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash);

	if (!ctx->initialized)
		if (init_vbnv())
			return;  /* error */

	memcpy(vbnv_copy, ctx->cache, BLOB_SIZE);
}

void save_vbnv_flash(const uint8_t *vbnv_copy)
{
	struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash);
	int new_offset;
	int i;
	const struct region_device *rdev = &ctx->vbnv_dev;

	if (!ctx->initialized)
		if (init_vbnv())
			return;  /* error */

	/* Bail out if there have been no changes. */
	if (!memcmp(vbnv_copy, ctx->cache, BLOB_SIZE))
		return;

	new_offset = ctx->blob_offset;

	/* See if we can overwrite the current blob with the new one */
	for (i = 0; i < BLOB_SIZE; i++) {
		if (!can_overwrite(ctx->cache[i], vbnv_copy[i])) {
			/* unable to overwrite. need to use the next blob */
			new_offset += BLOB_SIZE;
			if (new_offset > ctx->top_offset) {
				if (erase_nvram())
					return;  /* error */
				new_offset = 0;
			}
			break;
		}
	}

	if (rdev_writeat(rdev, vbnv_copy, new_offset, BLOB_SIZE) == BLOB_SIZE) {
		/* write was successful. safely move pointer forward */
		ctx->blob_offset = new_offset;
		memcpy(ctx->cache, vbnv_copy, BLOB_SIZE);
	} else {
		printk(BIOS_ERR, "failed to save nvdata\n");
	}
}
