/******************************************************************************
 * Copyright (c) 2004, 2008 IBM Corporation
 * All rights reserved.
 * This program and the accompanying materials
 * are made available under the terms of the BSD License
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/bsd-license.php
 *
 * Contributors:
 *     IBM Corporation - initial implementation
 *****************************************************************************/

#include "cache.h"
#include "nvram.h"
#include "../libhvcall/libhvcall.h"

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <southbridge.h>
#include <nvramlog.h>
#include <byteorder.h>

#ifdef RTAS_NVRAM
static uint32_t fetch_token;
static uint32_t store_token;
static uint32_t NVRAM_LENGTH;
static char *nvram_buffer; /* use buffer allocated by SLOF code */
#else
#ifndef NVRAM_LENGTH
#define NVRAM_LENGTH	0x10000
#endif
/*
 * This is extremely ugly, but still better than implementing 
 * another sbrk() around it.
 */
static char nvram_buffer[NVRAM_LENGTH];
#endif

static uint8_t nvram_buffer_locked=0x00;

void nvram_init(uint32_t _fetch_token, uint32_t _store_token, 
		long _nvram_length, void* nvram_addr)
{
#ifdef RTAS_NVRAM
	fetch_token = _fetch_token;
	store_token = _store_token;
	NVRAM_LENGTH = _nvram_length;
	nvram_buffer = nvram_addr;

	DEBUG("\nNVRAM: size=%d, fetch=%x, store=%x\n",
		NVRAM_LENGTH, fetch_token, store_token);
#endif
}


void asm_cout(long Character,long UART,long NVRAM);

#if defined(DISABLE_NVRAM)

static volatile uint8_t nvram[NVRAM_LENGTH]; /* FAKE */

#define nvram_access(type,size,name) 				\
	type nvram_read_##name(unsigned int offset)		\
	{							\
		type *pos;					\
		if (offset > (NVRAM_LENGTH - sizeof(type)))	\
			return 0;				\
		pos = (type *)(nvram+offset);			\
		return *pos;					\
	}							\
	void nvram_write_##name(unsigned int offset, type data)	\
	{							\
		type *pos;					\
		if (offset > (NVRAM_LENGTH - sizeof(type)))	\
			return;					\
		pos = (type *)(nvram+offset);			\
		*pos = data;					\
	}

#elif defined(RTAS_NVRAM)

static inline void nvram_fetch(unsigned int offset, void *buf, unsigned int len)
{
 	struct hv_rtas_call rtas = {
		.token = fetch_token,
		.nargs = 3,
		.nrets = 2,
		.argret = { offset, (uint32_t)(unsigned long)buf, len },
	};
	h_rtas(&rtas);
}

static inline void nvram_store(unsigned int offset, void *buf, unsigned int len)
{
	struct hv_rtas_call rtas = {
		.token = store_token,
		.nargs = 3,
		.nrets = 2,
		.argret = { offset, (uint32_t)(unsigned long)buf, len },
	};
	h_rtas(&rtas);
}

#define nvram_access(type,size,name) 				\
	type nvram_read_##name(unsigned int offset)		\
	{							\
		type val;					\
		if (offset > (NVRAM_LENGTH - sizeof(type)))	\
			return 0;				\
		nvram_fetch(offset, &val, size / 8);		\
		return val;					\
	}							\
	void nvram_write_##name(unsigned int offset, type data)	\
	{							\
		if (offset > (NVRAM_LENGTH - sizeof(type)))	\
			return;					\
		nvram_store(offset, &data, size / 8);		\
	}

#else	/* DISABLE_NVRAM */

static volatile uint8_t *nvram = (volatile uint8_t *)SB_NVRAM_adr;

#define nvram_access(type,size,name) 				\
	type nvram_read_##name(unsigned int offset)		\
	{							\
		type *pos;					\
		if (offset > (NVRAM_LENGTH - sizeof(type)))	\
			return 0;				\
		pos = (type *)(nvram+offset);			\
		return ci_read_##size(pos);			\
	}							\
	void nvram_write_##name(unsigned int offset, type data)	\
	{							\
		type *pos;					\
		if (offset > (NVRAM_LENGTH - sizeof(type)))	\
			return;					\
		pos = (type *)(nvram+offset);			\
		ci_write_##size(pos, data);			\
	}

#endif

/*
 * producer for nvram access functions. Since these functions are
 * basically all the same except for the used data types, produce 
 * them via the nvram_access macro to keep the code from bloating.
 */

nvram_access(uint8_t,   8, byte)
nvram_access(uint16_t, 16, word)
nvram_access(uint32_t, 32, dword)
nvram_access(uint64_t, 64, qword)



/**
 * This function is a minimal abstraction for our temporary
 * buffer. It should have been malloced, but since there is no
 * usable malloc, we go this route.
 *
 * @return pointer to temporary buffer
 */

char *get_nvram_buffer(unsigned len)
{
	if(len>NVRAM_LENGTH)
		return NULL;

	if(nvram_buffer_locked)
		return NULL;

	nvram_buffer_locked = 0xff;

	return nvram_buffer;
}

/**
 * @param buffer pointer to the allocated buffer. This
 * is unused, but nice in case we ever get a real malloc
 */

void free_nvram_buffer(char *buffer __attribute__((unused)))
{
	nvram_buffer_locked = 0x00;
}

/**
 * @param fmt format string, like in printf
 * @param ... variable number of arguments
 */

int nvramlog_printf(const char* fmt, ...)
{
	char buff[256];
	int count, i;
	va_list ap;

	va_start(ap, fmt);
	count = vsprintf(buff, fmt, ap);
	va_end(ap);

	for (i=0; i<count; i++)
		asm_cout(buff[i], 0, 1);

	return count;
}

/**
 * @param offset start offset of the partition header
 */

static uint8_t get_partition_type(int offset)
{
	return nvram_read_byte(offset);
}

/**
 * @param offset start offset of the partition header
 */

static uint8_t get_partition_header_checksum(int offset)
{
	return nvram_read_byte(offset+1);
}

/**
 * @param offset start offset of the partition header
 */

static uint16_t get_partition_len(int offset)
{
	return nvram_read_word(offset+2);
}

/**
 * @param offset start offset of the partition header
 * @return static char array containing the partition name
 *
 * NOTE: If the partition name needs to be non-temporary, strdup 
 * and use the copy instead.
 */

static char * get_partition_name(int offset)
{
	static char name[12];
	int i;
	for (i=0; i<12; i++)
		name[i]=nvram_read_byte(offset+4+i);

	DEBUG("name: \"%s\"\n", name);
	return name;
}

static uint8_t calc_partition_header_checksum(int offset)
{
	uint16_t plainsum;
	uint8_t checksum;
	int i;

	plainsum = nvram_read_byte(offset);

	for (i=2; i<PARTITION_HEADER_SIZE; i++)
		plainsum+=nvram_read_byte(offset+i);

	checksum=(plainsum>>8)+(plainsum&0xff);

	return checksum;
}

static unsigned int calc_used_nvram_space(void)
{
	unsigned walk, len;

	for (walk=0; walk<NVRAM_LENGTH;) {
		if(nvram_read_byte(walk) == 0 
		   || get_partition_header_checksum(walk) != 
				calc_partition_header_checksum(walk)) {
			/* If there's no valid entry, bail out */
			break;
		}

		len=get_partition_len(walk);
		DEBUG("... part len=%x, %x\n", len, len*16);

		if(!len) {
			/* If there's a partition type but no len, bail out.
			 * Don't bail out if type is 0. This can be used to
			 * find the offset of the first free byte.
			 */
			break;
		}

		walk += len * 16;
	}
	DEBUG("used nvram space: %d\n", walk);

	return walk;
}

/**
 *
 * @param type partition type. Set this to the partition type you are looking
 *             for. If there are several partitions with the same type, only
 *             the first partition with that type will be found.
 *             Set to -1 to ignore. Set to 0 to find free unpartitioned space.
 *
 * @param name partition name. Set this to the name of the partition you are
 *             looking for. If there are several partitions with the same name,
 *             only the first partition with that name will be found.
 *             Set to NULL to ignore.
 *
 * To disambiguate the partitions you should have a unique name if you plan to
 * have several partitions of the same type.
 *
 */

partition_t get_partition(unsigned int type, char *name)
{
	partition_t ret={0,-1};
	unsigned walk, len;

	DEBUG("get_partition(%i, '%s')\n", type, name);

	for (walk=0; walk<NVRAM_LENGTH;) {
		// DEBUG("get_partition: walk=%x\n", walk);
		if(get_partition_header_checksum(walk) != 
				calc_partition_header_checksum(walk)) {
			/* If there's no valid entry, bail out */
			break;
		}

		len=get_partition_len(walk);
		if(type && !len) {
			/* If there's a partition type but no len, bail out.
			 * Don't bail out if type is 0. This can be used to
			 * find the offset of the first free byte.
			 */
			break;
		}

		/* Check if either type or name or both do not match. */
		if ( (type!=(unsigned int)-1 && type != get_partition_type(walk)) ||
			(name && strncmp(get_partition_name(walk), name, 12)) ) {
			/* We hit another partition. Continue
			 * at the end of this partition
			 */
			walk += len*16;
			continue;
		}

		ret.addr=walk+PARTITION_HEADER_SIZE;
		ret.len=(len*16)-PARTITION_HEADER_SIZE;
		break;
	}

	return ret;
}

/* Get partition specified by a Forth string */
partition_t get_partition_fs(char *name, int namelen)
{
	char buf[namelen + 1];

	memcpy(buf, name, namelen);
	buf[namelen] = 0;

	return get_partition(-1, buf);
}

void erase_nvram(int offset, int len)
{
	int i;

#ifdef RTAS_NVRAM
	char *erase_buf = get_nvram_buffer(len);
	if (erase_buf) {
		/* Speed up by erasing all memory at once */
		memset(erase_buf, 0, len);
		nvram_store(offset, erase_buf, len);
		free_nvram_buffer(erase_buf);
		return;
	}
	/* If get_nvram_buffer failed, fall through to default code */
#endif
	for (i=offset; i<offset+len; i++)
		nvram_write_byte(i, 0);
}

void wipe_nvram(void)
{
	erase_nvram(0, NVRAM_LENGTH);
}

/**
 * @param partition   partition structure pointing to the partition to wipe.
 * @param header_only if header_only is != 0 only the partition header is
 *                    nulled out, not the whole partition.
 */

int wipe_partition(partition_t partition, int header_only)
{
	int pstart, len;

	pstart=partition.addr-PARTITION_HEADER_SIZE;
	
	len=PARTITION_HEADER_SIZE;

	if(!header_only)
		len += partition.len;

	erase_nvram(pstart, len);

	return 0;
}


static partition_t create_nvram_partition(int type, const char *name, unsigned len)
{
	partition_t ret = { 0, 0 };
	unsigned i, offset, plen;

	plen = ALIGN(len+PARTITION_HEADER_SIZE, 16);

	DEBUG("Creating partition type=%x, name=%s, len=%d plen=%d\n",
			type, name, len, plen);

	offset = calc_used_nvram_space();

	if (NVRAM_LENGTH-(calc_used_nvram_space())<plen) {
		DEBUG("Not enough free space.\n");
		return ret;
	}

	DEBUG("Writing header.");

	nvram_write_byte(offset, type);
	nvram_write_word(offset+2, plen/16);

	for (i=0; i<strlen(name); i++)
		nvram_write_byte(offset+4+i, name[i]);

	nvram_write_byte(offset+1, calc_partition_header_checksum(offset));

	ret.addr = offset+PARTITION_HEADER_SIZE;
	ret.len = len;

	DEBUG("partition created: addr=%lx len=%lx\n", ret.addr, ret.len);

	return ret;
}

static int create_free_partition(void)
{
	int free_space;
	partition_t free_part;

	free_space = NVRAM_LENGTH - calc_used_nvram_space() - PARTITION_HEADER_SIZE;
	free_part = create_nvram_partition(0x7f, "free space", free_space);

	return (free_part.addr != 0);
}

partition_t new_nvram_partition(int type, char *name, int len)
{
	partition_t free_part, new_part = { 0, 0 };

	/* NOTE: Assume all free space is consumed by the "free space"
	 * partition. This means a partition can not be increased in the middle
	 * of reset_nvram, which is obviously not a big loss.
	 */

	free_part=get_partition(0x7f, NULL);
	if( free_part.len && free_part.len != -1)
		wipe_partition(free_part, 1);

	new_part = create_nvram_partition(type, name, len);

	if(new_part.len != len) {
		new_part.len = 0;
		new_part.addr = 0;
	}

	create_free_partition();

	return new_part;
}

partition_t new_nvram_partition_fs(int type, char *name, int namelen, int len)
{
	char buf[13];
	int i;

	for (i = 0; i < 12; i++) {
		if (i < namelen)
			buf[i] = name[i];
		else
			buf[i] = 0;
	}
	buf[12] = 0;

	return new_nvram_partition(type, buf, len);
}

/**
 * @param partition   partition structure pointing to the partition to wipe.
 */

int delete_nvram_partition(partition_t partition)
{
	unsigned i;
	partition_t free_part;

	if(!partition.len || partition.len == -1)
		return 0;

	for (i=partition.addr+partition.len; i< NVRAM_LENGTH; i++) 
		nvram_write_byte(i - partition.len - PARTITION_HEADER_SIZE, nvram_read_byte(i));

	erase_nvram(NVRAM_LENGTH-partition.len-PARTITION_HEADER_SIZE, 
			partition.len-PARTITION_HEADER_SIZE);

	free_part=get_partition(0x7f, NULL);
	wipe_partition(free_part, 0);
	create_free_partition();

	return 1;
}

int clear_nvram_partition(partition_t part)
{
	if(!part.addr)
		return 0;

	erase_nvram(part.addr, part.len);

	return 1;
}


int increase_nvram_partition_size(partition_t partition, int newsize)
{
	partition_t free_part;
	int free_offset, end_offset, i;

	/* We don't support shrinking partitions (yet) */
	if (newsize < partition.len) {
		return 0;
	}

	/* NOTE: Assume all free space is consumed by the "free space"
	 * partition. This means a partition can not be increased in the middle
	 * of reset_nvram, which is obviously not a big loss.
	 */

	free_part=get_partition(0x7f, NULL);

	// FIXME: It could be 16 byte more. Also handle empty "free" partition.
	if (free_part.len == -1 || free_part.len < newsize - partition.len ) {
		return 0;
	}
	
	free_offset=free_part.addr - PARTITION_HEADER_SIZE; // first unused byte
	end_offset=partition.addr + partition.len; // last used byte of partition + 1

	if(free_offset > end_offset) {
		int j, bufferlen;
		char *overlap_buffer;

		bufferlen=free_offset - end_offset;

		overlap_buffer=get_nvram_buffer(bufferlen);
		if(!overlap_buffer) {
			return 0;
		}

		for (i=end_offset, j=0; i<free_offset; i++, j++)
			overlap_buffer[j]=nvram_read_byte(i);

		/* Only wipe the header. The free space partition is empty per
		 * definition
		 */

		wipe_partition(free_part, 1);

		for (i=partition.addr+newsize, j=0; i<(int)(partition.addr+newsize+bufferlen); i++, j++)
			nvram_write_byte(i, overlap_buffer[j]);

		free_nvram_buffer(overlap_buffer);
	} else {
		/* Only wipe the header. */
		wipe_partition(free_part, 1);
	}

	/* Clear the new partition space */
	erase_nvram(partition.addr+partition.len, newsize-partition.len);

	nvram_write_word(partition.addr - 16 + 2, newsize);

	create_free_partition();

	return 1;
}

static void init_cpulog_partition(partition_t cpulog)
{
	unsigned int offset=cpulog.addr;

	/* see board-xxx/include/nvramlog.h for information */
	nvram_write_word(offset+0, 0x40);  // offset
	nvram_write_word(offset+2, 0x00);  // flags
	nvram_write_dword(offset+4, 0x01); // pointer

}

void reset_nvram(void)
{
	partition_t cpulog0, cpulog1;
	struct {
		uint32_t prefix;
		uint64_t name;
	} __attribute__((packed)) header;

	DEBUG("Erasing NVRAM\n");
	erase_nvram(0, NVRAM_LENGTH);

	DEBUG("Creating CPU log partitions\n");
	header.prefix = be32_to_cpu(LLFW_LOG_BE0_NAME_PREFIX);
	header.name   = be64_to_cpu(LLFW_LOG_BE0_NAME);
	cpulog0=create_nvram_partition(LLFW_LOG_BE0_SIGNATURE, (char *)&header, 
			(LLFW_LOG_BE0_LENGTH*16)-PARTITION_HEADER_SIZE);

	header.prefix = be32_to_cpu(LLFW_LOG_BE1_NAME_PREFIX);
	header.name   = be64_to_cpu(LLFW_LOG_BE1_NAME);
	cpulog1=create_nvram_partition(LLFW_LOG_BE1_SIGNATURE, (char *)&header, 
			(LLFW_LOG_BE1_LENGTH*16)-PARTITION_HEADER_SIZE);

	DEBUG("Initializing CPU log partitions\n");
	init_cpulog_partition(cpulog0);
	init_cpulog_partition(cpulog1);

	nvramlog_printf("Creating common NVRAM partition\r\n");
	create_nvram_partition(0x70, "common", 0x01000-PARTITION_HEADER_SIZE);

	create_free_partition();
}

void nvram_debug(void)
{
#ifndef RTAS_NVRAM
	printf("\nNVRAM_BASE: %p\n", nvram);
	printf("NVRAM_LEN: 0x%x\n", NVRAM_LENGTH);
#endif
}

unsigned int get_nvram_size(void)
{
	return NVRAM_LENGTH;
}
