/*
 * libfdt - Flat Device Tree manipulation
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include "libfdt_env.h"

#include <fdt.h>
#include <libfdt.h>

#include "libfdt_internal.h"

static int check_header_sw(struct fdt_header *fdt)
{
	if (fdt_magic(fdt) != SW_MAGIC)
		return FDT_ERR_BADMAGIC;
	return 0;
}

static void *grab_space(struct fdt_header *fdt, int len)
{
	int offset = sw_size_dt_struct(fdt);
	int spaceleft;

	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
		- fdt_size_dt_strings(fdt);

	if ((offset + len < offset) || (offset + len > spaceleft))
		return NULL;

	fdt->version = cpu_to_fdt32(offset + len);
	return fdt_offset_ptr(fdt, offset, len);
}

struct fdt_header *fdt_create(void *buf, int bufsize)
{
	struct fdt_header *fdt = buf;

	if (bufsize < sizeof(struct fdt_header))
		return NULL;

	memset(buf, 0, bufsize);

	fdt->magic = cpu_to_fdt32(SW_MAGIC);
	fdt->totalsize = cpu_to_fdt32(bufsize);

	fdt->off_mem_rsvmap = cpu_to_fdt32(ALIGN(sizeof(*fdt),
						 sizeof(struct fdt_reserve_entry)));
	fdt->off_dt_struct = fdt->off_mem_rsvmap;
	fdt->off_dt_strings = fdt32_to_cpu(bufsize);

	return fdt;
}

int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t size)
{
	struct fdt_reserve_entry *re;
	int err = check_header_sw(fdt);
	int offset;

	if (err)
		return err;
	if (sw_size_dt_struct(fdt))
		return FDT_ERR_BADSTATE;

	offset = fdt_off_dt_struct(fdt);
	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
		return FDT_ERR_NOSPACE;

	re = (struct fdt_reserve_entry *)((void *)fdt + offset);
	re->address = cpu_to_fdt64(addr);
	re->size = cpu_to_fdt64(size);

	fdt->off_dt_struct = cpu_to_fdt32(offset + sizeof(*re));

	return 0;
}

int fdt_finish_reservemap(struct fdt_header *fdt)
{
	return fdt_add_reservemap_entry(fdt, 0, 0);
}

int fdt_begin_node(struct fdt_header *fdt, const char *name)
{
	struct fdt_node_header *nh;
	int err = check_header_sw(fdt);
	int namelen = strlen(name) + 1;

	if (err)
		return err;

	nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
	if (! nh)
		return FDT_ERR_NOSPACE;

	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
	memcpy(nh->name, name, namelen);
	return 0;
}

int fdt_end_node(struct fdt_header *fdt)
{
	uint32_t *en;
	int err = check_header_sw(fdt);

	if (err)
		return err;

	en = grab_space(fdt, FDT_TAGSIZE);
	if (! en)
		return FDT_ERR_NOSPACE;

	*en = cpu_to_fdt32(FDT_END_NODE);
	return 0;
}

static int find_add_string(struct fdt_header *fdt, const char *s)
{
	char *strtab = (char *)fdt + fdt_totalsize(fdt);
	int strtabsize = fdt_size_dt_strings(fdt);
	int len = strlen(s) + 1;
	int struct_top, offset;

	/* We treat string offsets as negative from the end of our buffer */
	/* then fix them up in fdt_finish() */
	offset = -strtabsize;
	while ((offset < 0) && (memcmp(strtab + offset, s, len) != 0))
		offset++;

	if (offset < 0)
		/* Found it */
		return offset;

	/* Add it */
	offset = -strtabsize - len;
	struct_top = fdt_off_dt_struct(fdt) + sw_size_dt_struct(fdt);
	if (fdt_totalsize(fdt) + offset < struct_top)
		return 0; /* no more room :( */

	memcpy(strtab + offset, s, len);
	fdt->size_dt_strings = cpu_to_fdt32(strtabsize + len);
	return offset;
}

int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int len)
{
	struct fdt_property *prop;
	int err = check_header_sw(fdt);
	int nameoff;

	if (err)
		return err;

	nameoff = find_add_string(fdt, name);
	if (nameoff == 0)
		return FDT_ERR_NOSPACE;

	prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
	if (! prop)
		return FDT_ERR_NOSPACE;

	prop->tag = cpu_to_fdt32(FDT_PROP);
	prop->nameoff = cpu_to_fdt32(nameoff);
	prop->len = cpu_to_fdt32(len);
	memcpy(prop->data, val, len);
	return 0;
}

int fdt_finish(struct fdt_header *fdt)
{
	int err = check_header_sw(fdt);
	char *p = (char *)fdt;
	uint32_t *end;
	int oldstroffset, newstroffset;
	uint32_t tag;
	int offset, nextoffset;

	if (err)
		return err;

	/* Add terminator */
	end = grab_space(fdt, sizeof(*end));
	if (! end)
		return FDT_ERR_NOSPACE;
	*end = cpu_to_fdt32(FDT_END);

	/* Relocate the string table */
	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
	newstroffset = fdt_off_dt_struct(fdt) + sw_size_dt_struct(fdt);
	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
	fdt->off_dt_strings = fdt32_to_cpu(newstroffset);

	/* Walk the structure, correcting string offsets */
	offset = 0;
	while ((tag = _fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
		if (tag == FDT_PROP) {
			struct fdt_property *prop = fdt_offset_ptr(fdt, offset,
								   sizeof(*prop));
			int nameoff;

			if (! prop)
				return FDT_ERR_BADSTRUCTURE;

			nameoff = fdt32_to_cpu(prop->nameoff);
			nameoff += fdt_size_dt_strings(fdt);
			prop->nameoff = cpu_to_fdt32(nameoff);
		}
		offset = nextoffset;
	}

	/* Finally, adjust the header */
	fdt->totalsize = cpu_to_fdt32(newstroffset + fdt_size_dt_strings(fdt));
	fdt->version = cpu_to_fdt32(FDT_LAST_SUPPORTED_VERSION);
	fdt->last_comp_version= cpu_to_fdt32(FDT_FIRST_SUPPORTED_VERSION);
	fdt->magic = cpu_to_fdt32(FDT_MAGIC);
	return 0;
}
