Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Oct 2011 00:40:36 +0530
From:      "Jayachandran C." <jchandra@freebsd.org>
To:        Rafal Jaworowski <raj@semihalf.com>, Marcel Moolenaar <marcel@freebsd.org>, FreeBSD Current <freebsd-current@freebsd.org>
Subject:   [RFC] FDT fix for 64 bit platforms
Message-ID:  <CA%2B7sy7AhU7WLuabx6HCtUgvEtUHWBmGe-eP=N8L9VknM65r-mg@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
I'm planning commit this -CURRENT if there an no objections.

In the current implementation, phandle is used to store a pointer to
the location inside the device tree.  Since phandle_t is u32, this
will not work on 64 bit platforms. With this fix, the phandle is the
offset from the start of device tree pointer 'fdtp', which will be 32
bit.

Review or testing from device tree users will be welcome.

JC.

[-- Attachment #2 --]
commit 330ec3a106a5afe9b1df17ffed75c7525b4edf0b
Author: Jayachandran C <jayachandranc@netlogicmicro.com>
Date:   Wed Oct 12 13:09:25 2011 +0530

    Fix FDT code for 64 bit
    
    Use the offset into the device tree from fdtp as the phandle instead
    of using pointer into the device tree.  This will make sure  that
    phandle fits into a uint32_t type.

diff --git a/sys/dev/ofw/ofw_fdt.c b/sys/dev/ofw/ofw_fdt.c
index 68d3149..f9ccc32 100644
--- a/sys/dev/ofw/ofw_fdt.c
+++ b/sys/dev/ofw/ofw_fdt.c
@@ -112,19 +112,39 @@ ofw_fdt_init(ofw_t ofw, void *data)
  * Device tree functions
  */
 
+static phandle_t
+fdt_offset_phandle(int offset)
+{
+	if (offset < 0)
+		return (0);
+	return ((phandle_t)offset + fdt_off_dt_struct(fdtp));
+}
+
 static int
 fdt_phandle_offset(phandle_t p)
 {
-	const char *dt_struct;
+	int pint = (int)p;
+	int dtoff = fdt_off_dt_struct(fdtp);
+
+	if (pint < dtoff)
+		return (-1);
+	return (pint - dtoff);
+}
+
+static int
+fdt_pointer_offset(const void *ptr)
+{
+	uintptr_t dt_struct, p;
 	int offset;
 
-	dt_struct = (const char *)fdtp + fdt_off_dt_struct(fdtp);
+	p = (uintptr_t)ptr;
+	dt_struct = (uintptr_t)fdtp + fdt_off_dt_struct(fdtp);
 
-	if (((const char *)p < dt_struct) ||
-	    (const char *)p > (dt_struct + fdt_size_dt_struct(fdtp)))
+	if ((p < dt_struct) ||
+	    p > (dt_struct + fdt_size_dt_struct(fdtp)))
 		return (-1);
 
-	offset = (const char *)p - dt_struct;
+	offset = p - dt_struct;
 	if (offset < 0)
 		return (-1);
 
@@ -135,15 +155,13 @@ fdt_phandle_offset(phandle_t p)
 static phandle_t
 ofw_fdt_peer(ofw_t ofw, phandle_t node)
 {
-	phandle_t p;
 	int depth, offset;
 
 	if (node == 0) {
 		/* Find root node */
 		offset = fdt_path_offset(fdtp, "/");
-		p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
 
-		return (p);
+		return (fdt_offset_phandle(offset));
 	}
 
 	offset = fdt_phandle_offset(node);
@@ -155,10 +173,8 @@ ofw_fdt_peer(ofw_t ofw, phandle_t node)
 	    offset = fdt_next_node(fdtp, offset, &depth)) {
 		if (depth < 0)
 			return (0);
-		if (depth == 1) {
-			p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
-			return (p);
-		}
+		if (depth == 1)
+			return (fdt_offset_phandle(offset));
 	}
 
 	return (0);
@@ -168,7 +184,6 @@ ofw_fdt_peer(ofw_t ofw, phandle_t node)
 static phandle_t
 ofw_fdt_child(ofw_t ofw, phandle_t node)
 {
-	phandle_t p;
 	int depth, offset;
 
 	offset = fdt_phandle_offset(node);
@@ -180,10 +195,8 @@ ofw_fdt_child(ofw_t ofw, phandle_t node)
 	    offset = fdt_next_node(fdtp, offset, &depth)) {
 		if (depth < 0)
 			return (0);
-		if (depth == 1) {
-			p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
-			return (p);
-		}
+		if (depth == 1)
+			return (fdt_offset_phandle(offset));
 	}
 
 	return (0);
@@ -193,7 +206,6 @@ ofw_fdt_child(ofw_t ofw, phandle_t node)
 static phandle_t
 ofw_fdt_parent(ofw_t ofw, phandle_t node)
 {
-	phandle_t p;
 	int offset, paroffset;
 
 	offset = fdt_phandle_offset(node);
@@ -201,15 +213,13 @@ ofw_fdt_parent(ofw_t ofw, phandle_t node)
 		return (0);
 
 	paroffset = fdt_parent_offset(fdtp, offset);
-	p = (phandle_t)fdt_offset_ptr(fdtp, paroffset, sizeof(phandle_t));
-	return (p);
+	return (fdt_offset_phandle(paroffset));
 }
 
 /* Return the package handle that corresponds to an instance handle. */
 static phandle_t
 ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance)
 {
-	phandle_t p;
 	int offset;
 
 	/*
@@ -223,8 +233,7 @@ ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance)
 	if (offset < 0)
 		return (-1);
 
-	p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(phandle_t));
-	return (p);
+	return (fdt_offset_phandle(offset));
 }
 
 /* Get the length of a property of a package. */
@@ -343,7 +352,7 @@ ofw_fdt_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf,
 	if (prop == NULL)
 		return (-1);
 
-	offset = fdt_phandle_offset((phandle_t)prop);
+	offset = fdt_pointer_offset(prop);
 	rv = fdt_nextprop(offset, buf, size);
 	return (rv);
 }
@@ -374,14 +383,10 @@ ofw_fdt_canon(ofw_t ofw, const char *device, char *buf, size_t len)
 static phandle_t
 ofw_fdt_finddevice(ofw_t ofw, const char *device)
 {
-	phandle_t p;
 	int offset;
 
 	offset = fdt_path_offset(fdtp, device);
-
-	p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
-
-	return (p);
+	return (fdt_offset_phandle(offset));
 }
 
 /* Return the fully qualified pathname corresponding to an instance. */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CA%2B7sy7AhU7WLuabx6HCtUgvEtUHWBmGe-eP=N8L9VknM65r-mg>