/* 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.
 *
 * Auxiliary firmware sync routines for vboot
 */

#include "2api.h"
#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2sysincludes.h"
#include "vboot_api.h"
#include "vboot_display.h"

/**
 * Display the WAIT screen
 */
static void display_wait_screen(struct vb2_context *ctx)
{
	VB2_DEBUG("AUX FW update is slow. Show WAIT screen.\n");
	VbDisplayScreen(ctx, VB_SCREEN_WAIT, 0, NULL);
}

/**
 * Determine if we are allowed to update auxfw
 *
 * @param ctx		Vboot2 context
 * @return boolean (true iff we can update auxfw)
 */
static int auxfw_sync_allowed(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);

	/* Reasons not to do sync at all */
	if (gbb->flags & VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC)
		return 0;
	if (sd->recovery_reason)
		return 0;
	return 1;
}

/**
 * Update the specified Aux FW and verify the update succeeded
 *
 * @param ctx		Vboot2 context
 * @return VB2_SUCCESS, or non-zero error code.
 */
static vb2_error_t update_auxfw(struct vb2_context *ctx)
{
	vb2_error_t rv;

	VB2_DEBUG("Updating auxfw\n");

	/*
	 * The underlying platform is expected to know how and where to find the
	 * firmware image for all auxfw devices.
	 */
	rv = vb2ex_auxfw_update();
	if (rv != VB2_SUCCESS) {
		VB2_DEBUG("vb2ex_auxfw_update() returned %d\n", rv);

		/*
		 * The device may need a reboot.  It may need to unprotect the
		 * region before updating, or may need to reboot after updating.
		 * Either way, it's not an error requiring recovery mode.
		 *
		 * If we fail for any other reason, trigger recovery mode.
		 */
		if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
			vb2api_fail(ctx, VB2_RECOVERY_AUX_FW_UPDATE, rv);
	}

	return rv;
}

/**
 * Decides if auxfw sync is allowed to be performed
 *
 * If sync is allowed, invokes the external callback,
 * vb2ex_auxfw_check() to allow the client to decide on the auxfw
 * update severity.
 *
 * @param ctx		Vboot2 context
 * @return VB2_SUCCESS, or non-zero error code.
 */
static vb2_error_t auxfw_sync_check_update(struct vb2_context *ctx,
					   enum vb2_auxfw_update_severity *severity)
{
	if (!auxfw_sync_allowed(ctx)) {
		*severity = VB_AUX_FW_NO_UPDATE;
		return VB2_SUCCESS;
	}

	return vb2ex_auxfw_check(severity);
}

vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx)
{
	enum vb2_auxfw_update_severity fw_update = VB_AUX_FW_NO_UPDATE;
	vb2_error_t rv;

	/* Check for update severity */
	rv = auxfw_sync_check_update(ctx, &fw_update);
	if (rv)
		return rv;

	/* If AUX FW update is slow display the wait screen */
	if (fw_update == VB_AUX_FW_SLOW_UPDATE) {
		/* Display should be available, but better check again */
		if (vb2api_need_reboot_for_display(ctx))
			return VBERROR_REBOOT_REQUIRED;
		display_wait_screen(ctx);
	}

	if (fw_update > VB_AUX_FW_NO_UPDATE) {
		rv = update_auxfw(ctx);
		if (rv)
			return rv;
		/*
		 * AUX FW Update is applied successfully. Request EC reboot to
		 * RO, so that the chips that had FW update get reset to a
		 * clean state.
		 */
		return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
	}

	return vb2ex_auxfw_finalize(ctx);
}
