/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2011 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 <types.h>
#include <console/cbmem_console.h>
#include <console/console.h>
#include <arch/acpi.h>
#include <tpm.h>
#include <reset.h>

//#define EXTRA_LOGGING

#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256	/* saves space in the firmware */

#define TPM_SUCCESS               ((u32)0x00000000)

#define TPM_E_IOERROR             ((u32)0x0000001f)
#define TPM_E_COMMUNICATION_ERROR ((u32)0x00005004)
#define TPM_E_NON_FATAL           ((u32)0x00000800)
#define TPM_E_INVALID_POSTINIT    ((u32)0x00000026)

#define TPM_E_NEEDS_SELFTEST     ((u32)(TPM_E_NON_FATAL + 1))
#define TPM_E_DOING_SELFTEST     ((u32)(TPM_E_NON_FATAL + 2))

static const struct {
	u8 buffer[12];
} tpm_resume_cmd = {
	{ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2 }
};

static const struct {
	u8 buffer[12];
} tpm_startup_cmd = {
	{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1 }
};

static const struct {
	u8 buffer[12];
} tpm_deactivate_cmd = {
	{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x3 }
};

static const struct {
	u8 buffer[10];
} tpm_continueselftest_cmd = {
	{ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53 }
};

static inline void FromTpmUint32(const u8 * buffer, u32 * x)
{
	*x = ((buffer[0] << 24) |
	      (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);
}

static inline int TpmCommandSize(const u8 * buffer)
{
	u32 size;
	FromTpmUint32(buffer + sizeof(u16), &size);
	return (int)size;
}

/* Gets the code field of a TPM command. */
static inline int TpmCommandCode(const u8 * buffer)
{
	u32 code;
	FromTpmUint32(buffer + sizeof(u16) + sizeof(u32), &code);
	return code;
}

/* Gets the return code field of a TPM result. */
static inline int TpmReturnCode(const u8 * buffer)
{
	return TpmCommandCode(buffer);
}

/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or
 * DOING_SELFTEST errors are returned.
 */
static u32 TlclSendReceiveNoRetry(const u8 * request,
				  u8 * response, int max_length)
{
	size_t response_length = max_length;
	u32 result;

#ifdef EXTRA_LOGGING
	printk(BIOS_DEBUG, "TPM: command: %x%x %x%x%x%x %x%x%x%x\n",
	       request[0], request[1],
	       request[2], request[3], request[4], request[5],
	       request[6], request[7], request[8], request[9]);
#endif

	result = TPM_SUCCESS;
	if (tis_sendrecv
	    (request, TpmCommandSize(request), response, &response_length))
		result = TPM_E_IOERROR;

	if (0 != result) {
		/* Communication with TPM failed, so response is garbage */
		printk(BIOS_DEBUG,
		       "TPM: command 0x%x send/receive failed: 0x%x\n",
		       TpmCommandCode(request), result);
		return TPM_E_COMMUNICATION_ERROR;
	}
	/* Otherwise, use the result code from the response */
	result = TpmReturnCode(response);

/* TODO: add paranoia about returned response_length vs. max_length
 * (and possibly expected length from the response header).  See
 * crosbug.com/17017 */

#ifdef EXTRA_LOGGING
	printk(BIOS_DEBUG, "TPM: response: %x%x %x%x%x%x %x%x%x%x\n",
	       response[0], response[1],
	       response[2], response[3], response[4], response[5],
	       response[6], response[7], response[8], response[9]);
#endif

	printk(BIOS_DEBUG, "TPM: command 0x%x returned 0x%x\n",
	       TpmCommandCode(request), result);

	return result;
}

static inline u32 TlclContinueSelfTest(void)
{
	u8 response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
	printk(BIOS_DEBUG, "TPM: Continue self test\n");
	/* Call the No Retry version of SendReceive to avoid recursion. */
	return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer,
				      response, sizeof(response));
}

/* Sends a TPM command and gets a response.  Returns 0 if success or the TPM
 * error code if error. In the firmware, waits for the self test to complete
 * if needed. In the host, reports the first error without retries. */
static u32 TlclSendReceive(const u8 * request, u8 * response, int max_length)
{
	u32 result = TlclSendReceiveNoRetry(request, response, max_length);
	/* When compiling for the firmware, hide command failures due to the self
	 * test not having run or completed. */
	/* If the command fails because the self test has not completed, try it
	 * again after attempting to ensure that the self test has completed. */
	if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) {
		result = TlclContinueSelfTest();
		if (result != TPM_SUCCESS) {
			return result;
		}
#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE)
		/* Retry only once */
		result = TlclSendReceiveNoRetry(request, response, max_length);
#else
		/* This needs serious testing.  The TPM specification says:
		 * "iii. The caller MUST wait for the actions of
		 * TPM_ContinueSelfTest to complete before reissuing the
		 * command C1."  But, if ContinueSelfTest is non-blocking, how
		 * do we know that the actions have completed other than trying
		 * again? */
		do {
			result =
			    TlclSendReceiveNoRetry(request, response,
						   max_length);
		} while (result == TPM_E_DOING_SELFTEST);
#endif
	}

	return result;
}

void init_tpm(int s3resume)
{
	u32 result;
	u8 response[TPM_LARGE_ENOUGH_COMMAND_SIZE];

	if (IS_ENABLED(CONFIG_TPM_DEACTIVATE)) {
		printk(BIOS_SPEW, "TPM: Deactivate\n");
		result = TlclSendReceive(tpm_deactivate_cmd.buffer,
					response, sizeof(response));
		if (result == TPM_SUCCESS) {
			printk(BIOS_SPEW, "TPM: OK.\n");
			return;
		}

		printk(BIOS_ERR, "TPM: Error code 0x%x.\n", result);
		return;
	}

	/* Doing TPM startup when we're not coming in on the S3 resume path
	 * saves us roughly 20ms in boot time only. This does not seem to
	 * be worth an API change to vboot_reference-firmware right now, so
	 * let's keep the code around, but just bail out early:
	 */
	if (s3resume ? CONFIG_NO_TPM_RESUME
	    : CONFIG_SKIP_TPM_STARTUP_ON_NORMAL_BOOT)
		return;

	printk(BIOS_DEBUG, "TPM initialization.\n");

	printk(BIOS_SPEW, "TPM: Init\n");
	if (tis_init())
		return;

	printk(BIOS_SPEW, "TPM: Open\n");
	if (tis_open())
		return;


	if (s3resume) {
		/* S3 Resume */
		printk(BIOS_SPEW, "TPM: Resume\n");
		result = TlclSendReceive(tpm_resume_cmd.buffer,
					response, sizeof(response));
		if (result == TPM_E_INVALID_POSTINIT) {
			/* We're on a platform where the TPM maintains power
			 * in S3, so it's already initialized.
			 */
			printk(BIOS_DEBUG, "TPM: Already initialized.\n");
			return;
		}
	} else {
		printk(BIOS_SPEW, "TPM: Startup\n");
		result = TlclSendReceive(tpm_startup_cmd.buffer,
					response, sizeof(response));
	}

	if (result == TPM_SUCCESS) {
		printk(BIOS_SPEW, "TPM: OK.\n");
		return;
	}

	printk(BIOS_ERR, "TPM: Error code 0x%x.\n", result);

	if (IS_ENABLED(CONFIG_TPM_INIT_FAILURE_IS_FATAL)) {
		printk(BIOS_ERR, "Hard reset!\n");
		post_code(POST_TPM_FAILURE);
		if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART))
			cbmem_dump_console();
		hard_reset();
	}
}
