/*
 * 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"

#define CHECK_HEADER(fdt) \
	{ \
		int err; \
		if ((err = _fdt_check_header(fdt)) != 0) \
			return err; \
	}

static int offset_streq(const void *fdt, int offset,
			const char *s, int len)
{
	const char *p = fdt_offset_ptr(fdt, offset, len+1);

	if (! p)
		/* short match */
		return 0;

	if (memcmp(p, s, len) != 0)
		return 0;

	if (p[len] != '\0')
		return 0;

	return 1;
}

/*
 * Return a pointer to the string at the given string offset.
 */
char *fdt_string(const void *fdt, int stroffset)
{
	return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}

/*
 * Return the node offset of the node specified by:
 *   parentoffset - starting place (0 to start at the root)
 *   name         - name being searched for
 *   namelen      - length of the name: typically strlen(name)
 *
 * Notes:
 *   If the start node has subnodes, the subnodes are _not_ searched for the
 *     requested name.
 */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
			       const char *name, int namelen)
{
	int level = 0;
	uint32_t tag;
	int offset, nextoffset;

	CHECK_HEADER(fdt);

	tag = fdt_next_tag(fdt, parentoffset, &nextoffset, NULL);
	if (tag != FDT_BEGIN_NODE)
		return -FDT_ERR_BADOFFSET;

	do {
		offset = nextoffset;
		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);

		switch (tag) {
		case FDT_END:
			return -FDT_ERR_TRUNCATED;

		case FDT_BEGIN_NODE:
			level++;
			/*
			 * If we are nested down levels, ignore the strings
			 * until we get back to the proper level.
			 */
			if (level != 1)
				continue;

			/* Return the offset if this is "our" string. */
			if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen))
				return offset;
			break;

		case FDT_END_NODE:
			level--;
			break;

		case FDT_PROP:
		case FDT_NOP:
			break;

		default:
			return -FDT_ERR_BADSTRUCTURE;
		}
	} while (level >= 0);

	return -FDT_ERR_NOTFOUND;
}

/*
 * See fdt_subnode_offset_namelen()
 */
int fdt_subnode_offset(const void *fdt, int parentoffset,
		       const char *name)
{
	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
}

/*
 * Searches for the node corresponding to the given path and returns the
 * offset of that node.
 */
int fdt_path_offset(const void *fdt, const char *path)
{
	const char *end = path + strlen(path);
	const char *p = path;
	int offset = 0;

	CHECK_HEADER(fdt);

	/* Paths must be absolute */
	if (*path != '/')
		return -FDT_ERR_BADPATH;

	while (*p) {
		const char *q;

		/* Skip path separator(s) */
		while (*p == '/')
			p++;
		if (! *p)
			return -FDT_ERR_BADPATH;

		/*
		 * Find the next path separator.  The characters between
		 * p and q are the next segment of the the path to find.
		 */
		q = strchr(p, '/');
		if (! q)
			q = end;

		/*
		 * Find the offset corresponding to the this path segment.
		 */
		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);

		/* Oops, error, abort abort abort */
		if (offset < 0)
			return offset;

		p = q;
	}

	return offset;	
}

/*
 * Given the offset of a node and a name of a property in that node, return
 * a pointer to the property struct.
 */
struct fdt_property *fdt_get_property(const void *fdt,
				      int nodeoffset,
				      const char *name, int *lenp)
{
	int level = 0;
	uint32_t tag;
	struct fdt_property *prop;
	int namestroff;
	int offset, nextoffset;
	int err;

	if ((err = _fdt_check_header(fdt)) != 0)
		goto fail;

	err = -FDT_ERR_BADOFFSET;
	if (nodeoffset % FDT_TAGSIZE)
		goto fail;

	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
	if (tag != FDT_BEGIN_NODE)
		goto fail;

	do {
		offset = nextoffset;

		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
		switch (tag) {
		case FDT_END:
			err = -FDT_ERR_TRUNCATED;
			goto fail;

		case FDT_BEGIN_NODE:
			level++;
			break;

		case FDT_END_NODE:
			level--;
			break;

		case FDT_PROP:
			/*
			 * If we are nested down levels, ignore the strings
			 * until we get back to the proper level.
			 */
			if (level != 0)
				continue;

			err = -FDT_ERR_BADSTRUCTURE;
			prop = fdt_offset_ptr_typed(fdt, offset, prop);
			if (! prop)
				goto fail;
			namestroff = fdt32_to_cpu(prop->nameoff);
			if (streq(fdt_string(fdt, namestroff), name)) {
				/* Found it! */
				int len = fdt32_to_cpu(prop->len);
				prop = fdt_offset_ptr(fdt, offset,
						      sizeof(*prop)+len);
				if (! prop)
					goto fail;

				if (lenp)
					*lenp = len;
				
				return prop;
			}
			break;

		case FDT_NOP:
			break;

		default:
			err = -FDT_ERR_BADSTRUCTURE;
			goto fail;
		}
	} while (level >= 0);

	err = -FDT_ERR_NOTFOUND;
 fail:
	if (lenp)
		*lenp = err;
	return NULL;
}

/*
 * Given the offset of a node and a name of a property in that node, return
 * a pointer to the property data (ONLY).
 */
void *fdt_getprop(const void *fdt, int nodeoffset,
		  const char *name, int *lenp)
{
	const struct fdt_property *prop;

	prop = fdt_get_property(fdt, nodeoffset, name, lenp);
	if (! prop)
		return NULL;

	return (void *)prop->data;
}


uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, char **namep)
{
	const uint32_t *tagp, *lenp;
	uint32_t tag;
	const char *p;

	if (offset % FDT_TAGSIZE)
		return -1;

	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
	if (! tagp)
		return FDT_END; /* premature end */
	tag = fdt32_to_cpu(*tagp);
	offset += FDT_TAGSIZE;

	switch (tag) {
	case FDT_BEGIN_NODE:
		if(namep)
			*namep = fdt_offset_ptr(fdt, offset, 1);

		/* skip name */
		do {
			p = fdt_offset_ptr(fdt, offset++, 1);
		} while (p && (*p != '\0'));
		if (! p)
			return FDT_END;
		break;
	case FDT_PROP:
		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
		if (! lenp)
			return FDT_END;
		/*
		 * Get the property and set the namep to the name.
		 */
		if(namep) {
			struct fdt_property *prop;

			prop = fdt_offset_ptr_typed(fdt, offset - FDT_TAGSIZE, prop);
			if (! prop)
				return -FDT_ERR_BADSTRUCTURE;
			*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
		}
		/* skip name offset, length and value */
		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
		break;
	}

	if (nextoffset)
		*nextoffset = ALIGN(offset, FDT_TAGSIZE);

	return tag;
}

