public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0 of 7] PowerPC kvm-userspace patches
@ 2008-03-12  4:50 Jerone Young
  2008-03-12  4:50 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

This set of patches enables the following:
	-Device tree Support
		- Add libfdt to kvm-userspace
		- Add bamboo device tree to qemu source
        	- Detection of host Device Tree attributes
		- Device tree loading
       	 	- Ability to specify initrd on the command line
        	- Ability to add kernel arguments on the command line
	- Ability to load compressed uImages
	- Ability to specify memory on the command line

So now when running powerpc code on a 440board. 

Known Issues:
   There is an issue currently where guest kernel is not mounting the initrd.
   Working it now!

   But these changes should go in anyway.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1 of 7] Add libfdt to KVM userspace
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-13  2:25   ` [kvm-ppc-devel] " Hollis Blanchard
  2008-03-12  4:50 ` [PATCH 2 of 7] Add libfdt support to qemu Jerone Young
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID cb3ca3805e7735fffcf42032b917cc761b145fb3
# Parent  c8f0f8c7d872cc909bdc32c14a9e3c49d632c6e6
Add libfdt to KVM userspace

This patch adds libfdt to allow for motification of device tree entries into
the KVM userspace tree.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ DESTDIR=
 
 rpmrelease = devel
 
-.PHONY: kernel user libkvm qemu bios vgabios extboot clean
+.PHONY: kernel user libkvm qemu bios vgabios extboot clean libfdt
 
 all: libkvm qemu
 ifneq '$(filter $(ARCH), x86_64 i386 ia64)' ''
@@ -20,6 +20,9 @@ qemu: libkvm
 qemu: libkvm
 ifneq '$(filter $(ARCH), i386 x86_64)' ''
     qemu: extboot
+endif
+ifneq '$(filter $(ARCH), powerpc)' ''
+    qemu: libfdt
 endif
 user: libkvm
 
@@ -38,6 +41,8 @@ extboot:
            || ! cmp -s qemu/pc-bios/extboot.bin extboot/extboot.bin; then \
 		cp extboot/extboot.bin qemu/pc-bios/extboot.bin; \
 	fi
+libfdt:
+	$(MAKE) -C $@
 
 
 bindir = /usr/bin
@@ -88,7 +93,7 @@ srpm:
 	$(RM) $(tmpspec)
 
 clean:
-	for i in $(if $(WANT_MODULE), kernel) user libkvm qemu; do \
+	for i in $(if $(WANT_MODULE), kernel) user libkvm qemu libfdt; do \
 		make -C $$i clean; \
 	done
 	rm -f config.mak user/config.mak
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -103,6 +103,9 @@ fi
 
 if [ "$arch" = "powerpc" ]; then
     target_exec="ppcemb-softmmu"
+    qemu_cflags="$qemu_cflags -I $PWD/libfdt"
+    qemu_ldflags="$qemu_ldflags -L $PWD/libfdt"
+    qemu_opts="$qemu_opts --enable-libfdt"
 fi
 
 #configure user dir
diff --git a/libfdt/Makefile b/libfdt/Makefile
new file mode 100644
--- /dev/null
+++ b/libfdt/Makefile
@@ -0,0 +1,19 @@
+include ../config.mak
+include ../user/config.mak
+
+LIBFDT_OBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o
+
+LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_EXTRA = libfdt_internal.h
+
+LIBFDT_LIB = libfdt.a
+
+CFLAGS += -I .
+
+all: libfdt.a
+
+libfdt.a: $(LIBFDT_OBJS)
+	$(AR) rcs $@ $^
+
+clean: 
+	rm -rf *.o *.a
diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
new file mode 100644
--- /dev/null
+++ b/libfdt/Makefile.libfdt
@@ -0,0 +1,14 @@
+# Makefile.libfdt
+#
+# This is not a complete Makefile of itself.  Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_EXTRA = libfdt_internal.h
+LIBFDT_LIB = libfdt/libfdt.a
+
+LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+
+$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
+
diff --git a/libfdt/README b/libfdt/README
new file mode 100644
--- /dev/null
+++ b/libfdt/README
@@ -0,0 +1,2 @@
+libfdt was grabbed from dtc source. It can be found here:
+http://www.jdl.com/git_repos/?p=dtc.git;a=summary
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt.c
@@ -0,0 +1,194 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		/* Complete tree */
+		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+	} else if (fdt_magic(fdt) == SW_MAGIC) {
+		/* Unfinished sequential-write blob */
+		if (fdt_size_dt_struct(fdt) == 0)
+			return -FDT_ERR_BADSTATE;
+	} else {
+		return -FDT_ERR_BADMAGIC;
+	}
+
+	return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+{
+	const void *p;
+
+	if (fdt_version(fdt) >= 0x11)
+		if (((offset + len) < offset)
+		    || ((offset + len) > fdt_size_dt_struct(fdt)))
+			return NULL;
+
+	p = _fdt_offset_ptr(fdt, offset);
+
+	if (p + len < p)
+		return NULL;
+	return p;
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+{
+	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:
+		/* 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;
+		/* skip name offset, length and value */
+		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+		break;
+	}
+
+	if (nextoffset)
+		*nextoffset = ALIGN(offset, FDT_TAGSIZE);
+
+	return tag;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+	int nextoffset = 0;
+	uint32_t tag;
+
+	if (offset >= 0) {
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		if (tag != FDT_BEGIN_NODE)
+			return -FDT_ERR_BADOFFSET;
+	}
+
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		case FDT_BEGIN_NODE:
+			if (depth)
+				(*depth)++;
+			break;
+
+		case FDT_END_NODE:
+			if (depth)
+				(*depth)--;
+			break;
+
+		case FDT_END:
+			return -FDT_ERR_NOTFOUND;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (tag != FDT_BEGIN_NODE);
+
+	return offset;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+	int len = strlen(s) + 1;
+	const char *last = strtab + tabsize - len;
+	const char *p;
+
+	for (p = strtab; p <= last; p++)
+		if (memeq(p, s, len))
+			return p;
+	return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+	CHECK_HEADER(fdt);
+
+	if (fdt_totalsize(fdt) > bufsize)
+		return -FDT_ERR_NOSPACE;
+
+	memmove(buf, fdt, fdt_totalsize(fdt));
+	return 0;
+}
diff --git a/libfdt/fdt.h b/libfdt/fdt.h
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt.h
@@ -0,0 +1,60 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+	uint32_t magic;			 /* magic word FDT_MAGIC */
+	uint32_t totalsize;		 /* total size of DT block */
+	uint32_t off_dt_struct;		 /* offset to structure */
+	uint32_t off_dt_strings;	 /* offset to strings */
+	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
+	uint32_t version;		 /* format version */
+	uint32_t last_comp_version;	 /* last compatible version */
+
+	/* version 2 fields below */
+	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
+					    booting on */
+	/* version 3 fields below */
+	uint32_t size_dt_strings;	 /* size of the strings block */
+
+	/* version 17 fields below */
+	uint32_t size_dt_struct;	 /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+	uint64_t address;
+	uint64_t size;
+};
+
+struct fdt_node_header {
+	uint32_t tag;
+	char name[0];
+};
+
+struct fdt_property {
+	uint32_t tag;
+	uint32_t len;
+	uint32_t nameoff;
+	char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
+#define FDT_TAGSIZE	sizeof(uint32_t)
+
+#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
+#define FDT_END_NODE	0x2		/* End node */
+#define FDT_PROP	0x3		/* Property: name off,
+					   size, content */
+#define FDT_NOP		0x4		/* nop */
+#define FDT_END		0x9
+
+#define FDT_V1_SIZE	(7*sizeof(uint32_t))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V16_SIZE	FDT_V3_SIZE
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
+
+#endif /* _FDT_H */
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt_ro.c
@@ -0,0 +1,476 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int nodename_eq(const void *fdt, int offset,
+		       const char *s, int len)
+{
+	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+
+	if (! p)
+		/* short match */
+		return 0;
+
+	if (memcmp(p, s, len) != 0)
+		return 0;
+
+	if (p[len] == '\0')
+		return 1;
+	else if (!memchr(s, '@', len) && (p[len] == '@'))
+		return 1;
+	else
+		return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+	return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
+{
+	CHECK_HEADER(fdt);
+	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+	return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+	int i = 0;
+
+	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+		i++;
+	return i;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+			       const char *name, int namelen)
+{
+	int depth;
+
+	CHECK_HEADER(fdt);
+
+	for (depth = 0;
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, &depth)) {
+		if (depth < 0)
+			return -FDT_ERR_NOTFOUND;
+		else if ((depth == 1)
+			 && nodename_eq(fdt, offset, name, namelen))
+			return offset;
+	}
+
+	return offset; /* error */
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+		       const char *name)
+{
+	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+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);
+
+	if (*path != '/')
+		return -FDT_ERR_BADPATH;
+
+	while (*p) {
+		const char *q;
+
+		while (*p == '/')
+			p++;
+		if (! *p)
+			return offset;
+		q = strchr(p, '/');
+		if (! q)
+			q = end;
+
+		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+		if (offset < 0)
+			return offset;
+
+		p = q;
+	}
+
+	return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+	const struct fdt_node_header *nh;
+	int err;
+
+	if ((err = fdt_check_header(fdt)) != 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
+	if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
+		goto fail;
+
+	if (len)
+		*len = strlen(nh->name);
+
+	return nh->name;
+
+ fail:
+	if (len)
+		*len = err;
+	return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+					    int nodeoffset,
+					    const char *name, int *lenp)
+{
+	uint32_t tag;
+	const 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);
+	if (tag != FDT_BEGIN_NODE)
+		goto fail;
+
+	do {
+		offset = nextoffset;
+
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		switch (tag) {
+		case FDT_END:
+			err = -FDT_ERR_TRUNCATED;
+			goto fail;
+
+		case FDT_BEGIN_NODE:
+		case FDT_END_NODE:
+		case FDT_NOP:
+			break;
+
+		case FDT_PROP:
+			err = -FDT_ERR_BADSTRUCTURE;
+			prop = fdt_offset_ptr(fdt, offset, sizeof(*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;
+
+		default:
+			err = -FDT_ERR_BADSTRUCTURE;
+			goto fail;
+		}
+	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+
+	err = -FDT_ERR_NOTFOUND;
+ fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
+
+const 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 prop->data;
+}
+
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+	const uint32_t *php;
+	int len;
+
+	php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+	if (!php || (len != sizeof(*php)))
+		return 0;
+
+	return fdt32_to_cpu(*php);
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+	int pdepth = 0, p = 0;
+	int offset, depth, namelen;
+	const char *name;
+
+	CHECK_HEADER(fdt);
+
+	if (buflen < 2)
+		return -FDT_ERR_NOSPACE;
+
+	for (offset = 0, depth = 0;
+	     (offset >= 0) && (offset <= nodeoffset);
+	     offset = fdt_next_node(fdt, offset, &depth)) {
+		if (pdepth < depth)
+			continue; /* overflowed buffer */
+
+		while (pdepth > depth) {
+			do {
+				p--;
+			} while (buf[p-1] != '/');
+			pdepth--;
+		}
+
+		name = fdt_get_name(fdt, offset, &namelen);
+		if (!name)
+			return namelen;
+		if ((p + namelen + 1) <= buflen) {
+			memcpy(buf + p, name, namelen);
+			p += namelen;
+			buf[p++] = '/';
+			pdepth++;
+		}
+
+		if (offset == nodeoffset) {
+			if (pdepth < (depth + 1))
+				return -FDT_ERR_NOSPACE;
+
+			if (p > 1) /* special case so that root path is "/", not "" */
+				p--;
+			buf[p] = '\0';
+			return p;
+		}
+	}
+
+	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+		return -FDT_ERR_BADOFFSET;
+	else if (offset == -FDT_ERR_BADOFFSET)
+		return -FDT_ERR_BADSTRUCTURE;
+
+	return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth)
+{
+	int offset, depth;
+	int supernodeoffset = -FDT_ERR_INTERNAL;
+
+	CHECK_HEADER(fdt);
+
+	if (supernodedepth < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	for (offset = 0, depth = 0;
+	     (offset >= 0) && (offset <= nodeoffset);
+	     offset = fdt_next_node(fdt, offset, &depth)) {
+		if (depth == supernodedepth)
+			supernodeoffset = offset;
+
+		if (offset == nodeoffset) {
+			if (nodedepth)
+				*nodedepth = depth;
+
+			if (supernodedepth > depth)
+				return -FDT_ERR_NOTFOUND;
+			else
+				return supernodeoffset;
+		}
+	}
+
+	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+		return -FDT_ERR_BADOFFSET;
+	else if (offset == -FDT_ERR_BADOFFSET)
+		return -FDT_ERR_BADSTRUCTURE;
+
+	return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+	int nodedepth;
+	int err;
+
+	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+	if (err)
+		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+	return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+	int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+	if (nodedepth < 0)
+		return nodedepth;
+	return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+					    nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+				  const char *propname,
+				  const void *propval, int proplen)
+{
+	int offset;
+	const void *val;
+	int len;
+
+	CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we scan each
+	 * property of a node in fdt_getprop(), then if that didn't
+	 * find what we want, we scan over them again making our way
+	 * to the next node.  Still it's the easiest to implement
+	 * approach; performance can come later. */
+	for (offset = fdt_next_node(fdt, startoffset, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		val = fdt_getprop(fdt, offset, propname, &len);
+		if (val && (len == proplen)
+		    && (memcmp(val, propval, len) == 0))
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
+{
+	if ((phandle == 0) || (phandle == -1))
+		return -FDT_ERR_BADPHANDLE;
+	phandle = cpu_to_fdt32(phandle);
+	return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
+					     &phandle, sizeof(phandle));
+}
+
+int _stringlist_contains(const void *strlist, int listlen, const char *str)
+{
+	int len = strlen(str);
+	const void *p;
+
+	while (listlen >= len) {
+		if (memcmp(str, strlist, len+1) == 0)
+			return 1;
+		p = memchr(strlist, '\0', listlen);
+		if (!p)
+			return 0; /* malformed strlist.. */
+		listlen -= (p-strlist) + 1;
+		strlist = p + 1;
+	}
+	return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+			      const char *compatible)
+{
+	const void *prop;
+	int len;
+
+	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+	if (!prop)
+		return len;
+	if (_stringlist_contains(prop, len, compatible))
+		return 0;
+	else
+		return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+				  const char *compatible)
+{
+	int offset, err;
+
+	CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we scan each
+	 * property of a node in fdt_node_check_compatible(), then if
+	 * that didn't find what we want, we scan over them again
+	 * making our way to the next node.  Still it's the easiest to
+	 * implement approach; performance can come later. */
+	for (offset = fdt_next_node(fdt, startoffset, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		err = fdt_node_check_compatible(fdt, offset, compatible);
+		if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+			return err;
+		else if (err == 0)
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
+}
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt_rw.c
@@ -0,0 +1,467 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _blocks_misordered(const void *fdt,
+			      int mem_rsv_size, int struct_size)
+{
+	return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8))
+		|| (fdt_off_dt_struct(fdt) <
+		    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+		|| (fdt_off_dt_strings(fdt) <
+		    (fdt_off_dt_struct(fdt) + struct_size))
+		|| (fdt_totalsize(fdt) <
+		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int rw_check_header(void *fdt)
+{
+	CHECK_HEADER(fdt);
+
+	if (fdt_version(fdt) < 17)
+		return -FDT_ERR_BADVERSION;
+	if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+			       fdt_size_dt_struct(fdt)))
+		return -FDT_ERR_BADLAYOUT;
+	if (fdt_version(fdt) > 17)
+		fdt_set_version(fdt, 17);
+
+	return 0;
+}
+
+#define RW_CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = rw_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+static inline int _blob_data_size(void *fdt)
+{
+	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _blob_splice(void *fdt, void *p, int oldlen, int newlen)
+{
+	void *end = fdt + _blob_data_size(fdt);
+
+	if (((p + oldlen) < p) || ((p + oldlen) > end))
+		return -FDT_ERR_BADOFFSET;
+	if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt)))
+		return -FDT_ERR_NOSPACE;
+	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	return 0;
+}
+
+static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+				int oldn, int newn)
+{
+	int delta = (newn - oldn) * sizeof(*p);
+	int err;
+	err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+	if (err)
+		return err;
+	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _blob_splice_struct(void *fdt, void *p,
+			       int oldlen, int newlen)
+{
+	int delta = newlen - oldlen;
+	int err;
+
+	if ((err = _blob_splice(fdt, p, oldlen, newlen)))
+		return err;
+
+	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _blob_splice_string(void *fdt, int newlen)
+{
+	void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+	int err;
+
+	if ((err = _blob_splice(fdt, p, 0, newlen)))
+		return err;
+
+	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+	return 0;
+}
+
+static int _find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+	const char *p;
+	char *new;
+	int len = strlen(s) + 1;
+	int err;
+
+	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+	if (p)
+		/* found it */
+		return (p - strtab);
+
+	new = strtab + fdt_size_dt_strings(fdt);
+	err = _blob_splice_string(fdt, len);
+	if (err)
+		return err;
+
+	memcpy(new, s, len);
+	return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
+{
+	struct fdt_reserve_entry *re;
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+
+	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+	err = _blob_splice_mem_rsv(fdt, re, 0, 1);
+	if (err)
+		return err;
+
+	re->address = cpu_to_fdt64(address);
+	re->size = cpu_to_fdt64(size);
+	return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+	if (n >= fdt_num_mem_rsv(fdt))
+		return -FDT_ERR_NOTFOUND;
+
+	err = _blob_splice_mem_rsv(fdt, re, 1, 0);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int _resize_property(void *fdt, int nodeoffset, const char *name, int len,
+			    struct fdt_property **prop)
+{
+	int oldlen;
+	int err;
+
+	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (! (*prop))
+		return oldlen;
+
+	if ((err = _blob_splice_struct(fdt, (*prop)->data,
+				       ALIGN(oldlen, FDT_TAGSIZE),
+				       ALIGN(len, FDT_TAGSIZE))))
+		return err;
+
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
+			 struct fdt_property **prop)
+{
+	uint32_t tag;
+	int proplen;
+	int nextoffset;
+	int namestroff;
+	int err;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+
+	namestroff = _find_add_string(fdt, name);
+	if (namestroff < 0)
+		return namestroff;
+
+	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
+	proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE);
+
+	err = _blob_splice_struct(fdt, *prop, 0, proplen);
+	if (err)
+		return err;
+
+	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
+	(*prop)->nameoff = cpu_to_fdt32(namestroff);
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+	char *namep;
+	int oldlen, newlen;
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+
+	namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen);
+	if (!namep)
+		return oldlen;
+
+	newlen = strlen(name);
+
+	err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE),
+				  ALIGN(newlen+1, FDT_TAGSIZE));
+	if (err)
+		return err;
+
+	memcpy(namep, name, newlen+1);
+	return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+
+	err = _resize_property(fdt, nodeoffset, name, len, &prop);
+	if (err == -FDT_ERR_NOTFOUND)
+		err = _add_property(fdt, nodeoffset, name, len, &prop);
+	if (err)
+		return err;
+
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len, proplen;
+
+	RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE);
+	return _blob_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen)
+{
+	struct fdt_node_header *nh;
+	int offset, nextoffset;
+	int nodelen;
+	int err;
+	uint32_t tag;
+	uint32_t *endtag;
+
+	RW_CHECK_HEADER(fdt);
+
+	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+	if (offset >= 0)
+		return -FDT_ERR_EXISTS;
+	else if (offset != -FDT_ERR_NOTFOUND)
+		return offset;
+
+	/* Try to place the new node after the parent's properties */
+	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+	} while ((tag == FDT_PROP) || (tag == FDT_NOP));
+
+	nh = _fdt_offset_ptr_w(fdt, offset);
+	nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
+
+	err = _blob_splice_struct(fdt, nh, 0, nodelen);
+	if (err)
+		return err;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE));
+	memcpy(nh->name, name, namelen);
+	endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE);
+	*endtag = cpu_to_fdt32(FDT_END_NODE);
+
+	return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+	return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	RW_CHECK_HEADER(fdt);
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+				   endoffset - nodeoffset, 0);
+}
+
+static void _packblocks(const void *fdt, void *buf,
+		       int mem_rsv_size, int struct_size)
+{
+	int mem_rsv_off, struct_off, strings_off;
+
+	mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8);
+	struct_off = mem_rsv_off + mem_rsv_size;
+	strings_off = struct_off + struct_size;
+
+	memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size);
+	fdt_set_off_mem_rsvmap(buf, mem_rsv_off);
+
+	memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size);
+	fdt_set_off_dt_struct(buf, struct_off);
+	fdt_set_size_dt_struct(buf, struct_size);
+
+	memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt),
+		fdt_size_dt_strings(fdt));
+	fdt_set_off_dt_strings(buf, strings_off);
+	fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+	int err;
+	int mem_rsv_size, struct_size;
+	int newsize;
+	void *tmp;
+
+	CHECK_HEADER(fdt);
+
+	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+		* sizeof(struct fdt_reserve_entry);
+
+	if (fdt_version(fdt) >= 17) {
+		struct_size = fdt_size_dt_struct(fdt);
+	} else {
+		struct_size = 0;
+		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+			;
+	}
+
+	if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+		/* no further work necessary */
+		err = fdt_move(fdt, buf, bufsize);
+		if (err)
+			return err;
+		fdt_set_version(buf, 17);
+		fdt_set_size_dt_struct(buf, struct_size);
+		fdt_set_totalsize(buf, bufsize);
+		return 0;
+	}
+
+	/* Need to reorder */
+	newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+		+ struct_size + fdt_size_dt_strings(fdt);
+
+	if (bufsize < newsize)
+		return -FDT_ERR_NOSPACE;
+
+	if (((buf + newsize) <= fdt)
+	    || (buf >= (fdt + fdt_totalsize(fdt)))) {
+		tmp = buf;
+	} else {
+		tmp = (void *)fdt + fdt_totalsize(fdt);
+		if ((tmp + newsize) > (buf + bufsize))
+			return -FDT_ERR_NOSPACE;
+	}
+
+	_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+	memmove(buf, tmp, newsize);
+
+	fdt_set_magic(buf, FDT_MAGIC);
+	fdt_set_totalsize(buf, bufsize);
+	fdt_set_version(buf, 17);
+	fdt_set_last_comp_version(buf, 16);
+	fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+	return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+	int mem_rsv_size;
+	int err;
+
+	err = rw_check_header(fdt);
+	if (err)
+		return err;
+
+	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+		* sizeof(struct fdt_reserve_entry);
+	_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+	fdt_set_totalsize(fdt, _blob_data_size(fdt));
+
+	return 0;
+}
diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt_strerror.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct errtabent {
+	const char *str;
+};
+
+#define ERRTABENT(val) \
+	[(val)] = { .str = #val, }
+
+static struct errtabent errtable[] = {
+	ERRTABENT(FDT_ERR_NOTFOUND),
+	ERRTABENT(FDT_ERR_EXISTS),
+	ERRTABENT(FDT_ERR_NOSPACE),
+
+	ERRTABENT(FDT_ERR_BADOFFSET),
+	ERRTABENT(FDT_ERR_BADPATH),
+	ERRTABENT(FDT_ERR_BADSTATE),
+
+	ERRTABENT(FDT_ERR_TRUNCATED),
+	ERRTABENT(FDT_ERR_BADMAGIC),
+	ERRTABENT(FDT_ERR_BADVERSION),
+	ERRTABENT(FDT_ERR_BADSTRUCTURE),
+	ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define ERRTABSIZE	(sizeof(errtable) / sizeof(errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+	if (errval > 0)
+		return "<valid offset/length>";
+	else if (errval == 0)
+		return "<no error>";
+	else if (errval > -ERRTABSIZE) {
+		const char *s = errtable[-errval].str;
+
+		if (s)
+			return s;
+	}
+
+	return "<unknown error>";
+}
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt_sw.c
@@ -0,0 +1,258 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int check_header_sw(void *fdt)
+{
+	if (fdt_magic(fdt) != SW_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	return 0;
+}
+
+static void *grab_space(void *fdt, int len)
+{
+	int offset = fdt_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_set_size_dt_struct(fdt, offset + len);
+	return fdt_offset_ptr_w(fdt, offset, len);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+	void *fdt = buf;
+
+	if (bufsize < sizeof(struct fdt_header))
+		return -FDT_ERR_NOSPACE;
+
+	memset(buf, 0, bufsize);
+
+	fdt_set_magic(fdt, SW_MAGIC);
+	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_totalsize(fdt,  bufsize);
+
+	fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header),
+					  sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+	fdt_set_off_dt_strings(fdt, bufsize);
+
+	return 0;
+}
+
+int fdt_add_reservemap_entry(void *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 (fdt_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 *)(fdt + offset);
+	re->address = cpu_to_fdt64(addr);
+	re->size = cpu_to_fdt64(size);
+
+	fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+	return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+	return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *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(void *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(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	const char *p;
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+	int struct_top, offset;
+
+	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	/* Add it */
+	offset = -strtabsize - len;
+	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	if (fdt_totalsize(fdt) + offset < struct_top)
+		return 0; /* no more room :( */
+
+	memcpy(strtab + offset, s, len);
+	fdt_set_size_dt_strings(fdt, strtabsize + len);
+	return offset;
+}
+
+int fdt_property(void *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(void *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) + fdt_size_dt_struct(fdt);
+	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+	fdt_set_off_dt_strings(fdt, 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_w(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_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+	fdt_set_magic(fdt, FDT_MAGIC);
+	return 0;
+}
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
new file mode 100644
--- /dev/null
+++ b/libfdt/fdt_wip.c
@@ -0,0 +1,144 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len)
+{
+	void *propval;
+	int proplen;
+
+	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+	if (! propval)
+		return proplen;
+
+	if (proplen != len)
+		return -FDT_ERR_NOSPACE;
+
+	memcpy(propval, val, len);
+	return 0;
+}
+
+static void nop_region(void *start, int len)
+{
+	uint32_t *p;
+
+	for (p = start; (void *)p < (start + len); p++)
+		*p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len;
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	nop_region(prop, len + sizeof(*prop));
+
+	return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int nodeoffset)
+{
+	int level = 0;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_END:
+			return offset;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (level >= 0);
+
+	return nextoffset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset);
+	return 0;
+}
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
new file mode 100644
--- /dev/null
+++ b/libfdt/libfdt.h
@@ -0,0 +1,1076 @@
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt_env.h>
+#include <fdt.h>
+
+#define FDT_FIRST_SUPPORTED_VERSION	0x10
+#define FDT_LAST_SUPPORTED_VERSION	0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND	1
+	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
+#define FDT_ERR_EXISTS		2
+	/* FDT_ERR_EXISTS: Attemped to create a node or property which
+	 * already exists */
+#define FDT_ERR_NOSPACE		3
+	/* FDT_ERR_NOSPACE: Operation needed to expand the device
+	 * tree, but its buffer did not have sufficient space to
+	 * contain the expanded tree. Use fdt_open_into() to move the
+	 * device tree to a buffer with more space. */
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET	4
+	/* FDT_ERR_BADOFFSET: Function was passed a structure block
+	 * offset which is out-of-bounds, or which points to an
+	 * unsuitable part of the structure for the operation. */
+#define FDT_ERR_BADPATH		5
+	/* FDT_ERR_BADPATH: Function was passed a badly formatted path
+	 * (e.g. missing a leading / for a function which requires an
+	 * absolute path) */
+#define FDT_ERR_BADPHANDLE	6
+	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
+	 * value.  phandle values of 0 and -1 are not permitted. */
+#define FDT_ERR_BADSTATE	7
+	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
+	 * tree created by the sequential-write functions, which is
+	 * not sufficiently complete for the requested operation. */
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED	8
+	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
+	 * ends without an FDT_END tag. */
+#define FDT_ERR_BADMAGIC	9
+	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
+	 * device tree at all - it is missing the flattened device
+	 * tree magic number. */
+#define FDT_ERR_BADVERSION	10
+	/* FDT_ERR_BADVERSION: Given device tree has a version which
+	 * can't be handled by the requested operation.  For
+	 * read-write functions, this may mean that fdt_open_into() is
+	 * required to convert the tree to the expected version. */
+#define FDT_ERR_BADSTRUCTURE	11
+	/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
+	 * structure block or other serious error (e.g. misnested
+	 * nodes, or subnodes preceding properties). */
+#define FDT_ERR_BADLAYOUT	12
+	/* FDT_ERR_BADLAYOUT: For read-write functions, the given
+	 * device tree has it's sub-blocks in an order that the
+	 * function can't handle (memory reserve map, then structure,
+	 * then strings).  Use fdt_open_into() to reorganize the tree
+	 * into a form suitable for the read-write operations. */
+
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL	13
+	/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
+	 * Should never be returned, if it is, it indicates a bug in
+	 * libfdt itself. */
+
+#define FDT_ERR_MAX		13
+
+/**********************************************************************/
+/* Low-level functions (you probably don't need these)                */
+/**********************************************************************/
+
+const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
+{
+	return (void *)fdt_offset_ptr(fdt, offset, checklen);
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+
+/**********************************************************************/
+/* Traversal functions                                                */
+/**********************************************************************/
+
+int fdt_next_node(const void *fdt, int offset, int *depth);
+
+/**********************************************************************/
+/* General functions                                                  */
+/**********************************************************************/
+
+#define fdt_get_header(fdt, field) \
+	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt) 			(fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt)		(fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt) 	(fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) 	(fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) 	(fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
+
+#define __fdt_set_hdr(name) \
+	static inline void fdt_set_##name(void *fdt, uint32_t val) \
+	{ \
+		struct fdt_header *fdth = fdt; \
+		fdth->name = cpu_to_fdt32(val); \
+	}
+__fdt_set_hdr(magic);
+__fdt_set_hdr(totalsize);
+__fdt_set_hdr(off_dt_struct);
+__fdt_set_hdr(off_dt_strings);
+__fdt_set_hdr(off_mem_rsvmap);
+__fdt_set_hdr(version);
+__fdt_set_hdr(last_comp_version);
+__fdt_set_hdr(boot_cpuid_phys);
+__fdt_set_hdr(size_dt_strings);
+__fdt_set_hdr(size_dt_struct);
+#undef __fdt_set_hdr
+
+/**
+ * fdt_check_header - sanity check a device tree or possible device tree
+ * @fdt: pointer to data which might be a flattened device tree
+ *
+ * fdt_check_header() checks that the given buffer contains what
+ * appears to be a flattened device tree with sane information in its
+ * header.
+ *
+ * returns:
+ *     0, if the buffer appears to contain a valid device tree
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings, as above
+ */
+int fdt_check_header(const void *fdt);
+
+/**
+ * fdt_move - move a device tree around in memory
+ * @fdt: pointer to the device tree to move
+ * @buf: pointer to memory where the device is to be moved
+ * @bufsize: size of the memory space at buf
+ *
+ * fdt_move() relocates, if possible, the device tree blob located at
+ * fdt to the buffer at buf of size bufsize.  The buffer may overlap
+ * with the existing device tree blob at fdt.  Therefore,
+ *     fdt_move(fdt, fdt, fdt_totalsize(fdt))
+ * should always succeed.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/**********************************************************************/
+/* Read-only functions                                                */
+/**********************************************************************/
+
+/**
+ * fdt_string - retreive a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ *
+ * fdt_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds
+ */
+const char *fdt_string(const void *fdt, int stroffset);
+
+/**
+ * fdt_num_mem_rsv - retreive the number of memory reserve map entries
+ * @fdt: pointer to the device tree blob
+ *
+ * Returns the number of entries in the device tree blob's memory
+ * reservation map.  This does not include the terminating 0,0 entry
+ * or any other (0,0) entries reserved for expansion.
+ *
+ * returns:
+ *     the number of entries
+ */
+int fdt_num_mem_rsv(const void *fdt);
+
+/**
+ * fdt_get_mem_rsv - retreive one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: pointers to 64-bit variables
+ *
+ * On success, *address and *size will contain the address and size of
+ * the n-th reserve map entry from the device tree blob, in
+ * native-endian format.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
+
+/**
+ * fdt_subnode_offset_namelen - find a subnode based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_subnode_offset(), but only examine the first
+ * namelen characters of name for matching the subnode name.  This is
+ * useful for finding subnodes based on a portion of a larger string,
+ * such as a full path.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+			       const char *name, int namelen);
+/**
+ * fdt_subnode_offset - find a subnode of a given node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node at structure block
+ * offset parentoffset with the given name.  name may include a unit
+ * address, in which case fdt_subnode_offset() will find the subnode
+ * with that unit address, or the unit address may be omitted, in
+ * which case fdt_subnode_offset() will find an arbitrary subnode
+ * whose name excluding unit address matches the given name.
+ *
+ * returns:
+ *	structure block offset of the requested subnode (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_path_offset - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ *
+ * fdt_path_offset() finds a node of a given path in the device tree.
+ * Each path component may omit the unit address portion, but the
+ * results of this are undefined if any such path component is
+ * ambiguous (that is if there are multiple nodes at the relevant
+ * level matching the given component, differentiated only by unit
+ * address).
+ *
+ * returns:
+ *	structure block offset of the node with the requested path (>=0), on success
+ *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ *	-FDT_ERR_NOTFOUND, if the requested node does not exist
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_path_offset(const void *fdt, const char *path);
+
+/**
+ * fdt_get_name - retreive the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the starting node
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_name() retrieves the name (including unit address) of the
+ * device tree node at structure block offset nodeoffset.  If lenp is
+ * non-NULL, the length of this name is also returned, in the integer
+ * pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the node's name, on success
+ *		If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE, standard meanings
+ */
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
+
+/**
+ * fdt_get_property - find a given property in a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property() retrieves a pointer to the fdt_property
+ * structure within the device tree blob corresponding to the property
+ * named 'name' of the node at offset nodeoffset.  If lenp is
+ * non-NULL, the length of the property value also returned, in the
+ * integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the structure representing the property
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_NOTFOUND, node does not have named property
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+					    const char *name, int *lenp);
+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
+						      const char *name,
+						      int *lenp)
+{
+	return (struct fdt_property *)fdt_get_property(fdt, nodeoffset,
+						       name, lenp);
+}
+
+/**
+ * fdt_getprop - retrieve the value of a given property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the property's value
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_NOTFOUND, node does not have named property
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+			const char *name, int *lenp);
+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
+				  const char *name, int *lenp)
+{
+	return (void *)fdt_getprop(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_get_phandle - retreive the phandle of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the node
+ *
+ * fdt_get_phandle() retrieves the phandle of the device tree node at
+ * structure block offset nodeoffset.
+ *
+ * returns:
+ *	the phandle of the node at nodeoffset, on succes (!= 0, != -1)
+ *	0, if the node has no phandle, or another error occurs
+ */
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_get_path - determine the full path of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose path to find
+ * @buf: character buffer to contain the returned path (will be overwritten)
+ * @buflen: size of the character buffer at buf
+ *
+ * fdt_get_path() computes the full path of the node at offset
+ * nodeoffset, and records that path in the buffer at buf.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ *	0, on success
+ *		buf contains the absolute path of the node at
+ *		nodeoffset, as a NUL-terminated string.
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
+ *		characters and will not fit in the given buffer.
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
+/**
+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ * @supernodedepth: depth of the ancestor to find
+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
+ * at a specific depth from the root (where the root itself has depth
+ * 0, its immediate subnodes depth 1 and so forth).  So
+ *	fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
+ * will always return 0, the offset of the root node.  If the node at
+ * nodeoffset has depth D, then:
+ *	fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
+ * will return nodeoffset itself.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+
+ *	structure block offset of the node at node offset's ancestor
+ *		of depth supernodedepth (>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+*	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth);
+
+/**
+ * fdt_node_depth - find the depth of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_node_depth() finds the depth of a given node.  The root node
+ * has depth 0, its immediate subnodes depth 1 and so forth.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ *	depth of the node at nodeoffset (>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_depth(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_parent_offset - find the parent of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_parent_offset() locates the parent node of a given node (that
+ * is, it finds the offset of the node which contains the node at
+ * nodeoffset as a subnode).
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset, *twice*.
+ *
+ * returns:
+ *	stucture block offset of the parent of the node at nodeoffset
+ *		(>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ *	offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ *					       propval, proplen);
+ *	while (offset != -FDT_ERR_NOTFOUND) {
+ *		// other code here
+ *		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ *						       propval, proplen);
+ *	}
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0, >startoffset),
+ *		 on success
+ *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ *		tree after startoffset
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+				  const char *propname,
+				  const void *propval, int proplen);
+
+/**
+ * fdt_node_offset_by_phandle - find the node with a given phandle
+ * @fdt: pointer to the device tree blob
+ * @phandle: phandle value
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the node
+ * which has the given phandle value.  If there is more than one node
+ * in the tree with the given phandle (an invalid tree), results are
+ * undefined.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0), on success
+ *	-FDT_ERR_NOTFOUND, no node with that phandle exists
+ *	-FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
+
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ *	0, if the node has a 'compatible' property listing the given string
+ *	1, if the node has a 'compatible' property, but it does not list
+ *		the given string
+ *	-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * 	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+			      const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ *	offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ *	while (offset != -FDT_ERR_NOTFOUND) {
+ *		// other code here
+ *		offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ *	}
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0, >startoffset),
+ *		 on success
+ *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ *		tree after startoffset
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+				  const char *compatible);
+
+/**********************************************************************/
+/* Write-in-place functions                                           */
+/**********************************************************************/
+
+/**
+ * fdt_setprop_inplace - change a property's value, but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * fdt_setprop_inplace() replaces the value of a given property with
+ * the data in val, of length len.  This function cannot change the
+ * size of a property, and so will only work if len is equal to the
+ * current length of the property.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if len is not equal to the property's current length
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len);
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: cell (32-bit integer) value to replace the property with
+ *
+ * fdt_setprop_inplace_cell() replaces the value of a given property
+ * with the 32-bit integer cell value in val, converting val to
+ * big-endian if necessary.  This function cannot change the size of a
+ * property, and so will only work if the property already exists and
+ * has length 4.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
+  *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+					   const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_nop_property - replace a property with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_nop_property() will replace a given property's representation
+ * in the blob with FDT_NOP tags, effectively removing it from the
+ * tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the property, and will not alter or move any other part of the
+ * tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_nop_node - replace a node (subtree) with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_nop_node() will replace a given node's representation in the
+ * blob, including all its subnodes, if any, with FDT_NOP tags,
+ * effectively removing it from the tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the node and its properties and subnodes, and will not alter or
+ * move any other part of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Sequential write functions                                         */
+/**********************************************************************/
+
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_property(fdt, name, &val, sizeof(val));
+}
+#define fdt_property_string(fdt, name, str) \
+	fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/**********************************************************************/
+/* Read-write functions                                               */
+/**********************************************************************/
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+/**
+ * fdt_add_mem_rsv - add one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @addres, @size: 64-bit values (native endian)
+ *
+ * Adds a reserve map entry to the given blob reserving a region at
+ * address address of length size.
+ *
+ * This function will insert data into the reserve map and will
+ * therfore change the indexes of some entries in the table.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new reservation entry
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
+
+/**
+ * fdt_del_mem_rsv - remove a memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @n: entry to remove
+ *
+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
+ * the blob.
+ *
+ * This function will delete data from the reservation table and will
+ * therfore change the indexes of some entries in the table.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
+ *		are less than n+1 reserve map entries)
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_mem_rsv(void *fdt, int n);
+
+/**
+ * fdt_set_name - change the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ * @name: name to give the node
+ *
+ * fdt_set_name() replaces the name (including unit address, if any)
+ * of the given node with the given string.  NOTE: this function can't
+ * efficiently check if the new name is unique amongst the given
+ * node's siblings; results are undefined if this function is invoked
+ * with a name equal to one of the given node's siblings.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob
+ *		to contain the new name
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_setprop - create or change a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_setprop() sets the value of the named property in the given
+ * node to the given value and length, creeating the property if it
+ * does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len);
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_cell() sets the value of the named property in the
+ * given node to the given cell value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+				   uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_string - set a property to a string value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value for the property
+ *
+ * fdt_setprop_string() sets the value of the named property in the
+ * given node to the given string value (using the length of the
+ * string to determine the new length of the property), or creates a
+ * new property with that value if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_delprop - delete a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_del_property() will delete the given property.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_add_subnode_namelen - creates a new node based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_add_subnode(), but use only the first namelen
+ * characters of name as the name of the new node.  This is useful for
+ * creating subnodes based on a portion of a larger string, such as a
+ * full path.
+ */
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen);
+
+/**
+ * fdt_add_subnode - creates a new node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_add_subnode() creates a new node as a subnode of the node at
+ * structure block offset parentoffset, with the given name (which
+ * should include the unit address, if any).
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+
+ * returns:
+ *	structure block offset of the created nodeequested subnode (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *	-FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ *		the given name
+ *	-FDT_ERR_NOSPACE, if there is insufficient free space in the
+ *		blob to contain the new node
+ *	-FDT_ERR_NOSPACE
+ *	-FDT_ERR_BADLAYOUT
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_del_node - delete a node (subtree)
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_del_node() will remove the given node, including all its
+ * subnodes if any, from the blob.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Debugging / informational functions                                */
+/**********************************************************************/
+
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
new file mode 100644
--- /dev/null
+++ b/libfdt/libfdt_env.h
@@ -0,0 +1,22 @@
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define fdt32_to_cpu(x)		(x)
+#define cpu_to_fdt32(x)		(x)
+#define fdt64_to_cpu(x)		(x)
+#define cpu_to_fdt64(x)		(x)
+#else
+#define fdt32_to_cpu(x)		(bswap_32((x)))
+#define cpu_to_fdt32(x)		(bswap_32((x)))
+#define fdt64_to_cpu(x)		(bswap_64((x)))
+#define cpu_to_fdt64(x)		(bswap_64((x)))
+#endif
+
+#endif /* _LIBFDT_ENV_H */
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
new file mode 100644
--- /dev/null
+++ b/libfdt/libfdt_internal.h
@@ -0,0 +1,96 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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; either version 2 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 General Public License for more details.
+ *
+ *     You should have received a copy of the GNU 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
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <fdt.h>
+
+#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
+#define PALIGN(p, a)	((void *)ALIGN((unsigned long)(p), (a)))
+
+#define memeq(p, q, n)	(memcmp((p), (q), (n)) == 0)
+#define streq(p, q)	(strcmp((p), (q)) == 0)
+
+#define CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+	return fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+	return (void *)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+	const struct fdt_reserve_entry *rsv_table =
+		fdt + fdt_off_mem_rsvmap(fdt);
+
+	return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+	return (void *)_fdt_mem_rsv(fdt, n);
+}
+
+#define SW_MAGIC		(~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2 of 7] Add libfdt support to qemu
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
  2008-03-12  4:50 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-12  4:50 ` [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu Jerone Young
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 36d2646a3c3d42021425febf3d14f0500ebbaace
# Parent  cb3ca3805e7735fffcf42032b917cc761b145fb3
Add libfdt support to qemu

This patch adds needed configuration options to compile in libfdt support
into qemu.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -555,6 +555,11 @@ ifdef CONFIG_VNC_TLS
 ifdef CONFIG_VNC_TLS
 CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
 LIBS += $(CONFIG_VNC_TLS_LIBS)
+endif
+
+ifdef CONFIG_LIBFDT
+LIBS += -lfdt
+DEPLIBS += libfdt.a
 endif
 
 # SCSI layer
diff --git a/qemu/configure b/qemu/configure
--- a/qemu/configure
+++ b/qemu/configure
@@ -112,6 +112,7 @@ uname_release=""
 uname_release=""
 curses="yes"
 cpu_emulation="yes"
+device_tree_support="no"
 
 # OS specific
 targetos=`uname -s`
@@ -345,6 +346,8 @@ for opt do
   ;;
   --disable-cpu-emulation) cpu_emulation="no"
   ;;
+  --enable-libfdt) device_tree_support="yes"
+  ;;
   *) echo "ERROR: unknown option $opt"; exit 1
   ;;
   esac
@@ -449,6 +452,7 @@ echo "  --enable-uname-release=R Return 
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
 echo "  --sparc_cpu=V            Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
 echo "  --disable-cpu-emulation  disables use of qemu cpu emulation code"
+echo "  --enable-libfdt 	 enable libfdt support for device tree support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -1186,6 +1190,10 @@ elif test "$target_cpu" = "ppcemb" ; the
   echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
   echo "#define TARGET_PPC 1" >> $config_h
   echo "#define TARGET_PPCEMB 1" >> $config_h
+  if test "$device_tree_support" = "yes" ; then
+      echo "#define CONFIG_LIBFDT 1" >> $config_h
+      echo "CONFIG_LIBFDT=1" >> $config_mak
+  fi
   configure_kvm
 elif test "$target_cpu" = "ppc64" ; then
   echo "TARGET_ARCH=ppc64" >> $config_mak

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
  2008-03-12  4:50 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
  2008-03-12  4:50 ` [PATCH 2 of 7] Add libfdt support to qemu Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-13  2:36   ` [kvm-ppc-devel] " Hollis Blanchard
  2008-03-12  4:50 ` [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu Jerone Young
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 48651677b7d05254d6acf03551bfea05cef8aa47
# Parent  36d2646a3c3d42021425febf3d14f0500ebbaace
Create new load_uboot() & gunzip support to uboot loader in Qemu

This patch adds the ability for the load address to be caputred when loading a uImage or cuImage. It also adds a better return code as the size can be an usigned long. This is done by creating a new function prototype and calling it load_uboot_l . To keep compatibility with code already using the old load_uboot a wrapper function has been created so current callers will not break them.

Also added is gunzip support to allow for loading of uimages with a compressed kenrel imagexs.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/loader.c b/qemu/loader.c
--- a/qemu/loader.c
+++ b/qemu/loader.c
@@ -26,6 +26,8 @@
 #include "sysemu.h"
 #include "uboot_image.h"
 
+#include <zlib.h>
+
 /* return the size or -1 if error */
 int get_image_size(const char *filename)
 {
@@ -263,14 +265,103 @@ static void bswap_uboot_header(uboot_ima
 }
 
 /* Load a U-Boot image.  */
-int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
-{
-
+
+/* gunzip functionality is derived from gunzip function 
+ * in uboot source code 
+ */
+
+#define	ZALLOC_ALIGNMENT	16
+
+static void *zalloc(void *x, unsigned items, unsigned size)
+{
+	void *p;
+
+	size *= items;
+	size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+	p = malloc (size);
+
+	return (p);
+}
+
+static void zfree(void *x, void *addr, unsigned nb)
+{
+	free (addr);
+}
+
+
+#define HEAD_CRC	2
+#define EXTRA_FIELD	4
+#define ORIG_NAME	8
+#define COMMENT		0x10
+#define RESERVED	0xe0
+
+#define DEFLATED	8
+
+static int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
+{
+	z_stream s;
+	int r, i, flags;
+
+	/* skip header */
+	i = 10;
+	flags = src[3];
+	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+		puts ("Error: Bad gzipped data\n");
+		return -1;
+	}
+	if ((flags & EXTRA_FIELD) != 0)
+		i = 12 + src[10] + (src[11] << 8);
+	if ((flags & ORIG_NAME) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & COMMENT) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & HEAD_CRC) != 0)
+		i += 2;
+	if (i >= *lenp) {
+		puts ("Error: gunzip out of data in header\n");
+		return -1;
+	}
+
+	s.zalloc = zalloc;
+	s.zfree = zfree;
+
+	r = inflateInit2(&s, -MAX_WBITS);
+	if (r != Z_OK) {
+		printf ("Error: inflateInit2() returned %d\n", r);
+		return (-1);
+	}
+	s.next_in = src + i;
+	s.avail_in = *lenp - i;
+	s.next_out = dst;
+	s.avail_out = dstlen;
+	r = inflate(&s, Z_FINISH);
+	if (r != Z_OK && r != Z_STREAM_END) {
+		printf ("Error: inflate() returned %d\n", r);
+		return -1;
+	}
+	*lenp = s.next_out - (unsigned char *) dst;
+	inflateEnd(&s);
+
+	return 0;
+}
+
+
+#define MAX_KERNEL_SIZE 8*1024*1024  //8MB
+int load_uboot_l(const char *filename, target_ulong *ep,
+                  target_ulong *la, 
+                  target_ulong *loaded_image_size,
+                  int *is_linux)
+{
     int fd;
     int size;
+    int ret;
     uboot_image_header_t h;
     uboot_image_header_t *hdr = &h;
     uint8_t *data = NULL;
+    uint8_t *uncompressed_data = NULL;
 
     fd = open(filename, O_RDONLY | O_BINARY);
     if (fd < 0)
@@ -291,13 +382,14 @@ int load_uboot(const char *filename, tar
         goto fail;
     }
 
-    /* TODO: Implement compressed images.  */
-    if (hdr->ih_comp != IH_COMP_NONE) {
-        fprintf(stderr, "Unable to load compressed u-boot images\n");
+    /* TODO bzip2 support */
+    if (hdr->ih_comp == IH_COMP_BZIP2) {
+        fprintf(stderr, "Unable to load bzip2 compressed u-boot images\n");
         goto fail;
     }
 
     /* TODO: Check CPU type.  */
+
     if (is_linux) {
         if (hdr->ih_type == IH_TYPE_KERNEL && hdr->ih_os == IH_OS_LINUX)
             *is_linux = 1;
@@ -306,6 +398,8 @@ int load_uboot(const char *filename, tar
     }
 
     *ep = hdr->ih_ep;
+    *la = hdr->ih_load;
+
     data = qemu_malloc(hdr->ih_size);
     if (!data)
         goto fail;
@@ -315,9 +409,29 @@ int load_uboot(const char *filename, tar
         goto fail;
     }
 
-    cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
-
-    return hdr->ih_size;
+    *loaded_image_size = hdr->ih_size;
+    
+    if (hdr->ih_comp == IH_COMP_GZIP) {
+	uncompressed_data = qemu_malloc(MAX_KERNEL_SIZE);
+	ret = gunzip(uncompressed_data, MAX_KERNEL_SIZE,
+                    (unsigned char *) data, 
+                    loaded_image_size);
+
+	if (ret < 0) {
+            fprintf(stderr, "Unable to decompress gziped image!\n");
+            goto fail;
+        }
+
+        qemu_free(data);
+        cpu_physical_memory_write_rom(hdr->ih_load, uncompressed_data,
+                                      *loaded_image_size);
+
+    }
+    else {
+        cpu_physical_memory_write_rom(hdr->ih_load, data, *loaded_image_size);
+    }
+
+    return 0;
 
 fail:
     if (data)
@@ -325,3 +439,18 @@ fail:
     close(fd);
     return -1;
 }
+
+
+int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
+{
+    target_ulong la;
+    target_ulong size;
+    int ret;
+
+    ret = load_uboot_l(filename, ep, &la, &size, is_linux);
+
+    if (ret < 0)
+	return ret;
+    else
+	return (int)size;
+}
diff --git a/qemu/sysemu.h b/qemu/sysemu.h
--- a/qemu/sysemu.h
+++ b/qemu/sysemu.h
@@ -182,6 +182,9 @@ int load_elf(const char *filename, int64
              uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr);
 int load_aout(const char *filename, uint8_t *addr);
 int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
+int load_uboot_l(const char *filename, target_ulong *ep, 
+             target_ulong *la, target_ulong *loaded_image_size,
+             int *is_linux);
 #endif
 
 #ifdef HAS_AUDIO

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
                   ` (2 preceding siblings ...)
  2008-03-12  4:50 ` [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-13  2:42   ` [kvm-ppc-devel] " Hollis Blanchard
  2008-03-12  4:50 ` [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model Jerone Young
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 9c15709640cd55bf6f782d6856423363312493bb
# Parent  48651677b7d05254d6acf03551bfea05cef8aa47
Add PPC 440EP bamboo board device tree source & binary into qemu

This patch places the bamboo device tree for the PPC 440EP bamboo board into the pc-bios directory of the qemu source. This also adds a rule into the pc-bios/Makefile to build device tree files.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/pc-bios/Makefile b/qemu/pc-bios/Makefile
--- a/qemu/pc-bios/Makefile
+++ b/qemu/pc-bios/Makefile
@@ -12,6 +12,9 @@ all: $(TARGETS)
 %.o: %.S
 	$(CC) $(DEFINES) -c -o $@ $<
 
+%.dtb: %.dts 
+	dtc -O dtb -I dts -o $@ $< 
+
 clean:
-	rm -f $(TARGETS) *.o *~
+	rm -f $(TARGETS) *.o *~ *.dtb
 
diff --git a/qemu/pc-bios/bamboo.dts b/qemu/pc-bios/bamboo.dts
new file mode 100644
--- /dev/null
+++ b/qemu/pc-bios/bamboo.dts
@@ -0,0 +1,310 @@
+/*
+ * Device Tree Source for AMCC Bamboo
+ *
+ * Copyright (c) 2006, 2007 IBM Corp.
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ *
+ * FIXME: Draft only!
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ */
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,bamboo";
+	compatible = "amcc,bamboo";
+	dcr-parent = <&/cpus/cpu@0>;
+
+	aliases {
+/*		ethernet0 = &EMAC0;  */
+/*		ethernet1 = &EMAC1;  *
+		serial0 = &UART0;
+ 		serial1 = &UART1;   
+/*		serial2 = &UART2;    */
+/*		serial3 = &UART3;    */
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,440EP";
+			reg = <0>;
+			clock-frequency = <1fca0550>; /* Filled in by zImage */
+			timebase-frequency = <017d7840>; /* Filled in by zImage */
+			i-cache-line-size = <20>;
+			d-cache-line-size = <20>;
+			i-cache-size = <8000>;
+			d-cache-size = <8000>;
+			dcr-controller;
+			dcr-access-method = "native";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 9000000>; /* Filled in by zImage */
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-440ep","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0c0 009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+/*
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-440ep","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0d0 009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <1e 4 1f 4>; 
+		interrupt-parent = <&UIC0>;
+	};
+*/
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-440ep";
+		dcr-reg = <00e 002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-440ep";
+		dcr-reg = <00c 002>;
+	};
+
+	plb {
+		compatible = "ibm,plb-440ep", "ibm,plb-440gp", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <07f28154>; /* Filled in by zImage */
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-440ep", "ibm,sdram-405gp";
+			dcr-reg = <010 2>;
+		};
+
+		DMA0: dma {
+			compatible = "ibm,dma-440ep", "ibm,dma-440gp";
+			dcr-reg = <100 027>;
+		};
+
+/*
+		MAL0: mcmal {
+			compatible = "ibm,mcmal-440ep", "ibm,mcmal-440gp", "ibm,mcmal";
+			dcr-reg = <180 62>;
+			num-tx-chans = <4>;
+			num-rx-chans = <2>;
+			interrupt-parent = <&MAL0>;
+			interrupts = <0 1 2 3 4>;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0 &UIC0 a 4
+					  1 &UIC0 b 4
+					  2 &UIC1 0 4
+					  3 &UIC1 1 4
+					  4 &UIC1 2 4>;
+		};
+*/
+		POB0: opb {
+		  	compatible = "ibm,opb-440ep", "ibm,opb-440gp", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/* Bamboo is oddball in the 44x world and doesn't use the ERPN
+			 * bits.
+			 */
+		  	ranges = <00000000 0 00000000 80000000
+			          80000000 0 80000000 80000000>;
+		  	/* interrupt-parent = <&UIC1>; */
+		  	interrupts = <7 4>;
+		  	clock-frequency = <0>; /* Filled in by zImage */
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-440ep", "ibm,ebc-440gp", "ibm,ebc";
+				dcr-reg = <012 2>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <>; /* Filled in by zImage */
+				interrupts = <5 1>;
+			/* interrupt-parent = <&UIC1>; */
+			};
+
+			UART0: serial@ef600300 {
+		   		device_type = "serial";
+		   		compatible = "ns16550";
+		   		reg = <ef600300 8>;
+		   		virtual-reg = <ef600300>;
+		   		clock-frequency = <00a8c000>; /* Filled in by zImage */
+		   		current-speed = <1c200>;
+		   		interrupt-parent = <&UIC0>;
+		   		interrupts = <0 4>;
+	   		};
+
+			UART1: serial@ef600400 {
+		   		device_type = "serial";
+		   		compatible = "ns16550";
+		   		reg = <ef600400 8>;
+		   		virtual-reg = <ef600400>;
+		   		clock-frequency = <00a8c000>;
+		   		current-speed = <0>;
+		   		interrupt-parent = <&UIC0>;
+		   		interrupts = <1 4>;
+	   		};
+/*
+			UART2: serial@ef600500 {
+		   		device_type = "serial";
+		   		compatible = "ns16550";
+		   		reg = <ef600500 8>;
+		   		virtual-reg = <ef600500>;
+		   		clock-frequency = <0>;
+		   		current-speed = <0>;
+		   		interrupt-parent = <&UIC0>;
+		   		interrupts = <3 4>;
+	   		};
+
+			UART3: serial@ef600600 {
+		   		device_type = "serial";
+		   		compatible = "ns16550";
+		   		reg = <ef600600 8>;
+		   		virtual-reg = <ef600600>;
+		   		clock-frequency = <0>;
+		   		current-speed = <0>;
+		   		interrupt-parent = <&UIC0>;
+		   		interrupts = <4 4>;
+	   		};
+
+*/
+			IIC0: i2c@ef600700 {
+				device_type = "i2c";
+				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
+				reg = <ef600700 14>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <2 4>;
+			};
+
+			IIC1: i2c@ef600800 {
+				device_type = "i2c";
+				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
+				reg = <ef600800 14>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <7 4>;
+			};
+
+			ZMII0: emac-zmii@ef600d00 {
+				device_type = "zmii-interface";
+				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
+				reg = <ef600d00 c>;
+			};
+
+/*
+			EMAC0: ethernet@ef600e00 {
+				linux,network-index = <0>;
+				device_type = "network";
+				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+				interrupt-parent = <&UIC1>;
+				interrupts = <1c 4 1d 4>;
+				reg = <ef600e00 70>;
+				local-mac-address = [000000000000];
+				mal-device = <&MAL0>;
+				mal-tx-channel = <0 1>;
+				mal-rx-channel = <0>;
+				cell-index = <0>;
+				max-frame-size = <5dc>;
+				rx-fifo-size = <1000>;
+				tx-fifo-size = <800>;
+				phy-mode = "rmii";
+				phy-map = <00000000>;
+				zmii-device = <&ZMII0>;
+				zmii-channel = <0>;
+			};
+
+			EMAC1: ethernet@ef600f00 {
+				linux,network-index = <1>;
+				device_type = "network";
+				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+				interrupt-parent = <&UIC1>;
+				interrupts = <1e 4 1f 4>;
+				reg = <ef600f00 70>;
+				local-mac-address = [000000000000];
+				mal-device = <&MAL0>;
+				mal-tx-channel = <2 3>;
+				mal-rx-channel = <1>;
+				cell-index = <1>;
+				max-frame-size = <5dc>;
+				rx-fifo-size = <1000>;
+				tx-fifo-size = <800>;
+				phy-mode = "rmii";
+				phy-map = <00000000>;
+				zmii-device = <&ZMII0>;
+				zmii-channel = <1>;
+			};
+
+			usb@ef601000 {
+				compatible = "ohci-be";
+				reg = <ef601000 80>;
+				interrupts = <8 1 9 1>;
+				interrupt-parent = < &UIC1 >;
+			};
+*/
+		};
+
+		PCI0: pci@ec000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
+			primary;
+			reg = <0 eec00000 8	/* Config space access */
+			       0 eed00000 4	/* IACK */
+			       0 eed00000 4	/* Special cycle */
+			       0 ef400000 40>;	/* Internal registers */
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed. Chip supports a second
+			 * IO range but we don't use it for now
+			 */
+			ranges = <02000000 0 a0000000 0 a0000000 0 20000000
+				  01000000 0 00000000 0 e8000000 0 00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <42000000 0 0 0 0 0 80000000>;
+
+			/* Bamboo has all 4 IRQ pins tied together per slot */
+			interrupt-map-mask = <f800 0 0 0>;
+			interrupt-map = <
+				/* IDSEL 1 */
+				0800 0 0 0 &UIC0 1c 8
+
+				/* IDSEL 2 */
+				1000 0 0 0 &UIC0 1b 8
+
+				/* IDSEL 3 */
+				1800 0 0 0 &UIC0 1a 8
+
+				/* IDSEL 4 */
+				2000 0 0 0 &UIC0 19 8
+			>;
+		};
+	};
+
+	chosen {
+		linux,stdout-path = "/plb/opb/serial@ef600300";
+		linux,initrd-start = <0>;
+		linux,initrd-end = <0>;
+		bootargs = "                ";
+	};
+};

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
                   ` (3 preceding siblings ...)
  2008-03-12  4:50 ` [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-13  2:53   ` [kvm-ppc-devel] " Hollis Blanchard
  2008-03-12  4:50 ` [PATCH 6 of 7] Modify PPC bamboo & ppc440 board models Jerone Young
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 50fddb23a4c19ec6f359a4dd39e98712eb6bcaeb
# Parent  9c15709640cd55bf6f782d6856423363312493bb
Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model

This patch adds code to dynamically manipulate the device tree when loaded into memory. This allows us to finally have the ability to manipulate the kernel command line & initrd from the qemu command line. This will also let us setup different settings for the board.

This patch also now uses new uboot loader uboot_loader_l() to load kernel image.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -615,7 +615,7 @@ OBJS+= unin_pci.o ppc_chrp.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
-OBJS+= ppc440.o ppc440_bamboo.o
+OBJS+= ppc440.o ppc440_bamboo.o ppc_device_tree_support.o
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
 OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
--- a/qemu/hw/ppc440_bamboo.c
+++ b/qemu/hw/ppc440_bamboo.c
@@ -8,11 +8,12 @@
  *
  */
 
+#include "config.h"
 #include "ppc440.h"
+#include "qemu-kvm.h"
+#include "ppc_device_tree_support.h"
 
-#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
-
-#include "qemu-kvm.h"
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
 
 /* PPC 440 refrence demo board
  *
@@ -26,14 +27,22 @@ void bamboo_init(ram_addr_t ram_size, in
 			const char *initrd_filename,
 			const char *cpu_model)
 {
+	char buf[1024];	
 	target_phys_addr_t ram_bases[2], ram_sizes[2];
 	qemu_irq *pic;
 	CPUState *env;
-	target_ulong ep;
+	target_ulong ep=0;
+	target_ulong la=0;
 	int is_linux=1; /* Will assume allways is Linux for now */
-	long kernel_size=0;
+	target_long kernel_size=0;
 	target_ulong initrd_base=0;
-	target_ulong initrd_size=0;
+	target_long initrd_size=0;
+	target_ulong dt_base=0;
+	void *fdt;
+	int ret;
+
+	uint32_t cpu_freq;
+	uint32_t timebase_freq;
 
 	printf("%s: START\n", __func__);
 
@@ -78,18 +87,23 @@ void bamboo_init(ram_addr_t ram_size, in
 
 	/* load kernel with uboot loader */
 	printf("%s: load kernel\n", __func__);
-	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
+	load_uboot_l(kernel_filename, &ep, &la, &kernel_size, &is_linux);
 	if (kernel_size < 0) {
 		fprintf(stderr, "qemu: could not load kernel '%s'\n",
 			kernel_filename);
 		exit(1);
 	}
+	printf("kernel is at guest address: 0x%lx\n", (unsigned long)la);
 
 	/* load initrd */
 	if (initrd_filename) {
-		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
+        	initrd_base = kernel_size + la;
+		printf("%s: load initrd\n", __func__);
 		initrd_size = load_image(initrd_filename,
 				phys_ram_base + initrd_base);
+
+		printf("initrd is at guest address: 0x%lx\n", 
+					(unsigned long) initrd_base);
 
 		if (initrd_size < 0) {
 			fprintf(stderr,
@@ -99,17 +113,58 @@ void bamboo_init(ram_addr_t ram_size, in
 		}
 	}
 
+#ifdef CONFIG_LIBFDT
+	/* get variable for device tree */
+	cpu_freq = get_proc_dt_prop_cpu_clock_freq();
+	timebase_freq = get_proc_dt_prop_cpu_timebase_freq();
+
+	/* load binary device tree into qemu (not guest memory) */
+	printf("%s: load device tree file\n", __func__);
+	
+	snprintf(buf, sizeof(buf), "%s/%s", bios_dir, 
+		BINARY_DEVICE_TREE_FILE);
+
+	/* set base for device tree that will be in guest memory */	
+	if (initrd_base)
+		dt_base = initrd_base + initrd_size;
+	else
+		dt_base = kernel_size + la;
+
+	fdt = load_device_tree(buf, (phys_ram_base + dt_base));
+	if (fdt == NULL) {
+		printf("Loading device tree failed!\n");
+		exit(1);
+	}
+
+	printf("device tree address is at guest address: 0x%lx\n", 
+		(unsigned long) dt_base);
+
+	/* manipulate device tree in memory */
+	set_dt_cpu_0_clock_freq_prop(fdt, cpu_freq);
+	set_dt_cpu_0_timebase_prop(fdt, timebase_freq);
+
+	set_dt_initrd_start_prop(fdt, initrd_base);
+	set_dt_initrd_end_prop(fdt, (initrd_base + initrd_size));
+
+	set_dt_bootargs_prop(fdt, kernel_cmdline);
+#endif
+
 	if (kvm_enabled()) {
-	    /* XXX insert TLB entries */
-	    env->gpr[1] = (16<<20) - 8;
-	    env->gpr[4] = initrd_base;
-	    env->gpr[5] = initrd_size;
 
-	    env->nip = ep;
+		/* XXX insert TLB entries */
+		env->gpr[1] = (16<<20) - 8;
 
-	    env->cpu_index = 0;
-	    printf("%s: loading kvm registers\n", __func__);
-	    kvm_load_registers(env);
+#ifdef CONFIG_LIBFDT
+		/* location of device tree in register */
+		env->gpr[3] = dt_base;
+#else
+		env->gpr[4] = initrd_base;
+		env->gpr[5] = initrd_size;
+#endif
+		env->nip = ep;
+
+		printf("%s: loading kvm registers\n", __func__);
+		kvm_load_registers(env);
 	}
 
 	printf("%s: DONE\n", __func__);
diff --git a/qemu/hw/ppc_device_tree_support.c b/qemu/hw/ppc_device_tree_support.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc_device_tree_support.c
@@ -0,0 +1,223 @@
+/*
+ * Functions to help device tree manipulation using libfdt.
+ * It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL licence version 2 or later.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "ppc440.h"
+
+#ifdef CONFIG_LIBFDT
+	#include "libfdt.h"
+#endif
+
+#define DT_PROC_INTERFACE_PATH "/proc/device-tree"
+
+/* FUNCTIONS FOR READING FROM DEVICE TREE OF HOST IN /PROC */
+
+/* This function reads device-tree property files that are of
+ * a single cell size
+ */
+static uint32_t read_proc_device_tree_prop_cell(char *path_in_device_tree)
+{
+	char buf[1024];
+	uint32_t num;
+	FILE *stream;
+
+	snprintf(buf, sizeof(buf), "%s/%s",  DT_PROC_INTERFACE_PATH,
+		path_in_device_tree);
+
+	stream = fopen(buf, "rb");
+	
+	if (stream == NULL)
+	{
+		printf("%s: Unable to open '%s'\n", __func__, buf);
+		exit(1);
+	}
+
+	fread(&num, sizeof(num), 1, stream);
+	fclose(stream);
+
+	return num;
+} 
+
+/* public functions */
+
+/* get cpu frequency in device tree */ 
+uint32_t get_proc_dt_prop_cpu_clock_freq()
+{
+	return read_proc_device_tree_prop_cell("cpus/cpu@0/clock-frequency");
+}
+
+/* get time base for cpu in device tree */
+uint32_t get_proc_dt_prop_cpu_timebase_freq()
+{
+	return read_proc_device_tree_prop_cell(
+				"cpus/cpu@0/timebase-frequency");
+}
+
+
+/* FUNCTIONS FOR LOADING & MANIPULATION OF DEVICE TREE IN GUEST */
+
+#ifdef CONFIG_LIBFDT
+/* support functions */
+static int get_offset_of_node(void *fdt, char *node_path)
+{
+	int node_offset;
+	node_offset = fdt_path_offset(fdt, node_path);
+	if (node_offset < 0) {
+		printf("Unable to find node in device tree '%s'\n", 
+			node_path);
+		exit(1);
+	}
+	return node_offset;
+}
+
+static void set_dt_prop_cell(void *fdt, int node_offset, char *prop_name,
+				uint32_t value)
+{
+	int ret;
+	ret = fdt_setprop_cell(fdt, node_offset, prop_name, value); 
+	if (ret < 0) {
+		printf("Unable to set device tree property '%s'\n",
+			prop_name);
+		exit(1);
+	}
+}
+
+static void set_dt_prop_string(void *fdt, int node_offset, char *prop_name,
+				char *string)
+{
+	int ret;
+	ret = fdt_setprop_string(fdt, node_offset, prop_name, string);
+	if (ret < 0) {
+		printf("Unable to set device tree property '%s'\n",
+			prop_name);
+		exit(1);
+	}
+}
+
+/* public functions */
+void *load_device_tree(char *filename_path, unsigned long load_addr)
+{
+	int dt_file_size;
+	int dt_file_load_size;
+	int new_dt_size;
+	int ret;
+	void *dt_file;
+	void *fdt;
+	
+	dt_file_size = get_image_size(filename_path);
+	if (dt_file_size < 0) {
+		printf("Unable to get size of device tree file");
+		goto fail;
+	}
+	
+	/* first allocate space in qemu for device tree */
+	dt_file = qemu_malloc(dt_file_size);
+	if (dt_file == NULL) {
+		printf("Unable to allocate memory in qemu for device tree\n");
+		goto fail;
+	}
+	memset(dt_file, 0, dt_file_size);
+
+	dt_file_load_size = load_image(filename_path, dt_file);
+
+
+	/* XXX Second we place new copy of 2x size in guest memory 
+ 	 *  This give us enough room for manipulation.
+	 */
+	new_dt_size = dt_file_size * 2;
+
+	fdt = (void *)load_addr;
+
+	ret = fdt_open_into(dt_file, fdt, new_dt_size);
+	if (ret) {
+		printf("Unable to copy device tree in memory\n");
+		goto fail;
+	}
+	
+	/* Check sanity of device tree */
+	if (fdt_check_header(fdt)) {
+		printf ("Device tree file loaded into memory is invalid: %s\n",
+			filename_path);
+		goto fail;
+	}
+	/* free qemu memory with old device tree */
+	qemu_free(dt_file);	
+	return fdt;
+
+fail:
+	if (dt_file) 
+		qemu_free(dt_file);
+	return NULL;
+}
+
+void dump_device_tree_to_file(void *fdt, char *filename)
+{
+	int fd;
+	fd = open(filename, O_RDWR|O_CREAT);
+	if (fd < 0) {
+		printf("Failed to open file %s\n Cannot dum device-tree\n", 
+			filename);
+		return;
+	}
+	
+	write(fd, fdt, fdt_totalsize(fdt));
+	close(fd);
+}
+
+void set_dt_cpu_0_clock_freq_prop(void *fdt, uint32_t freq)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/cpus/cpu@0");
+	set_dt_prop_cell(fdt, offset, "clock-frequency",
+			freq);
+}
+
+void set_dt_cpu_0_timebase_prop(void *fdt, uint32_t timebase)
+{	
+	int offset;
+	offset = get_offset_of_node(fdt, "/cpus/cpu@0");
+	set_dt_prop_cell(fdt, offset, "timebase-frequency",
+			timebase);
+
+}
+
+void set_dt_initrd_start_prop(void *fdt, uint32_t start_addr)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/chosen");
+	set_dt_prop_cell(fdt, offset, "linux,initrd-start",
+			start_addr);
+}
+
+void set_dt_initrd_end_prop(void *fdt, uint32_t end_addr)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/chosen");
+	set_dt_prop_cell(fdt, offset, "linux,initrd-end",
+			end_addr);
+}
+
+void set_dt_bootargs_prop(void *fdt, char *cmdline)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/chosen");
+	set_dt_prop_string(fdt,offset, "bootargs", cmdline);
+}
+
+#endif
diff --git a/qemu/hw/ppc_device_tree_support.h b/qemu/hw/ppc_device_tree_support.h
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc_device_tree_support.h
@@ -0,0 +1,26 @@
+/*
+ * Header with function prototypes to help device tree manipulation using 
+ * libfdt. It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL licence version 2 or later.
+ *
+ */
+
+/* device-tree proc support functions */
+uint32_t get_proc_dt_prop_cpu_clock_freq(void);
+uint32_t get_proc_dt_prop_cpu_timebase_freq(void);
+
+#ifdef CONFIG_LIBFDT
+/* device tree functions */ 
+void *load_device_tree(char *filename_path, target_ulong load_addr);
+void dump_device_tree_to_file(void *fdt, char *filename);
+void set_dt_cpu_0_clock_freq_prop(void *fdt, uint32_t freq);
+void set_dt_cpu_0_timebase_prop(void *fdt, uint32_t timebase);
+void set_dt_initrd_start_prop(void *fdt, uint32_t start_addr);
+void set_dt_initrd_end_prop(void *fdt, uint32_t end_addr);
+void set_dt_bootargs_prop(void *fdt, char *cmdline);
+#endif

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 6 of 7] Modify PPC bamboo & ppc440 board models
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
                   ` (4 preceding siblings ...)
  2008-03-12  4:50 ` [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-12  4:50 ` [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model Jerone Young
  2008-03-13  2:55 ` [kvm-ppc-devel] [PATCH 0 of 7] PowerPC kvm-userspace patches Hollis Blanchard
  7 siblings, 0 replies; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 3a891d8fada96166089b5796f3241087d4aae50f
# Parent  50fddb23a4c19ec6f359a4dd39e98712eb6bcaeb
Modify PPC bamboo & ppc440 board models

This patch renames pp440_init to ppc440ep_init, as ppc440 is the name of the core and ppc440ep is the name of the SOC. When we init we are initializing the SOC.

Also in this patch we now call cpu_ppc_init for bamboo with string 440 .. as 440 is the core.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/hw/ppc440.c b/qemu/hw/ppc440.c
--- a/qemu/hw/ppc440.c
+++ b/qemu/hw/ppc440.c
@@ -10,7 +10,7 @@
 
 #include "ppc440.h"
 
-void ppc440_init(CPUState *env,
+void ppc440ep_init(CPUState *env,
 		target_phys_addr_t ram_bases[2],
 		target_phys_addr_t ram_sizes[2],
 		qemu_irq **picp,
diff --git a/qemu/hw/ppc440.h b/qemu/hw/ppc440.h
--- a/qemu/hw/ppc440.h
+++ b/qemu/hw/ppc440.h
@@ -20,7 +20,7 @@
 #include "exec-all.h"
 #include "boards.h"
 
-void ppc440_init(CPUState *env,
+void ppc440ep_init(CPUState *env,
 		target_phys_addr_t ram_bases[2],
 		target_phys_addr_t ram_sizes[2],
 		qemu_irq **picp,
diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
--- a/qemu/hw/ppc440_bamboo.c
+++ b/qemu/hw/ppc440_bamboo.c
@@ -68,8 +68,7 @@ void bamboo_init(ram_addr_t ram_size, in
 	printf("Ram size of domain is %d bytes\n", (int)ram_size);
 
 	/* Setup CPU */
-	/* XXX We cheat for now and use 405 */
-	env = cpu_ppc_init("405");
+	env = cpu_ppc_init("440");
 	if (!env) {
 		fprintf(stderr, "Unable to initilize CPU!\n");
 		exit(1);
@@ -77,7 +76,7 @@ void bamboo_init(ram_addr_t ram_size, in
 
 	/* call init */
 	printf("Calling function ppc440_init\n");
-	ppc440_init(env, ram_bases, ram_sizes, &pic,1);
+	ppc440ep_init(env, ram_bases, ram_sizes, &pic,1);
 	printf("Done calling ppc440_init\n");
 
 	/* Register mem */

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
                   ` (5 preceding siblings ...)
  2008-03-12  4:50 ` [PATCH 6 of 7] Modify PPC bamboo & ppc440 board models Jerone Young
@ 2008-03-12  4:50 ` Jerone Young
  2008-03-13  2:23   ` [kvm-ppc-devel] " Hollis Blanchard
  2008-03-13  2:55 ` [kvm-ppc-devel] [PATCH 0 of 7] PowerPC kvm-userspace patches Hollis Blanchard
  7 siblings, 1 reply; 17+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 8b1dd3609551efefbd6633ac6fe4caa3a6cbe5e9
# Parent  3a891d8fada96166089b5796f3241087d4aae50f
Add ability to specify ram on command line for bamboo board model

This patch adds the ability to now specify ram sizes on the command line.
Due to the nature of the code there are restictions on exactly how
much ram and the multiple that the size must match.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
--- a/qemu/hw/ppc440_bamboo.c
+++ b/qemu/hw/ppc440_bamboo.c
@@ -40,32 +40,71 @@ void bamboo_init(ram_addr_t ram_size, in
 	target_ulong dt_base=0;
 	void *fdt;
 	int ret;
+	int holdr;
+ 	unsigned long ram_size1; /* Value will be in bytes */
+ 	unsigned long ram_size2; /* Value will be in bytes */
+
 
 	uint32_t cpu_freq;
 	uint32_t timebase_freq;
 
 	printf("%s: START\n", __func__);
 
-	/* Setup Memory */
-	if (ram_size) {
-		printf("Ram size specified on command line is %i bytes\n",
-								(int)ram_size);
-		printf("WARNING: RAM is hard coded to 144MB\n");
-	}
-	else {
-		printf("Using defualt ram size of %iMB\n",
-						((int)ram_size/1024)/1024);
-	}
-
-	/* Each bank can only have memory in configurations of
-	 *   16MB, 32MB, 64MB, 128MB, or 256MB
-	 */
-	ram_bases[0] = 0x0;
-	ram_sizes[0] = 0x08000000;
-	ram_bases[1] = 0x0;
-	ram_sizes[1] = 0x01000000;
-
-	printf("Ram size of domain is %d bytes\n", (int)ram_size);
+ 	/* Setup Memory */
+ 	printf("Ram size is set to: %i MB\n",
+ 				((int)ram_size/1024)/1024); 		
+ 
+   	/* Check that total ram is at least 8 MB 
+  	 * but less than 512 MB 
+    	 * and is a multiple of 4
+    	 */
+ 
+ 	if (ram_size < (8 * 1024 * 1024)) {
+ 		printf("Ram size specified on cmd line must at least be 8 MB\n");
+ 		exit(1);
+ 	}
+ 
+ 	if (ram_size > (512 * 1024 * 1024)) {
+ 		printf("Ram size specified on cmd line is greater than 512 MB\n");
+ 		exit(1);
+ 	}
+ 
+ 	if ((((int)ram_size/1024)/1024) % 4) {
+ 		printf("Ram size specified on cmd line must be multiple of 4\n");
+ 		exit(1);
+ 	}
+ 
+ 	/* split ram into two slots */
+ 	holdr = (ram_size/(1024*1024))/4;	
+ 
+ 	/* ram_size2 has to at least have 4MB in it*/
+ 	ram_size2 = 4 * 1024 * 1024; /* Add 4MB */
+ 	holdr = holdr - 1;
+ 
+ 	
+ 	if ((4 * holdr) <= 256) {
+ 		/* if what remains is 256MB or less put in first slot */
+ 		ram_size1 = (4 * holdr) * (1024 * 1024);
+ 	}
+ 	else {
+ 		/* place first 256MB or less in first slot */
+ 		ram_size1 = 256 * 1024 * 1024;
+ 		holdr = holdr - (256/4);
+ 		
+ 		/* place remainder in slot 2 */
+ 		ram_size2 += (4 * holdr) * (1024 * 1024);
+ 	}
+ 
+ 	/* Each bank can only have memory in configurations of
+ 	 *   4MB, 8MB, 16MB, 32MB, 64MB, 128MB, or 256MB
+ 	 *   why? see sdram_bcr()
+ 	 *   
+ 	 *   Max of 512MB
+ 	 */
+ 	ram_bases[0] = 0x0;
+ 	ram_sizes[0] = ram_size1;
+ 	ram_bases[1] = 0x0;
+ 	ram_sizes[1] = ram_size2;	
 
 	/* Setup CPU */
 	env = cpu_ppc_init("440");

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model
  2008-03-12  4:50 ` [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model Jerone Young
@ 2008-03-13  2:23   ` Hollis Blanchard
  0 siblings, 0 replies; 17+ messages in thread
From: Hollis Blanchard @ 2008-03-13  2:23 UTC (permalink / raw)
  To: Jerone Young; +Cc: kvm-ppc-devel, kvm-devel

On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> # HG changeset patch
> # User Jerone Young <jyoung5@us.ibm.com>
> # Date 1205296680 18000
> # Branch merge
> # Node ID 8b1dd3609551efefbd6633ac6fe4caa3a6cbe5e9
> # Parent  3a891d8fada96166089b5796f3241087d4aae50f
> Add ability to specify ram on command line for bamboo board model
> 
> This patch adds the ability to now specify ram sizes on the command line.
> Due to the nature of the code there are restictions on exactly how
> much ram and the multiple that the size must match.
> 
> Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

NAK, this is both brittle and overcomplicated. Try translating the
following Python to C:

ram = 144
reg = [0, 0, 0, 0]
sizes = (256, 128, 64, 32, 16, 8)

for i in range(len(reg)):
        for size in sizes:
                if ram / size:
                        reg[i] = size
                        ram -= size
                        break

if ram:
        print "warning: %d left over" % ram
print reg

-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 1 of 7] Add libfdt to KVM userspace
  2008-03-12  4:50 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
@ 2008-03-13  2:25   ` Hollis Blanchard
  0 siblings, 0 replies; 17+ messages in thread
From: Hollis Blanchard @ 2008-03-13  2:25 UTC (permalink / raw)
  To: Jerone Young; +Cc: kvm-ppc-devel, kvm-devel

On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> diff --git a/libfdt/Makefile b/libfdt/Makefile
> new file mode 100644
> --- /dev/null
> +++ b/libfdt/Makefile
> @@ -0,0 +1,19 @@
> +include ../config.mak
> +include ../user/config.mak
> +
> +LIBFDT_OBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o
> +
> +LIBFDT_INCLUDES = fdt.h libfdt.h
> +LIBFDT_EXTRA = libfdt_internal.h
> +
> +LIBFDT_LIB = libfdt.a
> +
> +CFLAGS += -I .
> +
> +all: libfdt.a
> +
> +libfdt.a: $(LIBFDT_OBJS)
> +	$(AR) rcs $@ $^
> +
> +clean: 
> +	rm -rf *.o *.a
> diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
> new file mode 100644
> --- /dev/null
> +++ b/libfdt/Makefile.libfdt
> @@ -0,0 +1,14 @@
> +# Makefile.libfdt
> +#
> +# This is not a complete Makefile of itself.  Instead, it is designed to
> +# be easily embeddable into other systems of Makefiles.
> +#
> +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
> +LIBFDT_INCLUDES = fdt.h libfdt.h
> +LIBFDT_EXTRA = libfdt_internal.h
> +LIBFDT_LIB = libfdt/libfdt.a
> +
> +LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
> +
> +$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
> +

Why are you duplicating Makefile.libfdt instead of including it?

-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu
  2008-03-12  4:50 ` [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu Jerone Young
@ 2008-03-13  2:36   ` Hollis Blanchard
  2008-03-13 20:09     ` Jerone Young
  0 siblings, 1 reply; 17+ messages in thread
From: Hollis Blanchard @ 2008-03-13  2:36 UTC (permalink / raw)
  To: Jerone Young; +Cc: kvm-ppc-devel, kvm-devel

On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> diff --git a/qemu/sysemu.h b/qemu/sysemu.h
> --- a/qemu/sysemu.h
> +++ b/qemu/sysemu.h
> @@ -182,6 +182,9 @@ int load_elf(const char *filename, int64
>               uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr);
>  int load_aout(const char *filename, uint8_t *addr);
>  int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
> +int load_uboot_l(const char *filename, target_ulong *ep, 
> +             target_ulong *la, target_ulong *loaded_image_size,
> +             int *is_linux);
>  #endif
> 
>  #ifdef HAS_AUDIO

I don't like the "_l" name, nor "la". Without reading the code I have no
idea what those mean.

Can't you just update the other load_uboot() callers? There are only 4
of them... and while you're at it, you should rename the function to
load_uimage(). Pass NULL for whatever you rename "la" to, just like
"is_linux" is handled already.

-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu
  2008-03-12  4:50 ` [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu Jerone Young
@ 2008-03-13  2:42   ` Hollis Blanchard
  2008-03-13 20:24     ` Jerone Young
  0 siblings, 1 reply; 17+ messages in thread
From: Hollis Blanchard @ 2008-03-13  2:42 UTC (permalink / raw)
  To: Jerone Young; +Cc: kvm-ppc-devel, kvm-devel

On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> # HG changeset patch
> # User Jerone Young <jyoung5@us.ibm.com>
> # Date 1205296680 18000
> # Branch merge
> # Node ID 9c15709640cd55bf6f782d6856423363312493bb
> # Parent  48651677b7d05254d6acf03551bfea05cef8aa47
> Add PPC 440EP bamboo board device tree source & binary into qemu
> 
> This patch places the bamboo device tree for the PPC 440EP bamboo
> board into the pc-bios directory of the qemu source. This also adds a
> rule into the pc-bios/Makefile to build device tree files.
> 
> Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
> 
> diff --git a/qemu/pc-bios/Makefile b/qemu/pc-bios/Makefile
> --- a/qemu/pc-bios/Makefile
> +++ b/qemu/pc-bios/Makefile
> @@ -12,6 +12,9 @@ all: $(TARGETS)
>  %.o: %.S
>  	$(CC) $(DEFINES) -c -o $@ $<
> 
> +%.dtb: %.dts 
> +	dtc -O dtb -I dts -o $@ $< 
> +
>  clean:
> -	rm -f $(TARGETS) *.o *~
> +	rm -f $(TARGETS) *.o *~ *.dtb
> 
> diff --git a/qemu/pc-bios/bamboo.dts b/qemu/pc-bios/bamboo.dts
> new file mode 100644
> --- /dev/null
> +++ b/qemu/pc-bios/bamboo.dts
> @@ -0,0 +1,310 @@
> +/*
> + * Device Tree Source for AMCC Bamboo
> + *
> + * Copyright (c) 2006, 2007 IBM Corp.
> + * Josh Boyer <jwboyer@linux.vnet.ibm.com>
> + *
> + * FIXME: Draft only!

Might as well remove this. In its place, add a little blurb explaining
how this file is used, and how qemu modifies the binary device tree at
runtime.

> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without
> + * any warranty of any kind, whether express or implied.
> + */
> +
> +/ {
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	model = "amcc,bamboo";
> +	compatible = "amcc,bamboo";
> +	dcr-parent = <&/cpus/cpu@0>;
> +
> +	aliases {
> +/*		ethernet0 = &EMAC0;  */
> +/*		ethernet1 = &EMAC1;  *
> +		serial0 = &UART0;
> + 		serial1 = &UART1;   
> +/*		serial2 = &UART2;    */
> +/*		serial3 = &UART3;    */
> +	};

Please just remove all the stuff you've commented out.

> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu@0 {
> +			device_type = "cpu";
> +			model = "PowerPC,440EP";
> +			reg = <0>;
> +			clock-frequency = <1fca0550>; /* Filled in by zImage */
> +			timebase-frequency = <017d7840>; /* Filled in by zImage */
> +			i-cache-line-size = <20>;
> +			d-cache-line-size = <20>;
> +			i-cache-size = <8000>;
> +			d-cache-size = <8000>;
> +			dcr-controller;
> +			dcr-access-method = "native";
> +		};
> +	};
> +	memory {
> +		device_type = "memory";
> +		reg = <0 0 9000000>; /* Filled in by zImage */
> +	};

Also remove all references to "zImage".

> +	UIC0: interrupt-controller0 {
> +		compatible = "ibm,uic-440ep","ibm,uic";
> +		interrupt-controller;
> +		cell-index = <0>;
> +		dcr-reg = <0c0 009>;
> +		#address-cells = <0>;
> +		#size-cells = <0>;
> +		#interrupt-cells = <2>;
> +	};
> +/*
> +	UIC1: interrupt-controller1 {
> +		compatible = "ibm,uic-440ep","ibm,uic";
> +		interrupt-controller;
> +		cell-index = <1>;
> +		dcr-reg = <0d0 009>;
> +		#address-cells = <0>;
> +		#size-cells = <0>;
> +		#interrupt-cells = <2>;
> +		interrupts = <1e 4 1f 4>; 
> +		interrupt-parent = <&UIC0>;
> +	};
> +*/

Is it difficult to add UIC1 to our 440EP init code?

> +
> +		PCI0: pci@ec000000 {
> +			device_type = "pci";
> +			#interrupt-cells = <1>;
> +			#size-cells = <2>;
> +			#address-cells = <3>;
> +			compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
> +			primary;
> +			reg = <0 eec00000 8	/* Config space access */
> +			       0 eed00000 4	/* IACK */
> +			       0 eed00000 4	/* Special cycle */
> +			       0 ef400000 40>;	/* Internal registers */
> +
> +			/* Outbound ranges, one memory and one IO,
> +			 * later cannot be changed. Chip supports a second
> +			 * IO range but we don't use it for now
> +			 */
> +			ranges = <02000000 0 a0000000 0 a0000000 0 20000000
> +				  01000000 0 00000000 0 e8000000 0 00010000>;
> +
> +			/* Inbound 2GB range starting at 0 */
> +			dma-ranges = <42000000 0 0 0 0 0 80000000>;
> +
> +			/* Bamboo has all 4 IRQ pins tied together per slot */
> +			interrupt-map-mask = <f800 0 0 0>;
> +			interrupt-map = <
> +				/* IDSEL 1 */
> +				0800 0 0 0 &UIC0 1c 8
> +
> +				/* IDSEL 2 */
> +				1000 0 0 0 &UIC0 1b 8
> +
> +				/* IDSEL 3 */
> +				1800 0 0 0 &UIC0 1a 8
> +
> +				/* IDSEL 4 */
> +				2000 0 0 0 &UIC0 19 8
> +			>;
> +		};
> +	};

PCI0 is the only node you might want to leave commented out, since we
will have a patch for that in the near future.

However, since we haven't posted that patch yet, the PCI0 node shouldn't
be visible to the guest yet.

> +	chosen {
> +		linux,stdout-path = "/plb/opb/serial@ef600300";
> +		linux,initrd-start = <0>;
> +		linux,initrd-end = <0>;
> +		bootargs = "                ";
> +	};
> +};

Why is bootargs filled with spaces? Also, do the initrd properties need
to be present? I thought you figured out how to add them at runtime.

-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model
  2008-03-12  4:50 ` [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model Jerone Young
@ 2008-03-13  2:53   ` Hollis Blanchard
  2008-03-13 22:27     ` Jerone Young
  0 siblings, 1 reply; 17+ messages in thread
From: Hollis Blanchard @ 2008-03-13  2:53 UTC (permalink / raw)
  To: Jerone Young; +Cc: kvm-ppc-devel, kvm-devel

You've misspelled "licence" several times in this patch.

On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> # HG changeset patch
> # User Jerone Young <jyoung5@us.ibm.com>
> # Date 1205296680 18000
> # Branch merge
> # Node ID 50fddb23a4c19ec6f359a4dd39e98712eb6bcaeb
> # Parent  9c15709640cd55bf6f782d6856423363312493bb
> Add dynamic device tree manipulation & change uboot loader for PPC
> bamboo board model
> 
> This patch adds code to dynamically manipulate the device tree when
> loaded into memory. This allows us to finally have the ability to
> manipulate the kernel command line & initrd from the qemu command
> line. This will also let us setup different settings for the board.
> 
> This patch also now uses new uboot loader uboot_loader_l() to load
> kernel image.

So the load_uboot() part should be a separate patch, right?

> Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
> 
> diff --git a/qemu/Makefile.target b/qemu/Makefile.target
> --- a/qemu/Makefile.target
> +++ b/qemu/Makefile.target
> @@ -615,7 +615,7 @@ OBJS+= unin_pci.o ppc_chrp.o
>  OBJS+= unin_pci.o ppc_chrp.o
>  # PowerPC 4xx boards
>  OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
> -OBJS+= ppc440.o ppc440_bamboo.o
> +OBJS+= ppc440.o ppc440_bamboo.o ppc_device_tree_support.o
>  endif
>  ifeq ($(TARGET_BASE_ARCH), mips)
>  OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
> diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
> --- a/qemu/hw/ppc440_bamboo.c
> +++ b/qemu/hw/ppc440_bamboo.c
> @@ -8,11 +8,12 @@
>   *
>   */
> 
> +#include "config.h"
>  #include "ppc440.h"
> +#include "qemu-kvm.h"
> +#include "ppc_device_tree_support.h"
> 
> -#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
> -
> -#include "qemu-kvm.h"
> +#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
> 
>  /* PPC 440 refrence demo board
>   *
> @@ -26,14 +27,22 @@ void bamboo_init(ram_addr_t ram_size, in
>  			const char *initrd_filename,
>  			const char *cpu_model)
>  {
> +	char buf[1024];	
>  	target_phys_addr_t ram_bases[2], ram_sizes[2];
>  	qemu_irq *pic;
>  	CPUState *env;
> -	target_ulong ep;
> +	target_ulong ep=0;
> +	target_ulong la=0;
>  	int is_linux=1; /* Will assume allways is Linux for now */
> -	long kernel_size=0;
> +	target_long kernel_size=0;
>  	target_ulong initrd_base=0;
> -	target_ulong initrd_size=0;
> +	target_long initrd_size=0;
> +	target_ulong dt_base=0;
> +	void *fdt;
> +	int ret;
> +
> +	uint32_t cpu_freq;
> +	uint32_t timebase_freq;
> 
>  	printf("%s: START\n", __func__);
> 
> @@ -78,18 +87,23 @@ void bamboo_init(ram_addr_t ram_size, in
> 
>  	/* load kernel with uboot loader */
>  	printf("%s: load kernel\n", __func__);
> -	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
> +	load_uboot_l(kernel_filename, &ep, &la, &kernel_size, &is_linux);
>  	if (kernel_size < 0) {
>  		fprintf(stderr, "qemu: could not load kernel '%s'\n",
>  			kernel_filename);
>  		exit(1);
>  	}
> +	printf("kernel is at guest address: 0x%lx\n", (unsigned long)la);
> 
>  	/* load initrd */
>  	if (initrd_filename) {
> -		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
> +        	initrd_base = kernel_size + la;
> +		printf("%s: load initrd\n", __func__);
>  		initrd_size = load_image(initrd_filename,
>  				phys_ram_base + initrd_base);
> +
> +		printf("initrd is at guest address: 0x%lx\n", 
> +					(unsigned long) initrd_base);
> 
>  		if (initrd_size < 0) {
>  			fprintf(stderr,
> @@ -99,17 +113,58 @@ void bamboo_init(ram_addr_t ram_size, in
>  		}
>  	}
> 
> +#ifdef CONFIG_LIBFDT
> +	/* get variable for device tree */
> +	cpu_freq = get_proc_dt_prop_cpu_clock_freq();
> +	timebase_freq = get_proc_dt_prop_cpu_timebase_freq();
> +
> +	/* load binary device tree into qemu (not guest memory) */
> +	printf("%s: load device tree file\n", __func__);
> +	
> +	snprintf(buf, sizeof(buf), "%s/%s", bios_dir, 
> +		BINARY_DEVICE_TREE_FILE);
> +
> +	/* set base for device tree that will be in guest memory */	
> +	if (initrd_base)
> +		dt_base = initrd_base + initrd_size;
> +	else
> +		dt_base = kernel_size + la;
> +
> +	fdt = load_device_tree(buf, (phys_ram_base + dt_base));
> +	if (fdt == NULL) {
> +		printf("Loading device tree failed!\n");
> +		exit(1);
> +	}
> +
> +	printf("device tree address is at guest address: 0x%lx\n", 
> +		(unsigned long) dt_base);
> +
> +	/* manipulate device tree in memory */
> +	set_dt_cpu_0_clock_freq_prop(fdt, cpu_freq);
> +	set_dt_cpu_0_timebase_prop(fdt, timebase_freq);
> +
> +	set_dt_initrd_start_prop(fdt, initrd_base);
> +	set_dt_initrd_end_prop(fdt, (initrd_base + initrd_size));
> +
> +	set_dt_bootargs_prop(fdt, kernel_cmdline);
> +#endif
> +
>  	if (kvm_enabled()) {
> -	    /* XXX insert TLB entries */
> -	    env->gpr[1] = (16<<20) - 8;
> -	    env->gpr[4] = initrd_base;
> -	    env->gpr[5] = initrd_size;
> 
> -	    env->nip = ep;
> +		/* XXX insert TLB entries */
> +		env->gpr[1] = (16<<20) - 8;

Please fix your whitespace.

> -	    env->cpu_index = 0;
> -	    printf("%s: loading kvm registers\n", __func__);
> -	    kvm_load_registers(env);
> +#ifdef CONFIG_LIBFDT
> +		/* location of device tree in register */
> +		env->gpr[3] = dt_base;
> +#else
> +		env->gpr[4] = initrd_base;
> +		env->gpr[5] = initrd_size;
> +#endif

Linux ignores R4 and R5 regardless of whether qemu has libfdt support or
not. Those should be removed.

> +		env->nip = ep;
> +
> +		printf("%s: loading kvm registers\n", __func__);
> +		kvm_load_registers(env);
>  	}
> 
>  	printf("%s: DONE\n", __func__);
> diff --git a/qemu/hw/ppc_device_tree_support.c b/qemu/hw/ppc_device_tree_support.c
> new file mode 100644
> --- /dev/null
> +++ b/qemu/hw/ppc_device_tree_support.c

This is a really long file name.

> @@ -0,0 +1,223 @@
> +/*
> + * Functions to help device tree manipulation using libfdt.
> + * It also provides functions to read entries from device tree proc
> + * interface.
> + *
> + * Copyright 2008 IBM Corporation.
> + * Authors: Jerone Young <jyoung5@us.ibm.com>
> + *
> + * This work is licensed under the GNU GPL licence version 2 or later.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +
> +#include "config.h"
> +#include "ppc440.h"
> +
> +#ifdef CONFIG_LIBFDT
> +	#include "libfdt.h"
> +#endif

Don't indent this.

> +#define DT_PROC_INTERFACE_PATH "/proc/device-tree"
> +
> +/* FUNCTIONS FOR READING FROM DEVICE TREE OF HOST IN /PROC */
> +
> +/* This function reads device-tree property files that are of
> + * a single cell size
> + */
> +static uint32_t read_proc_device_tree_prop_cell(char *path_in_device_tree)
> +{
> +	char buf[1024];
> +	uint32_t num;
> +	FILE *stream;
> +
> +	snprintf(buf, sizeof(buf), "%s/%s",  DT_PROC_INTERFACE_PATH,
> +		path_in_device_tree);
> +
> +	stream = fopen(buf, "rb");
> +	
> +	if (stream == NULL)
> +	{
> +		printf("%s: Unable to open '%s'\n", __func__, buf);
> +		exit(1);
> +	}
> +
> +	fread(&num, sizeof(num), 1, stream);
> +	fclose(stream);
> +
> +	return num;
> +} 

I hate that "buf" variable. You can use snprintf() with length 0 to find
out how much memory to malloc.

...
> +void set_dt_cpu_0_timebase_prop(void *fdt, uint32_t timebase)
> +{	
> +	int offset;
> +	offset = get_offset_of_node(fdt, "/cpus/cpu@0");
> +	set_dt_prop_cell(fdt, offset, "timebase-frequency",
> +			timebase);
> +
> +}
> +
> +void set_dt_initrd_start_prop(void *fdt, uint32_t start_addr)
> +{
> +	int offset;
> +	offset = get_offset_of_node(fdt, "/chosen");
> +	set_dt_prop_cell(fdt, offset, "linux,initrd-start",
> +			start_addr);
> +}
> +
> +void set_dt_initrd_end_prop(void *fdt, uint32_t end_addr)
> +{
> +	int offset;
> +	offset = get_offset_of_node(fdt, "/chosen");
> +	set_dt_prop_cell(fdt, offset, "linux,initrd-end",
> +			end_addr);
> +}
> +
> +void set_dt_bootargs_prop(void *fdt, char *cmdline)
> +{
> +	int offset;
> +	offset = get_offset_of_node(fdt, "/chosen");
> +	set_dt_prop_string(fdt,offset, "bootargs", cmdline);
> +}
> +
> +#endif

These are also really long function names. If you're basically going to
encode the full device tree path into the function name, I don't think
they're very convenient and they're not worth having. You could just
pass the path in from the caller.

-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 0 of 7] PowerPC kvm-userspace patches
  2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
                   ` (6 preceding siblings ...)
  2008-03-12  4:50 ` [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model Jerone Young
@ 2008-03-13  2:55 ` Hollis Blanchard
  7 siblings, 0 replies; 17+ messages in thread
From: Hollis Blanchard @ 2008-03-13  2:55 UTC (permalink / raw)
  To: Jerone Young; +Cc: kvm-ppc-devel, kvm-devel

On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> This set of patches enables the following:
> 	-Device tree Support
> 		- Add libfdt to kvm-userspace
> 		- Add bamboo device tree to qemu source
>         	- Detection of host Device Tree attributes
> 		- Device tree loading
>        	 	- Ability to specify initrd on the command line
>         	- Ability to add kernel arguments on the command line
> 	- Ability to load compressed uImages
> 	- Ability to specify memory on the command line

This is good work, but I have some comments. :) I'll be happy to ack
this stuff once those are addressed.

> So now when running powerpc code on a 440board. 
> 
> Known Issues:
>    There is an issue currently where guest kernel is not mounting the initrd.
>    Working it now!
> 
>    But these changes should go in anyway.

I don't believe our initrd troubles have anything to do with qemu, so I
wouldn't worry about that here.

-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu
  2008-03-13  2:36   ` [kvm-ppc-devel] " Hollis Blanchard
@ 2008-03-13 20:09     ` Jerone Young
  0 siblings, 0 replies; 17+ messages in thread
From: Jerone Young @ 2008-03-13 20:09 UTC (permalink / raw)
  To: Hollis Blanchard; +Cc: kvm-ppc-devel, kvm-devel

On Wed, 2008-03-12 at 21:36 -0500, Hollis Blanchard wrote:
> On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> > diff --git a/qemu/sysemu.h b/qemu/sysemu.h
> > --- a/qemu/sysemu.h
> > +++ b/qemu/sysemu.h
> > @@ -182,6 +182,9 @@ int load_elf(const char *filename, int64
> >               uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr);
> >  int load_aout(const char *filename, uint8_t *addr);
> >  int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
> > +int load_uboot_l(const char *filename, target_ulong *ep, 
> > +             target_ulong *la, target_ulong *loaded_image_size,
> > +             int *is_linux);
> >  #endif
> > 
> >  #ifdef HAS_AUDIO
> 
> I don't like the "_l" name, nor "la". Without reading the code I have no
> idea what those mean.
> 
> Can't you just update the other load_uboot() callers? There are only 4
> of them... and while you're at it, you should rename the function to
> load_uimage(). Pass NULL for whatever you rename "la" to, just like
> "is_linux" is handled already.

I changed the name to load_uimage() .. but still going to keep
load_uboot() wrapper until this actually makes it to upstream qemu. Then
it will make since to add changing all the others and then removing the
wrapper.

> 


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu
  2008-03-13  2:42   ` [kvm-ppc-devel] " Hollis Blanchard
@ 2008-03-13 20:24     ` Jerone Young
  0 siblings, 0 replies; 17+ messages in thread
From: Jerone Young @ 2008-03-13 20:24 UTC (permalink / raw)
  To: Hollis Blanchard; +Cc: kvm-ppc-devel, kvm-devel

On Wed, 2008-03-12 at 21:42 -0500, Hollis Blanchard wrote:
> On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> > # HG changeset patch
> > # User Jerone Young <jyoung5@us.ibm.com>
> > # Date 1205296680 18000
> > # Branch merge
> > # Node ID 9c15709640cd55bf6f782d6856423363312493bb
> > # Parent  48651677b7d05254d6acf03551bfea05cef8aa47
> > Add PPC 440EP bamboo board device tree source & binary into qemu
> > 
> > This patch places the bamboo device tree for the PPC 440EP bamboo
> > board into the pc-bios directory of the qemu source. This also adds a
> > rule into the pc-bios/Makefile to build device tree files.
> > 
> > Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
> > 
> > diff --git a/qemu/pc-bios/Makefile b/qemu/pc-bios/Makefile
> > --- a/qemu/pc-bios/Makefile
> > +++ b/qemu/pc-bios/Makefile
> > @@ -12,6 +12,9 @@ all: $(TARGETS)
> >  %.o: %.S
> >  	$(CC) $(DEFINES) -c -o $@ $<
> > 
> > +%.dtb: %.dts 
> > +	dtc -O dtb -I dts -o $@ $< 
> > +
> >  clean:
> > -	rm -f $(TARGETS) *.o *~
> > +	rm -f $(TARGETS) *.o *~ *.dtb
> > 
> > diff --git a/qemu/pc-bios/bamboo.dts b/qemu/pc-bios/bamboo.dts
> > new file mode 100644
> > --- /dev/null
> > +++ b/qemu/pc-bios/bamboo.dts
> > @@ -0,0 +1,310 @@
> > +/*
> > + * Device Tree Source for AMCC Bamboo
> > + *
> > + * Copyright (c) 2006, 2007 IBM Corp.
> > + * Josh Boyer <jwboyer@linux.vnet.ibm.com>
> > + *
> > + * FIXME: Draft only!
> 
> Might as well remove this. In its place, add a little blurb explaining
> how this file is used, and how qemu modifies the binary device tree at
> runtime.
> 
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2.  This program is licensed "as is" without
> > + * any warranty of any kind, whether express or implied.
> > + */
> > +
> > +/ {
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> > +	model = "amcc,bamboo";
> > +	compatible = "amcc,bamboo";
> > +	dcr-parent = <&/cpus/cpu@0>;
> > +
> > +	aliases {
> > +/*		ethernet0 = &EMAC0;  */
> > +/*		ethernet1 = &EMAC1;  *
> > +		serial0 = &UART0;
> > + 		serial1 = &UART1;   
> > +/*		serial2 = &UART2;    */
> > +/*		serial3 = &UART3;    */
> > +	};
> 
> Please just remove all the stuff you've commented out.


Ok mainly just commented out stuff so that if we later wanted to have it
(for what ever reason), it could just be uncommented.

> 
> > +	cpus {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		cpu@0 {
> > +			device_type = "cpu";
> > +			model = "PowerPC,440EP";
> > +			reg = <0>;
> > +			clock-frequency = <1fca0550>; /* Filled in by zImage */
> > +			timebase-frequency = <017d7840>; /* Filled in by zImage */
> > +			i-cache-line-size = <20>;
> > +			d-cache-line-size = <20>;
> > +			i-cache-size = <8000>;
> > +			d-cache-size = <8000>;
> > +			dcr-controller;
> > +			dcr-access-method = "native";
> > +		};
> > +	};
> > +	memory {
> > +		device_type = "memory";
> > +		reg = <0 0 9000000>; /* Filled in by zImage */
> > +	};
> 
> Also remove all references to "zImage".

I can. Though this helped me to determine which variables that need to
be filled in. I'll still have it in some places till I have the code to
fill them in.

> 
> > +	UIC0: interrupt-controller0 {
> > +		compatible = "ibm,uic-440ep","ibm,uic";
> > +		interrupt-controller;
> > +		cell-index = <0>;
> > +		dcr-reg = <0c0 009>;
> > +		#address-cells = <0>;
> > +		#size-cells = <0>;
> > +		#interrupt-cells = <2>;
> > +	};
> > +/*
> > +	UIC1: interrupt-controller1 {
> > +		compatible = "ibm,uic-440ep","ibm,uic";
> > +		interrupt-controller;
> > +		cell-index = <1>;
> > +		dcr-reg = <0d0 009>;
> > +		#address-cells = <0>;
> > +		#size-cells = <0>;
> > +		#interrupt-cells = <2>;
> > +		interrupts = <1e 4 1f 4>; 
> > +		interrupt-parent = <&UIC0>;
> > +	};
> > +*/
> 
> Is it difficult to add UIC1 to our 440EP init code?

I'll leave this commented. But will have to try adding once bigger
issues are taken care of.

> 
> > +
> > +		PCI0: pci@ec000000 {
> > +			device_type = "pci";
> > +			#interrupt-cells = <1>;
> > +			#size-cells = <2>;
> > +			#address-cells = <3>;
> > +			compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
> > +			primary;
> > +			reg = <0 eec00000 8	/* Config space access */
> > +			       0 eed00000 4	/* IACK */
> > +			       0 eed00000 4	/* Special cycle */
> > +			       0 ef400000 40>;	/* Internal registers */
> > +
> > +			/* Outbound ranges, one memory and one IO,
> > +			 * later cannot be changed. Chip supports a second
> > +			 * IO range but we don't use it for now
> > +			 */
> > +			ranges = <02000000 0 a0000000 0 a0000000 0 20000000
> > +				  01000000 0 00000000 0 e8000000 0 00010000>;
> > +
> > +			/* Inbound 2GB range starting at 0 */
> > +			dma-ranges = <42000000 0 0 0 0 0 80000000>;
> > +
> > +			/* Bamboo has all 4 IRQ pins tied together per slot */
> > +			interrupt-map-mask = <f800 0 0 0>;
> > +			interrupt-map = <
> > +				/* IDSEL 1 */
> > +				0800 0 0 0 &UIC0 1c 8
> > +
> > +				/* IDSEL 2 */
> > +				1000 0 0 0 &UIC0 1b 8
> > +
> > +				/* IDSEL 3 */
> > +				1800 0 0 0 &UIC0 1a 8
> > +
> > +				/* IDSEL 4 */
> > +				2000 0 0 0 &UIC0 19 8
> > +			>;
> > +		};
> > +	};
> 
> PCI0 is the only node you might want to leave commented out, since we
> will have a patch for that in the near future.
> 
> However, since we haven't posted that patch yet, the PCI0 node shouldn't
> be visible to the guest yet.
> 
> > +	chosen {
> > +		linux,stdout-path = "/plb/opb/serial@ef600300";
> > +		linux,initrd-start = <0>;
> > +		linux,initrd-end = <0>;
> > +		bootargs = "                ";
> > +	};
> > +};
> 
> Why is bootargs filled with spaces? Also, do the initrd properties need
> to be present? I thought you figured out how to add them at runtime.

These are going to be removed. I left them in. But they actually don't
need to be here at all.

> 


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [kvm-ppc-devel] [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model
  2008-03-13  2:53   ` [kvm-ppc-devel] " Hollis Blanchard
@ 2008-03-13 22:27     ` Jerone Young
  0 siblings, 0 replies; 17+ messages in thread
From: Jerone Young @ 2008-03-13 22:27 UTC (permalink / raw)
  To: Hollis Blanchard; +Cc: kvm-ppc-devel, kvm-devel

On Wed, 2008-03-12 at 21:53 -0500, Hollis Blanchard wrote:
> You've misspelled "licence" several times in this patch.

Got them. More of one error propagating through cut & paste.
> 
> On Tue, 2008-03-11 at 23:50 -0500, Jerone Young wrote:
> > # HG changeset patch
> > # User Jerone Young <jyoung5@us.ibm.com>
> > # Date 1205296680 18000
> > # Branch merge
> > # Node ID 50fddb23a4c19ec6f359a4dd39e98712eb6bcaeb
> > # Parent  9c15709640cd55bf6f782d6856423363312493bb
> > Add dynamic device tree manipulation & change uboot loader for PPC
> > bamboo board model
> > 
> > This patch adds code to dynamically manipulate the device tree when
> > loaded into memory. This allows us to finally have the ability to
> > manipulate the kernel command line & initrd from the qemu command
> > line. This will also let us setup different settings for the board.
> > 
> > This patch also now uses new uboot loader uboot_loader_l() to load
> > kernel image.
> 
> So the load_uboot() part should be a separate patch, right?
> 
> > Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
> > 
> > diff --git a/qemu/Makefile.target b/qemu/Makefile.target
> > --- a/qemu/Makefile.target
> > +++ b/qemu/Makefile.target
> > @@ -615,7 +615,7 @@ OBJS+= unin_pci.o ppc_chrp.o
> >  OBJS+= unin_pci.o ppc_chrp.o
> >  # PowerPC 4xx boards
> >  OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
> > -OBJS+= ppc440.o ppc440_bamboo.o
> > +OBJS+= ppc440.o ppc440_bamboo.o ppc_device_tree_support.o
> >  endif
> >  ifeq ($(TARGET_BASE_ARCH), mips)
> >  OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
> > diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
> > --- a/qemu/hw/ppc440_bamboo.c
> > +++ b/qemu/hw/ppc440_bamboo.c
> > @@ -8,11 +8,12 @@
> >   *
> >   */
> > 
> > +#include "config.h"
> >  #include "ppc440.h"
> > +#include "qemu-kvm.h"
> > +#include "ppc_device_tree_support.h"
> > 
> > -#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
> > -
> > -#include "qemu-kvm.h"
> > +#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
> > 
> >  /* PPC 440 refrence demo board
> >   *
> > @@ -26,14 +27,22 @@ void bamboo_init(ram_addr_t ram_size, in
> >  			const char *initrd_filename,
> >  			const char *cpu_model)
> >  {
> > +	char buf[1024];	
> >  	target_phys_addr_t ram_bases[2], ram_sizes[2];
> >  	qemu_irq *pic;
> >  	CPUState *env;
> > -	target_ulong ep;
> > +	target_ulong ep=0;
> > +	target_ulong la=0;
> >  	int is_linux=1; /* Will assume allways is Linux for now */
> > -	long kernel_size=0;
> > +	target_long kernel_size=0;
> >  	target_ulong initrd_base=0;
> > -	target_ulong initrd_size=0;
> > +	target_long initrd_size=0;
> > +	target_ulong dt_base=0;
> > +	void *fdt;
> > +	int ret;
> > +
> > +	uint32_t cpu_freq;
> > +	uint32_t timebase_freq;
> > 
> >  	printf("%s: START\n", __func__);
> > 
> > @@ -78,18 +87,23 @@ void bamboo_init(ram_addr_t ram_size, in
> > 
> >  	/* load kernel with uboot loader */
> >  	printf("%s: load kernel\n", __func__);
> > -	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
> > +	load_uboot_l(kernel_filename, &ep, &la, &kernel_size, &is_linux);
> >  	if (kernel_size < 0) {
> >  		fprintf(stderr, "qemu: could not load kernel '%s'\n",
> >  			kernel_filename);
> >  		exit(1);
> >  	}
> > +	printf("kernel is at guest address: 0x%lx\n", (unsigned long)la);
> > 
> >  	/* load initrd */
> >  	if (initrd_filename) {
> > -		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
> > +        	initrd_base = kernel_size + la;
> > +		printf("%s: load initrd\n", __func__);
> >  		initrd_size = load_image(initrd_filename,
> >  				phys_ram_base + initrd_base);
> > +
> > +		printf("initrd is at guest address: 0x%lx\n", 
> > +					(unsigned long) initrd_base);
> > 
> >  		if (initrd_size < 0) {
> >  			fprintf(stderr,
> > @@ -99,17 +113,58 @@ void bamboo_init(ram_addr_t ram_size, in
> >  		}
> >  	}
> > 
> > +#ifdef CONFIG_LIBFDT
> > +	/* get variable for device tree */
> > +	cpu_freq = get_proc_dt_prop_cpu_clock_freq();
> > +	timebase_freq = get_proc_dt_prop_cpu_timebase_freq();
> > +
> > +	/* load binary device tree into qemu (not guest memory) */
> > +	printf("%s: load device tree file\n", __func__);
> > +	
> > +	snprintf(buf, sizeof(buf), "%s/%s", bios_dir, 
> > +		BINARY_DEVICE_TREE_FILE);
> > +
> > +	/* set base for device tree that will be in guest memory */	
> > +	if (initrd_base)
> > +		dt_base = initrd_base + initrd_size;
> > +	else
> > +		dt_base = kernel_size + la;
> > +
> > +	fdt = load_device_tree(buf, (phys_ram_base + dt_base));
> > +	if (fdt == NULL) {
> > +		printf("Loading device tree failed!\n");
> > +		exit(1);
> > +	}
> > +
> > +	printf("device tree address is at guest address: 0x%lx\n", 
> > +		(unsigned long) dt_base);
> > +
> > +	/* manipulate device tree in memory */
> > +	set_dt_cpu_0_clock_freq_prop(fdt, cpu_freq);
> > +	set_dt_cpu_0_timebase_prop(fdt, timebase_freq);
> > +
> > +	set_dt_initrd_start_prop(fdt, initrd_base);
> > +	set_dt_initrd_end_prop(fdt, (initrd_base + initrd_size));
> > +
> > +	set_dt_bootargs_prop(fdt, kernel_cmdline);
> > +#endif
> > +
> >  	if (kvm_enabled()) {
> > -	    /* XXX insert TLB entries */
> > -	    env->gpr[1] = (16<<20) - 8;
> > -	    env->gpr[4] = initrd_base;
> > -	    env->gpr[5] = initrd_size;
> > 
> > -	    env->nip = ep;
> > +		/* XXX insert TLB entries */
> > +		env->gpr[1] = (16<<20) - 8;
> 
> Please fix your whitespace.

This actually is the white space fix. Moves from 

> 
> > -	    env->cpu_index = 0;
> > -	    printf("%s: loading kvm registers\n", __func__);
> > -	    kvm_load_registers(env);
> > +#ifdef CONFIG_LIBFDT
> > +		/* location of device tree in register */
> > +		env->gpr[3] = dt_base;
> > +#else
> > +		env->gpr[4] = initrd_base;
> > +		env->gpr[5] = initrd_size;
> > +#endif
> 
> Linux ignores R4 and R5 regardless of whether qemu has libfdt support or
> not. Those should be removed.
Oh I forgot. 

> 
> > +		env->nip = ep;
> > +
> > +		printf("%s: loading kvm registers\n", __func__);
> > +		kvm_load_registers(env);
> >  	}
> > 
> >  	printf("%s: DONE\n", __func__);
> > diff --git a/qemu/hw/ppc_device_tree_support.c b/qemu/hw/ppc_device_tree_support.c
> > new file mode 100644
> > --- /dev/null
> > +++ b/qemu/hw/ppc_device_tree_support.c
> 
> This is a really long file name.
Just renamed them something much shorter.

> 
> > @@ -0,0 +1,223 @@
> > +/*
> > + * Functions to help device tree manipulation using libfdt.
> > + * It also provides functions to read entries from device tree proc
> > + * interface.
> > + *
> > + * Copyright 2008 IBM Corporation.
> > + * Authors: Jerone Young <jyoung5@us.ibm.com>
> > + *
> > + * This work is licensed under the GNU GPL licence version 2 or later.
> > + *
> > + */
> > +
> > +#include <stdio.h>
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +#include <fcntl.h>
> > +#include <unistd.h>
> > +#include <stdlib.h>
> > +
> > +#include "config.h"
> > +#include "ppc440.h"
> > +
> > +#ifdef CONFIG_LIBFDT
> > +	#include "libfdt.h"
> > +#endif
> 
> Don't indent this.
> 
> > +#define DT_PROC_INTERFACE_PATH "/proc/device-tree"
> > +
> > +/* FUNCTIONS FOR READING FROM DEVICE TREE OF HOST IN /PROC */
> > +
> > +/* This function reads device-tree property files that are of
> > + * a single cell size
> > + */
> > +static uint32_t read_proc_device_tree_prop_cell(char *path_in_device_tree)
> > +{
> > +	char buf[1024];
> > +	uint32_t num;
> > +	FILE *stream;
> > +
> > +	snprintf(buf, sizeof(buf), "%s/%s",  DT_PROC_INTERFACE_PATH,
> > +		path_in_device_tree);
> > +
> > +	stream = fopen(buf, "rb");
> > +	
> > +	if (stream == NULL)
> > +	{
> > +		printf("%s: Unable to open '%s'\n", __func__, buf);
> > +		exit(1);
> > +	}
> > +
> > +	fread(&num, sizeof(num), 1, stream);
> > +	fclose(stream);
> > +
> > +	return num;
> > +} 
> 
> I hate that "buf" variable. You can use snprintf() with length 0 to find
> out how much memory to malloc.
done

> 
> ...
> > +void set_dt_cpu_0_timebase_prop(void *fdt, uint32_t timebase)
> > +{	
> > +	int offset;
> > +	offset = get_offset_of_node(fdt, "/cpus/cpu@0");
> > +	set_dt_prop_cell(fdt, offset, "timebase-frequency",
> > +			timebase);
> > +
> > +}
> > +
> > +void set_dt_initrd_start_prop(void *fdt, uint32_t start_addr)
> > +{
> > +	int offset;
> > +	offset = get_offset_of_node(fdt, "/chosen");
> > +	set_dt_prop_cell(fdt, offset, "linux,initrd-start",
> > +			start_addr);
> > +}
> > +
> > +void set_dt_initrd_end_prop(void *fdt, uint32_t end_addr)
> > +{
> > +	int offset;
> > +	offset = get_offset_of_node(fdt, "/chosen");
> > +	set_dt_prop_cell(fdt, offset, "linux,initrd-end",
> > +			end_addr);
> > +}
> > +
> > +void set_dt_bootargs_prop(void *fdt, char *cmdline)
> > +{
> > +	int offset;
> > +	offset = get_offset_of_node(fdt, "/chosen");
> > +	set_dt_prop_string(fdt,offset, "bootargs", cmdline);
> > +}
> > +
> > +#endif
> 
> These are also really long function names. If you're basically going to
> encode the full device tree path into the function name, I don't think
> they're very convenient and they're not worth having. You could just
> pass the path in from the caller.
I've reworked the codd to remove all this.

> 


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2008-03-13 22:27 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-12  4:50 [PATCH 0 of 7] PowerPC kvm-userspace patches Jerone Young
2008-03-12  4:50 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
2008-03-13  2:25   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-12  4:50 ` [PATCH 2 of 7] Add libfdt support to qemu Jerone Young
2008-03-12  4:50 ` [PATCH 3 of 7] Create new load_uboot() & gunzip support to uboot loader in Qemu Jerone Young
2008-03-13  2:36   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-13 20:09     ` Jerone Young
2008-03-12  4:50 ` [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu Jerone Young
2008-03-13  2:42   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-13 20:24     ` Jerone Young
2008-03-12  4:50 ` [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model Jerone Young
2008-03-13  2:53   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-13 22:27     ` Jerone Young
2008-03-12  4:50 ` [PATCH 6 of 7] Modify PPC bamboo & ppc440 board models Jerone Young
2008-03-12  4:50 ` [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model Jerone Young
2008-03-13  2:23   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-13  2:55 ` [kvm-ppc-devel] [PATCH 0 of 7] PowerPC kvm-userspace patches Hollis Blanchard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox