/*
 * 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 <assert.h>
#include <cbmem.h>
#include <reset.h>
#include <string.h>
#include <vb2_api.h>
#include <security/vboot/misc.h>
#include <security/vboot/symbols.h>
#include <security/vboot/vboot_common.h>

struct selected_region {
	uint32_t offset;
	uint32_t size;
};

/*
 * this is placed at the start of the vboot work buffer. selected_region is used
 * for the verstage to return the location of the selected slot. buffer is used
 * by the vboot2 core. Keep the struct CPU architecture agnostic as it crosses
 * stage boundaries.
 */
struct vb2_working_data {
	struct selected_region selected_region;
	/* offset of the buffer from the start of this struct */
	uint32_t buffer_offset;
	uint32_t buffer_size;
};

static const size_t vb_work_buf_size = 16 * KiB;

static struct vb2_working_data * const vboot_get_working_data(void)
{
	if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
		/* cbmem_add() does a cbmem_find() first. */
		return cbmem_add(CBMEM_ID_VBOOT_WORKBUF, vb_work_buf_size);
	else
		return (struct vb2_working_data *)_vboot2_work;
}

static size_t vb2_working_data_size(void)
{
	if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
		return vb_work_buf_size;
	else
		return REGION_SIZE(vboot2_work);
}

static struct selected_region *vb2_selected_region(void)
{
	struct selected_region *sel_reg = NULL;

	/* Ramstage and postcar always uses cbmem as a source of truth. */
	if (ENV_RAMSTAGE || ENV_POSTCAR)
		sel_reg = cbmem_find(CBMEM_ID_VBOOT_SEL_REG);
	else if (ENV_ROMSTAGE) {
		/* Try cbmem first. Fall back on working data if not found. */
		sel_reg = cbmem_find(CBMEM_ID_VBOOT_SEL_REG);

		if (sel_reg == NULL) {
			struct vb2_working_data *wd = vboot_get_working_data();
			sel_reg = &wd->selected_region;
		}
	} else {
		/* Stages such as bootblock and verstage use working data. */
		struct vb2_working_data *wd = vboot_get_working_data();
		sel_reg = &wd->selected_region;
	}

	return sel_reg;
}

void vb2_init_work_context(struct vb2_context *ctx)
{
	struct vb2_working_data *wd;
	size_t work_size;

	/* First initialize the working data region. */
	work_size = vb2_working_data_size();
	wd = vboot_get_working_data();
	memset(wd, 0, work_size);

	/*
	 * vboot prefers 16-byte alignment. This takes away 16 bytes
	 * from the VBOOT2_WORK region, but the vboot devs said that's okay.
	 */
	wd->buffer_offset = ALIGN_UP(sizeof(*wd), 16);
	wd->buffer_size = work_size - wd->buffer_offset;

	/* Initialize the vb2_context. */
	memset(ctx, 0, sizeof(*ctx));
	ctx->workbuf = (void *)vb2_get_shared_data();
	ctx->workbuf_size = wd->buffer_size;

}

struct vb2_shared_data *vb2_get_shared_data(void)
{
	struct vb2_working_data *wd = vboot_get_working_data();
	return (void *)((uintptr_t)wd + wd->buffer_offset);
}

int vb2_get_selected_region(struct region *region)
{
	const struct selected_region *reg = vb2_selected_region();

	if (reg == NULL)
		return -1;

	if (reg->offset == 0 && reg->size == 0)
		return -1;

	region->offset = reg->offset;
	region->size = reg->size;

	return 0;
}

void vb2_set_selected_region(const struct region *region)
{
	struct selected_region *reg = vb2_selected_region();

	assert(reg != NULL);

	reg->offset = region_offset(region);
	reg->size = region_sz(region);
}

int vb2_is_slot_selected(void)
{
	const struct selected_region *reg = vb2_selected_region();

	assert(reg != NULL);

	return reg->size > 0;
}

void vb2_store_selected_region(void)
{
	const struct vb2_working_data *wd;
	struct selected_region *sel_reg;

	/* Always use the working data in this path since it's the object
	 * which has the result.. */
	wd = vboot_get_working_data();

	sel_reg = cbmem_add(CBMEM_ID_VBOOT_SEL_REG, sizeof(*sel_reg));

	assert(sel_reg != NULL);

	sel_reg->offset = wd->selected_region.offset;
	sel_reg->size = wd->selected_region.size;
}

/*
 * For platforms that employ VBOOT_STARTS_IN_ROMSTAGE, the vboot
 * verification doesn't happen until after cbmem is brought online.
 * Therefore, the selected region contents would not be initialized
 * so don't automatically add results when cbmem comes online.
 */
#if !IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)
static void vb2_store_selected_region_cbmem(int unused)
{
	vb2_store_selected_region();
}
ROMSTAGE_CBMEM_INIT_HOOK(vb2_store_selected_region_cbmem)
#endif
