#include <tee_internal_api.h>
#include <string.h>
#include "tima_util.h"
#include "tima_ioctl.h"
#include "drTimaMm.h"
#define TAG "TIMA_LOG: "
log_header_t g_log_hdr;
char g_log_msg[LOG_MSG_SIZE];
extern long get_time(
	void
)
{
	return 0;
}

/* @log_start: starting virtual address of the log 
 * @log_size: MISLEADING WARNING: This is the nr_bytes that need to be memset to zero
 * 		NOT the actual size of the log.
 */
int log_init(
	log_info_t log_info
)
{
	log_header_t *header_ptr;
	printf(TAG "Init Log!\n");
	header_ptr = (log_header_t *) log_info.log_hdr_vaddr;
	TEE_MemFill((void *)log_info.log_hdr_vaddr, 0, TIMA_LOG_MAP_SIZE);
	header_ptr->magic = LOG_MAGIC;
	header_ptr->log_start_addr =
		log_info.log_start_paddr + sizeof(log_header_t);
	header_ptr->log_write_addr =
		log_info.log_start_paddr + sizeof(log_header_t);
	printf(TAG "log_init: log_start_addr is %x\n", header_ptr->log_start_addr);

	printf(TAG "log_init: log_write_addr is %x\n", header_ptr->log_write_addr);

	header_ptr->num_log_entries = 0;
	printf(TAG "Init Log Done!\n");
	return 0;
}

int32_t log_read(
	int32_t region,
	int32_t entry_index,
	void *rsp
)
{
	int32_t ret = 0;
	printf(TAG "log_read!\n");

	//buf_address = TIMA_SEC_LOG_VADDR;
#if 0
	ret =
	    qsee_register_shared_buffer((void *)(buf_address & SECT_MASK),
					1 << 20);
	if (ret != 0)
		return -1;
	memcpy(rsp, (void *)buf_address, 1 << 19);
	qsee_deregister_shared_buffer((void *)(buf_address & SECT_MASK));
#endif
	return ret;
}

int log_update_header(
	log_info_t log_info,
	uint32_t log_write_addr
)
{
	log_header_t *header_ptr = (log_header_t *) log_info.log_hdr_vaddr;
	/* num_log_entries counts total entries, not just circular buffer entries */
	header_ptr->num_log_entries++;

	if (log_write_addr + sizeof(log_entry_t) >=
		(log_info.log_start_paddr + log_info.log_size)) {
		/* Reset pointer to the start of the log. Circular */
		header_ptr->log_write_addr =
			log_info.log_start_paddr + sizeof(log_header_t);
		printf(TAG "log_update_header: [RST]log_write_addr is %x\n", header_ptr->log_write_addr);

	} else {
		header_ptr->log_write_addr =
			log_write_addr + sizeof(log_entry_t);
		printf(TAG "log_update_header: log_write_addr is %x\n", header_ptr->log_write_addr);

	}
//	printf(TAG "log_update_header done!\n");
	return 0;
}

int log_add_entry(
	log_info_t log_info,
	log_entry_t * pentry
)
{
	log_header_t *header_ptr;
	uint32_t write_ptr_paddr, write_ptr_vaddr;
	uint32_t drRet;
	header_ptr = (log_header_t *) log_info.log_hdr_vaddr;
	write_ptr_paddr = header_ptr->log_write_addr;
	/* Initialize sec_log memory */
	drRet = drApiMapPhys((void *) TIMA_SEC_LOG_PAGE, TIMA_LOG_MAP_SIZE,
			    (void *) (write_ptr_paddr & ~TIMA_LOG_MAP_MASK));
	if (0 != drRet) {
		printf(TAG "Cannot map sec_log val! Driver log_add_entry failed\n");
		drApiUnmap((void *)drRet, TIMA_LOG_MAP_SIZE);
		return drRet;
	}
	write_ptr_vaddr =
	    TIMA_SEC_LOG_PAGE + (write_ptr_paddr & TIMA_LOG_MAP_MASK);
	TEE_MemMove((void *) write_ptr_vaddr, pentry, sizeof(log_entry_t));
	drApiUnmap((void *) TIMA_SEC_LOG_PAGE, TIMA_LOG_MAP_SIZE);
	log_update_header(log_info, header_ptr->log_write_addr);
	return 0;
}

log_entry_t g_entry_ptr;
void log_msg(
	log_info_t log_info,
	char *msg
)
{
	TEE_MemFill(&g_entry_ptr, 0, sizeof(log_entry_t));
	g_entry_ptr.logger_id = 1;	/*FIXME */
	g_entry_ptr.timestamp = 9999;	/*FIXME how to get timestamp?   */
	snprintf(g_entry_ptr.log_msg, LOG_MSG_SIZE - 1, "%s", msg);
	log_add_entry(log_info, &g_entry_ptr);
	printf(msg);
}
