All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
To: Devicetree Compiler
	<devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: Jason Clinton <jclinton-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
	David Gibson
	<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>,
	Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Subject: [PATCH 2/2] fdtget: Support following phandles
Date: Sun, 20 Aug 2017 06:28:55 -0600	[thread overview]
Message-ID: <20170820122855.171271-2-sjg@chromium.org> (raw)
In-Reply-To: <20170820122855.171271-1-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

Currently nodes with phandles just print out as plain integer values, e.g.

   $ fdtget firefly-rk3288/u-boot.dtb /gpio-keys/button@0 gpios
   112 5 1

It is useful to be able to follow these phandles and print them out in a
properly formatted way, e.g.

   $ fdtget firefly-rk3288/u-boot.dtb -f -c gpio /gpio-keys/button@0 gpios
   /pinctrl/gpio0@ff750000 5 1

Add a -f option to follow phandles. For those which require arguments, add
a -c option to specify the name of the '#xxx-cells' property in the target
node.

Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---

 fdtget.c           | 115 +++++++++++++++++++++++++++++++++++++++++++++++++----
 tests/label01.dts  |  30 ++++++++++++++
 tests/run_tests.sh |  18 +++++++++
 3 files changed, 156 insertions(+), 7 deletions(-)

diff --git a/fdtget.c b/fdtget.c
index 6cc5242..6d7c6af 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -46,6 +46,10 @@ struct display_info {
 	int size;		/* data size (1/2/4) */
 	enum display_mode mode;	/* display mode that we are using */
 	const char *default_val; /* default value if node/property not found */
+
+	int follow;		/* follow phandle links */
+	/* property which defines the number of parameter cells for a phandle */
+	char *phandle_cells;
 };
 
 static void report_error(const char *where, int err)
@@ -53,6 +57,59 @@ static void report_error(const char *where, int err)
 	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
 }
 
+/**
+ * Shows the target node of a phandle
+ *
+ * @param disp		Display information / options
+ * @param value		Phandle value to look up
+ * @param blob		Device tree blob (for looking up phandles)
+ * @return number of arguments expected, or -1 on error
+ */
+static int show_phandle_target(struct display_info *disp, int value,
+			       const char *blob)
+{
+	const void *cells_prop;
+	int phandle_args = 0;
+	int cells_size;
+	char buf[256];
+	int target;
+	int ret;
+
+	target = fdt_node_offset_by_phandle(blob, value);
+	if (target < 0) {
+		printf("invalid_%d", value);
+		return -1;
+	}
+
+	if (disp->phandle_cells) {
+		cells_prop = fdt_getprop(blob, target, disp->phandle_cells,
+					 &cells_size);
+		if (!cells_prop) {
+			fprintf(stderr, "Expected node '%s' to have property "
+				"'%s' but it is missing\n",
+				fdt_get_name(blob, target, NULL),
+				disp->phandle_cells);
+			return -1;
+		}
+		if (cells_size != 4) {
+			fprintf(stderr, "Expected node '%s' property '%s' size "
+				"to be 4, but it is %d\n",
+				fdt_get_name(blob, target, NULL),
+				disp->phandle_cells, cells_size);
+			return -1;
+		}
+		phandle_args = fdt32_to_cpu(*(const fdt32_t *)cells_prop);
+	}
+	ret = fdt_get_path(blob, target, buf, sizeof(buf));
+	if (ret < 0) {
+		report_error("Could not get full path", ret);
+		return -1;
+	}
+	printf("%s", buf);
+
+	return phandle_args;
+}
+
 /**
  * Shows a list of cells in the requested format
  *
@@ -60,12 +117,15 @@ static void report_error(const char *where, int err)
  * @param data		Data to display
  * @param len		Maximum length of buffer
  * @param size		Data size to use for display (e.g. 4 for 32-bit)
+ * @param blob		Device tree blob (for looking up phandles)
  * @return 0 if ok, -1 on error
  */
 static int show_cell_list(struct display_info *disp, const char *data, int len,
-			  int size)
+			  int size, const void *blob)
 {
 	const uint8_t *p = (const uint8_t *)data;
+	int phandle_start = 0; /* expecting a phandle pointer next */
+	int phandle_args = 0; /* numnber of phandle args left to process */
 	char fmt[3];
 	int value;
 	int i;
@@ -73,12 +133,33 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
 	fmt[0] = '%';
 	fmt[1] = disp->type ? disp->type : 'd';
 	fmt[2] = '\0';
+	if (disp->follow) {
+		if (size != 4) {
+			fprintf(stderr, "Following phandles requires an output "
+				"size of 4 bytes\n");
+			return -1;
+		}
+		phandle_start = 1;
+	}
 	for (i = 0; i < len; i += size, p += size) {
 		if (i)
 			printf(" ");
 		value = size == 4 ? fdt32_to_cpu(*(const fdt32_t *)p) :
 			size == 2 ? (*p << 8) | p[1] : *p;
-		printf(fmt, value);
+		if (phandle_start && phandle_args <= 0) {
+			phandle_args = show_phandle_target(disp, value, blob);
+			if (phandle_args < 0)
+				return phandle_args;
+		} else {
+			printf(fmt, value);
+			if (phandle_args > 0)
+				phandle_args--;
+		}
+	}
+	if (phandle_args > 0) {
+		fprintf(stderr, "Not enough data: %d more arg(s) expected",
+			phandle_args);
+		return -1;
 	}
 
 	return 0;
@@ -93,9 +174,11 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
  * @param disp		Display information / options
  * @param data		Data to display
  * @param len		Maximum length of buffer
- * @return 0 if ok, -1 if data does not match format
+ * @param blob		Device tree blob (for looking up phandles)
+ * @return 0 if ok, -1 on error
  */
-static int show_data(struct display_info *disp, const char *data, int len)
+static int show_data(struct display_info *disp, const char *data, int len,
+		     const void *blob)
 {
 	int size;
 	const char *s;
@@ -128,7 +211,7 @@ static int show_data(struct display_info *disp, const char *data, int len)
 		return -1;
 	}
 
-	return show_cell_list(disp, data, len, size);
+	return show_cell_list(disp, data, len, size, blob);
 }
 
 /**
@@ -241,7 +324,7 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
 		assert(property);
 		value = fdt_getprop(blob, node, property, &len);
 		if (value) {
-			if (show_data(disp, value, len))
+			if (show_data(disp, value, len, blob))
 				err = -1;
 			else
 				printf("\n");
@@ -310,12 +393,14 @@ static const char usage_synopsis[] =
 	"\n"
 	"Each value is printed on a new line.\n"
 	USAGE_TYPE_MSG;
-static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
+static const char usage_short_opts[] = "t:pld:fc:" USAGE_COMMON_SHORT_OPTS;
 static struct option const usage_long_opts[] = {
 	{"type",              a_argument, NULL, 't'},
 	{"properties",       no_argument, NULL, 'p'},
 	{"list",             no_argument, NULL, 'l'},
 	{"default",           a_argument, NULL, 'd'},
+	{"follow",           no_argument, NULL, 'f'},
+	{"cells",             a_argument, NULL, 'c'},
 	USAGE_COMMON_LONG_OPTS,
 };
 static const char * const usage_opts_help[] = {
@@ -323,6 +408,8 @@ static const char * const usage_opts_help[] = {
 	"List properties for each node",
 	"List subnodes for each node",
 	"Default value to display when the property is missing",
+	"Print phandle targets and (with -c) args",
+	"Cells property in phandle target (e.g. 'gpio' for '#gpio-cells') ",
 	USAGE_COMMON_OPTS_HELP
 };
 
@@ -360,6 +447,20 @@ int main(int argc, char *argv[])
 		case 'd':
 			disp.default_val = optarg;
 			break;
+
+		case 'f':
+			disp.follow = 1;
+			break;
+
+		case 'c':
+			disp.phandle_cells = malloc(strlen(optarg) +
+						    strlen("#-cells"));
+			if (!disp.phandle_cells) {
+				fprintf(stderr, "Out of memory\n");
+				return 1;
+			}
+			sprintf(disp.phandle_cells, "#%s-cells", optarg);
+			break;
 		}
 	}
 
diff --git a/tests/label01.dts b/tests/label01.dts
index a895803..020e27d 100644
--- a/tests/label01.dts
+++ b/tests/label01.dts
@@ -59,5 +59,35 @@ memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000;
 		linux,platform = <0x600>;
 	};
 
+	phandle-test {
+		first = <&target_a 10 20>;
+		both = <&target_a 30 40 &target_b 50 &target_a 60 70>;
+		third = <&target_c &target_c>;
+		all = <&target_a 30 40 &target_b 50 &target_c &target_a 60 70>;
+		too-few-args = <&target_a 80>;
+		invalid-size = [01];
+		invalid-target = <&target_d>;
+	};
+
+	target_a: target@0 {
+		reg = <0 0 0 0>;
+		#gpio-cells = <2>;
+	};
+
+	target_b: target@1 {
+		reg = <1 0 0 0>;
+		#gpio-cells = <1>;
+	};
+
+	target_c: target@2 {
+		reg = <2 0 0 0>;
+		#gpio-cells = <0>;
+	};
+
+	target_d: target@3 {
+		reg = <3 0 0 0>;
+		#gpio-cells = [01];	/* invalid cell value */
+	};
+
 };
 
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 3bc5b41..6272675 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -692,6 +692,24 @@ fdtget_tests () {
     run_fdtget_test "<the dead silence>" -tx \
 	-d "<the dead silence>" $dtb /randomnode doctor-who
     run_fdtget_test "<blink>" -tx -d "<blink>" $dtb /memory doctor-who
+
+    # Test following of phandles
+    run_fdtget_test "/target@0 10 20" -f -c "gpio" $dtb /phandle-test first
+    run_fdtget_test "/target@0 30 40 /target@1 50 /target@0 60 70" \
+	-f -c "gpio" $dtb /phandle-test both
+    run_fdtget_test "/target@2 /target@2" -f -c "gpio" $dtb /phandle-test third
+    run_fdtget_test "/target@0 30 40 /target@1 50 /target@2 /target@0 60 70" \
+	-f -c "gpio" $dtb /phandle-test all
+
+    # Without the -c parameter we cannot decode some phandles.
+    run_wrap_error_test $DTGET -f $dtb /phandle-test first
+    run_wrap_error_test $DTGET -f $dtb /phandle-test both
+    run_wrap_error_test $DTGET -f $dtb /phandle-test all
+    run_wrap_error_test $DTGET -f -c wrong $dtb /phandle-test all
+
+    run_wrap_error_test $DTGET -f -c gpio $dtb /phandle-test too-few-args
+    run_wrap_error_test $DTGET -f -c gpio $dtb /phandle-test invalid-size
+    run_wrap_error_test $DTGET -f -c gpio $dtb /phandle-test invalid-target
 }
 
 fdtput_tests () {
-- 
2.14.1.480.gb18f417b89-goog

  parent reply	other threads:[~2017-08-20 12:28 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-20 12:28 [PATCH 1/2] fdtget: Split out cell list display into a new function Simon Glass
     [not found] ` <20170820122855.171271-1-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2017-08-20 12:28   ` Simon Glass [this message]
     [not found]     ` <20170820122855.171271-2-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2017-08-23  5:47       ` [PATCH 2/2] fdtget: Support following phandles David Gibson
2017-08-21  0:29   ` [PATCH 1/2] fdtget: Split out cell list display into a new function David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170820122855.171271-2-sjg@chromium.org \
    --to=sjg-f7+t8e8rja9g9huczpvpmw@public.gmane.org \
    --cc=david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org \
    --cc=devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=jclinton-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.