/* Copyright (c) 2011 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 vboot_api_firmware
 */

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

#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2secdata.h"
#include "2sysincludes.h"
#include "crc32.h"
#include "host_common.h"
#include "load_kernel_fw.h"
#include "secdata_tpm.h"
#include "test_common.h"
#include "vboot_display.h"
#include "vboot_kernel.h"
#include "vboot_struct.h"

/* Expected results */

#define MAX_NOTE_EVENTS 10
#define TIME_FUZZ 500
#define KBD_READ_TIME 60

typedef struct {
	uint16_t msec;
	uint16_t freq;
	int time;
} note_event_t;

typedef struct {
	const char *name;
	uint32_t gbb_flags;
	vb2_error_t beep_return;
	uint32_t keypress_key;
	int keypress_at_count;
	int num_events;
	note_event_t notes[MAX_NOTE_EVENTS];
} test_case_t;

test_case_t test[] = {

	{ "VbBootDeveloperSoundTest( fast )",
	  VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY, VBERROR_NO_BACKGROUND_SOUND,
	  0, 0,
	  1,
	  {
		{0, 0, 2000},		// off and return at 2 seconds
	  }},

	{ "VbBootDeveloperSoundTest( normal )",
	  0, VBERROR_NO_BACKGROUND_SOUND,
	  0, 0,
	  3,
	  {
		{250, 400, 20000},	// first beep at 20 seconds
		{250, 400, 20510},	// second beep shortly after
		{0, 0, 30020},	// off and return at 30 seconds
	  }},

	// Now with some keypresses

	{ "VbBootDeveloperSoundTest( normal, Ctrl-D )",
	  0, VBERROR_NO_BACKGROUND_SOUND,
	  4, 20400,			// Ctrl-D between beeps
	  2,
	  {
		{250, 400, 20000},	// first beep at 20 seconds
		{0, 0, 20400},	// sees Ctrl-D, sound off, return
	  }},

	{ "VbBootDeveloperSoundTest( normal, Ctrl-U not allowed )",
	  0, VBERROR_NO_BACKGROUND_SOUND,
	  21, 10000,                          // Ctrl-U at 10 seconds
	  5,
	  {
		{120, 400, 10000},	// complains about Ctrl-U (one beep)
		{120, 400, 10240},	// complains about Ctrl-U (two beeps)
		{250, 400, 20000},	// starts first beep at 20 seconds
		{250, 400, 20510},	// starts second beep
		{0, 0, 30020},	// returns at 30 seconds + 360ms
	  }},
};

/* Mock data */
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
static struct vb2_context *ctx;
static struct vb2_shared_data *sd;
static struct vb2_gbb_header gbb;
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
static int current_time;
static uint64_t current_ticks;
static int current_event;
static int max_events;
static int matched_events;
static int kbd_fire_at;
static uint32_t kbd_fire_key;
static vb2_error_t beep_return;
static note_event_t *expected_event;

/* Audio open count, so we can reset it */
extern int audio_open_count;

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

	sd = vb2_get_sd(ctx);
	sd->vbsd = shared;

	ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP;
	sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;

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

	memset(&shared_data, 0, sizeof(shared_data));
	shared->fw_keyblock_flags = 0xABCDE0;

	current_ticks = 0;
	current_time = 0;

	current_event = 0;
	kbd_fire_at = 0;
	kbd_fire_key = 0;

	beep_return = VB2_SUCCESS;
	audio_open_count = 0;

	matched_events = 0;
	max_events = 0;
}

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

vb2_error_t vb2_commit_data(struct vb2_context *c)
{
	return VB2_SUCCESS;
}

vb2_error_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
			    uint32_t disk_flags)
{
	return VB2_ERROR_UNKNOWN;
}

vb2_error_t VbExDiskFreeInfo(VbDiskInfo* infos,
			     VbExDiskHandle_t preserve_handle)
{
	return VB2_SUCCESS;
}

vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
			 uint64_t lba_count, void* buffer)
{
	return VB2_ERROR_UNKNOWN;
}

vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
			  uint64_t lba_count, const void* buffer)
{
	return VB2_ERROR_UNKNOWN;
}

uint32_t VbExIsShutdownRequested(void)
{
	return 0;
}

uint32_t VbExKeyboardRead(void)
{
	uint32_t tmp;
	uint32_t now;

	VbExSleepMs(KBD_READ_TIME);
	now = current_time;

	if (kbd_fire_key && now >= kbd_fire_at) {
		VB2_DEBUG("  VbExKeyboardRead() - returning %d at %d msec\n",
			  kbd_fire_key, now);
		tmp = kbd_fire_key;
		kbd_fire_key = 0;
		return tmp;
	}
	VB2_DEBUG("  VbExKeyboardRead() - returning %d at %d msec\n",
		  0, now);
	return 0;
}

void VbExSleepMs(uint32_t msec)
{
	current_ticks += (uint64_t)msec * VB_USEC_PER_MSEC;
	current_time = current_ticks / VB_USEC_PER_MSEC;
	VB2_DEBUG("VbExSleepMs(%d) -> %d\n", msec, current_time);
}

uint64_t VbExGetTimer(void)
{
	return current_ticks;
}

vb2_error_t VbExBeep(uint32_t msec, uint32_t frequency)
{
	VB2_DEBUG("VbExBeep(%d, %d) at %d msec\n",
		  msec, frequency, current_time);

	if (current_event < max_events &&
	    msec == expected_event[current_event].msec &&
	    frequency == expected_event[current_event].freq &&
	    abs(current_time - expected_event[current_event].time)
	    < TIME_FUZZ ) {
		matched_events++;
	}

	if (msec)
		VbExSleepMs(msec);
	current_event++;
	return beep_return;
}

vb2_error_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale,
			      const VbScreenData *data)
{
	switch(screen_type) {
		case VB_SCREEN_BLANK:
			VB2_DEBUG("VbExDisplayScreen(BLANK)\n");
			break;
		case VB_SCREEN_DEVELOPER_WARNING:
			VB2_DEBUG("VbExDisplayScreen(DEV)\n");
			break;
		case VB_SCREEN_RECOVERY_INSERT:
			VB2_DEBUG("VbExDisplayScreen(INSERT)\n");
			break;
		case VB_SCREEN_RECOVERY_NO_GOOD:
			VB2_DEBUG("VbExDisplayScreen(NO_GOOD)\n");
			break;
		case VB_SCREEN_OS_BROKEN:
			VB2_DEBUG("VbExDisplayScreen(BROKEN)\n");
			break;
		default:
			VB2_DEBUG("VbExDisplayScreen(%d)\n", screen_type);
	}

	VB2_DEBUG("  current_time is %d msec\n", current_time);

	return VB2_SUCCESS;
}

/****************************************************************************/

static void VbBootDeveloperSoundTest(void)
{
	int i;
	int num_tests =  sizeof(test) / sizeof(test_case_t);

	for (i=0; i<num_tests; i++) {
		VB2_DEBUG("STARTING %s ...\n", test[i].name);
		ResetMocks();
		gbb.flags = test[i].gbb_flags;
		beep_return = test[i].beep_return;
		kbd_fire_key = test[i].keypress_key;
		kbd_fire_at = test[i].keypress_at_count;
		max_events = test[i].num_events;
		expected_event = test[i].notes;
		(void) VbBootDeveloper(ctx);
		VbExBeep(0, 0); /* Dummy call to determine end time */
		VB2_DEBUG("INFO: matched %d total %d expected %d\n",
			  matched_events, current_event, test[i].num_events);
		TEST_TRUE(matched_events == test[i].num_events &&
			  current_event == test[i].num_events, test[i].name);
	}
}

int main(int argc, char* argv[])
{
	VbBootDeveloperSoundTest();
	return gTestSuccess ? 0 : 255;
}
