Date: Wed, 6 Nov 2013 14:33:37 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r257745 - head/sys/dev/ofw Message-ID: <201311061433.rA6EXbrF010329@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311061433.rA6EXbrF010329>