/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2016 Google Inc.
 *
 * 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 <string.h>
#include <types.h>
#include <vboot/vbnv.h>
#include <vboot/vbnv_layout.h>

static int vbnv_initialized CAR_GLOBAL;
static uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE] CAR_GLOBAL;

/* Wrappers for accessing the variables marked as CAR_GLOBAL. */
static inline int is_vbnv_initialized(void)
{
	return car_get_var(vbnv_initialized);
}

static inline uint8_t *vbnv_data_addr(int index)
{
	uint8_t *vbnv_arr = car_get_var_ptr(vbnv);

	return &vbnv_arr[index];
}

static inline uint8_t vbnv_data(int index)
{
	return *vbnv_data_addr(index);
}

/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. */
static uint8_t crc8_vbnv(const uint8_t *data, int len)
{
	unsigned crc = 0;
	int i, j;

	for (j = len; j; j--, data++) {
		crc ^= (*data << 8);
		for (i = 8; i; i--) {
			if (crc & 0x8000)
				crc ^= (0x1070 << 3);
			crc <<= 1;
		}
	}

	return (uint8_t) (crc >> 8);
}

static void reset_vbnv(uint8_t *vbnv_copy)
{
	memset(vbnv_copy, 0, VBOOT_VBNV_BLOCK_SIZE);
}

/* Read VBNV data into cache. */
static void vbnv_setup(void)
{
	if (!is_vbnv_initialized()) {
		read_vbnv(vbnv_data_addr(0));
		car_set_var(vbnv_initialized, 1);
	}
}

/* Verify VBNV header and checksum. */
int verify_vbnv(uint8_t *vbnv_copy)
{
	return (HEADER_SIGNATURE == (vbnv_copy[HEADER_OFFSET] & HEADER_MASK)) &&
		(crc8_vbnv(vbnv_copy, CRC_OFFSET) == vbnv_copy[CRC_OFFSET]);
}

/* Re-generate VBNV checksum. */
void regen_vbnv_crc(uint8_t *vbnv_copy)
{
	vbnv_copy[CRC_OFFSET] = crc8_vbnv(vbnv_copy, CRC_OFFSET);
}

/*
 * Read VBNV data from configured storage backend.
 * If VBNV verification fails, reset the vbnv copy.
 */
void read_vbnv(uint8_t *vbnv_copy)
{
	if (IS_ENABLED(CONFIG_VBOOT_VBNV_CMOS))
		read_vbnv_cmos(vbnv_copy);
	else if (IS_ENABLED(CONFIG_VBOOT_VBNV_EC))
		read_vbnv_ec(vbnv_copy);
	else if (IS_ENABLED(CONFIG_VBOOT_VBNV_FLASH))
		read_vbnv_flash(vbnv_copy);

	/* Check data for consistency */
	if (!verify_vbnv(vbnv_copy))
		reset_vbnv(vbnv_copy);
}

/*
 * Write VBNV data to configured storage backend.
 * This assumes that the caller has updated the CRC already.
 */
void save_vbnv(const uint8_t *vbnv_copy)
{
	if (IS_ENABLED(CONFIG_VBOOT_VBNV_CMOS))
		save_vbnv_cmos(vbnv_copy);
	else if (IS_ENABLED(CONFIG_VBOOT_VBNV_EC))
		save_vbnv_ec(vbnv_copy);
	else if (IS_ENABLED(CONFIG_VBOOT_VBNV_FLASH))
		save_vbnv_flash(vbnv_copy);

	/* Clear initialized flag to force cached data to be updated */
	car_set_var(vbnv_initialized, 0);
}

/* Save a recovery reason into VBNV. */
void set_recovery_mode_into_vbnv(int recovery_reason)
{
	uint8_t vbnv_copy[VBOOT_VBNV_BLOCK_SIZE];

	read_vbnv(vbnv_copy);

	vbnv_copy[RECOVERY_OFFSET] = recovery_reason;
	vbnv_copy[CRC_OFFSET] = crc8_vbnv(vbnv_copy, CRC_OFFSET);

	save_vbnv(vbnv_copy);
}

/* Read the recovery reason from VBNV. */
int get_recovery_mode_from_vbnv(void)
{
	vbnv_setup();
	return vbnv_data(RECOVERY_OFFSET);
}

/* Read the BOOT_OPROM_NEEDED flag from VBNV. */
int vboot_wants_oprom(void)
{
	vbnv_setup();
	return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0;
}
