svn commit: r257745 - head/sys/dev/ofw

Nathan Whitehorn nwhitehorn at FreeBSD.org
Wed Nov 6 14:33:38 UTC 2013


Author: nwhitehorn
Date: Wed Nov  6 14:33:37 2013
New Revision: 257745
URL: http://svnweb.freebsd.org/changeset/base/257745

Log:
  Make OF_nextprop() work correctly for FDT by using the libfdt
  fdt_next_property_offset() API. The old code would sometimes (e.g. on
  the device tree supplied by the RB800 boot loader) get confused and stop
  partway through listing properties.
  
  MFC after:	1 week

Modified:
  head/sys/dev/ofw/ofw_fdt.c

Modified: head/sys/dev/ofw/ofw_fdt.c
==============================================================================
--- head/sys/dev/ofw/ofw_fdt.c	Wed Nov  6 14:24:24 2013	(r257744)
+++ head/sys/dev/ofw/ofw_fdt.c	Wed Nov  6 14:33:37 2013	(r257745)
@@ -137,26 +137,6 @@ fdt_phandle_offset(phandle_t p)
 	return (pint - dtoff);
 }
 
-static int
-fdt_pointer_offset(const void *ptr)
-{
-	uintptr_t dt_struct, p;
-	int offset;
-
-	p = (uintptr_t)ptr;
-	dt_struct = (uintptr_t)fdtp + fdt_off_dt_struct(fdtp);
-
-	if ((p < dt_struct) ||
-	    p > (dt_struct + fdt_size_dt_struct(fdtp)))
-		return (-1);
-
-	offset = p - dt_struct;
-	if (offset < 0)
-		return (-1);
-
-	return (offset);
-}
-
 /* Return the next sibling of this node or 0. */
 static phandle_t
 ofw_fdt_peer(ofw_t ofw, phandle_t node)
@@ -285,41 +265,6 @@ ofw_fdt_getprop(ofw_t ofw, phandle_t pac
 	return (len);
 }
 
-static int
-fdt_nextprop(int offset, char *buf, size_t size)
-{
-	const struct fdt_property *prop;
-	const char *name;
-	uint32_t tag;
-	int nextoffset, depth;
-
-	depth = 0;
-	tag = fdt_next_tag(fdtp, offset, &nextoffset);
-
-	/* Find the next prop */
-	do {
-		offset = nextoffset;
-		tag = fdt_next_tag(fdtp, offset, &nextoffset);
-
-		if (tag == FDT_BEGIN_NODE)
-			depth++;
-		else if (tag == FDT_END_NODE)
-			depth--;
-		else if ((tag == FDT_PROP) && (depth == 0)) {
-			prop =
-			    (const struct fdt_property *)fdt_offset_ptr(fdtp,
-			    offset, sizeof(*prop));
-			name = fdt_string(fdtp,
-			    fdt32_to_cpu(prop->nameoff));
-			strncpy(buf, name, size);
-			return (strlen(name));
-		} else
-			depth = -1;
-	} while (depth >= 0);
-
-	return (0);
-}
-
 /*
  * Get the next property of a package. Return the actual len of retrieved
  * prop name.
@@ -329,26 +274,40 @@ ofw_fdt_nextprop(ofw_t ofw, phandle_t pa
     size_t size)
 {
 	const struct fdt_property *prop;
-	int offset, rv;
+	const char *name;
+	int offset;
 
 	offset = fdt_phandle_offset(package);
 	if (offset < 0)
 		return (-1);
 
-	if (previous == NULL)
-		/* Find the first prop in the node */
-		return (fdt_nextprop(offset, buf, size));
+	/* Find the first prop in the node */
+	offset = fdt_first_property_offset(fdtp, offset);
 
-	/*
-	 * Advance to the previous prop
-	 */
-	prop = fdt_get_property(fdtp, offset, previous, NULL);
+	if (previous != NULL) {
+		while (offset >= 0) {
+			prop = fdt_get_property_by_offset(fdtp, offset, NULL);
+			if (prop == NULL)
+				return (-1); /* Internal error */
+
+			offset = fdt_next_property_offset(fdtp, offset);
+			if (offset < 0)
+				return (0); /* No more properties */
+
+			/* Check if the last one was the one we wanted */
+			name = fdt_string(fdtp, fdt32_to_cpu(prop->nameoff));
+			if (strcmp(name, previous) == 0)
+				break;
+		}
+	}
+
+	prop = fdt_get_property_by_offset(fdtp, offset, &offset);
 	if (prop == NULL)
-		return (-1);
+		return (-1); /* Internal error */
 
-	offset = fdt_pointer_offset(prop);
-	rv = fdt_nextprop(offset, buf, size);
-	return (rv);
+	strncpy(buf, fdt_string(fdtp, fdt32_to_cpu(prop->nameoff)), size);
+
+	return (strlen(buf));
 }
 
 /* Set the value of a property of a package. */


More information about the svn-src-head mailing list