/* Copyright 2019 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.
 *
 * Tests for auxfw synchronization.
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2sysincludes.h"
#include "host_common.h"
#include "load_kernel_fw.h"
#include "test_common.h"
#include "vboot_audio.h"
#include "vboot_kernel.h"
#include "vboot_struct.h"

/* Mock data */
static struct vb2_context *ctx;
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
static struct vb2_shared_data *sd;
static struct vb2_gbb_header gbb;

static vb2_error_t auxfw_retval;
static int auxfw_update_req;
static enum vb2_auxfw_update_severity auxfw_mock_severity;
static enum vb2_auxfw_update_severity auxfw_update_severity;
static int auxfw_mock_display_available;
static int auxfw_protected;
static vb2_error_t auxfw_done_retval;

/* Reset mock data (for use before each test) */
static void ResetMocks(void)
{
	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
		  "vb2api_init failed");

	ctx->flags = VB2_CONTEXT_EC_SYNC_SUPPORTED;
	vb2_nv_init(ctx);

	sd = vb2_get_sd(ctx);

	memset(&gbb, 0, sizeof(gbb));

	auxfw_retval = VB2_SUCCESS;
	auxfw_mock_severity = VB2_AUXFW_NO_UPDATE;
	auxfw_update_severity = VB2_AUXFW_NO_UPDATE;
	auxfw_mock_display_available = 1;
	auxfw_update_req = 0;
	auxfw_protected = 0;
	auxfw_done_retval = VB2_SUCCESS;
}

/* Mock functions */
struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
{
	return &gbb;
}

vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity)
{
	*severity = auxfw_mock_severity;
	auxfw_update_severity = auxfw_mock_severity;
	if (*severity == VB2_AUXFW_SLOW_UPDATE)
		if (!auxfw_mock_display_available)
			return VB2_REQUEST_REBOOT;
	return VB2_SUCCESS;
}

vb2_error_t vb2ex_auxfw_update(void)
{
	if (auxfw_update_severity != VB2_AUXFW_NO_DEVICE &&
	    auxfw_update_severity != VB2_AUXFW_NO_UPDATE)
		auxfw_update_req = 1;
	return auxfw_retval;
}

vb2_error_t vb2ex_auxfw_finalize(struct vb2_context *c)
{
	auxfw_protected = auxfw_update_severity != VB2_AUXFW_NO_DEVICE;
	return auxfw_done_retval;
}

static void test_auxsync(vb2_error_t retval, int recovery_reason,
			 const char *desc)
{
	TEST_EQ(vb2api_auxfw_sync(ctx), retval, desc);
	TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
		recovery_reason, "  recovery reason");
}

/* Tests */

static void VbSoftwareSyncTest(void)
{
	ResetMocks();
	gbb.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
	auxfw_mock_severity = VB2_AUXFW_FAST_UPDATE;
	test_auxsync(VB2_REQUEST_REBOOT_EC_TO_RO, 0,
		     "VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC"
		     " does not disable auxfw update request");
	TEST_EQ(auxfw_update_req, 1, "  auxfw update requested");
	TEST_EQ(auxfw_protected, 0, "  auxfw protected");

	ResetMocks();
	gbb.flags |= VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC;
	auxfw_mock_severity = VB2_AUXFW_FAST_UPDATE;
	test_auxsync(VB2_SUCCESS, 0,
		     "VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC"
		     " disables auxfw update request");
	TEST_EQ(auxfw_update_req, 0, "  auxfw update disabled");
	TEST_EQ(auxfw_protected, 1, "  auxfw protected");

	ResetMocks();
	auxfw_mock_severity = VB2_AUXFW_NO_DEVICE;
	test_auxsync(VB2_SUCCESS, 0,
		     "No auxfw update needed");
	TEST_EQ(auxfw_update_req, 0, "  no auxfw update requested");
	TEST_EQ(auxfw_protected, 0, "  no auxfw protected");

	ResetMocks();
	auxfw_mock_severity = VB2_AUXFW_NO_UPDATE;
	test_auxsync(VB2_SUCCESS, 0,
		"No auxfw update needed");
	TEST_EQ(auxfw_update_req, 0, "  no auxfw update requested");
	TEST_EQ(auxfw_protected, 1, "  auxfw protected");

	ResetMocks();
	auxfw_mock_severity = VB2_AUXFW_FAST_UPDATE;
	test_auxsync(VB2_REQUEST_REBOOT_EC_TO_RO, 0,
		     "Fast auxfw update needed");
	TEST_EQ(auxfw_update_req, 1, "  auxfw update requested");
	TEST_EQ(auxfw_protected, 0, "  auxfw protected");

	ResetMocks();
	auxfw_mock_severity = VB2_AUXFW_SLOW_UPDATE;
	auxfw_mock_display_available = 0;
	test_auxsync(VB2_REQUEST_REBOOT, 0,
		     "Slow auxfw update needed - reboot for display");

	ResetMocks();
	auxfw_mock_severity = VB2_AUXFW_SLOW_UPDATE;
	test_auxsync(VB2_REQUEST_REBOOT_EC_TO_RO, 0,
		     "Slow auxfw update needed");
	TEST_EQ(auxfw_update_req, 1, "  auxfw update requested");
	TEST_EQ(auxfw_protected, 0, "  auxfw protected");

	ResetMocks();
	auxfw_mock_severity = VB2_AUXFW_FAST_UPDATE;
	auxfw_retval = VB2_ERROR_UNKNOWN;
	test_auxsync(VB2_ERROR_UNKNOWN, VB2_RECOVERY_AUXFW_UPDATE,
		     "Error updating auxfw");
}

int main(void)
{
	VbSoftwareSyncTest();

	return gTestSuccess ? 0 : 255;
}
