11ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass/*
21ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
31ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass *
41ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * This program is free software; you can redistribute it and/or
51ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * modify it under the terms of the GNU General Public License as
61ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * published by the Free Software Foundation; either version 2 of
71ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * the License, or (at your option) any later version.
81ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass *
91ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * This program is distributed in the hope that it will be useful,
101ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * but WITHOUT ANY WARRANTY; without even the implied warranty of
111ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
121ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * GNU General Public License for more details.
131ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass *
141ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * You should have received a copy of the GNU General Public License
151ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * along with this program; if not, write to the Free Software
161ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
171ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * MA 02111-1307 USA
181ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass */
191ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
201ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <assert.h>
211ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <ctype.h>
221ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <getopt.h>
231ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <stdio.h>
241ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <stdlib.h>
251ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <string.h>
261ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
271ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include <libfdt.h>
281ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
291ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass#include "util.h"
301ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
31f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass/* These are the operations we support */
32f58dff50407c0ee56b372ab201469c18dc042f56Simon Glassenum oper_type {
33f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	OPER_WRITE_PROP,		/* Write a property in a node */
34d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	OPER_CREATE_NODE,		/* Create a new node */
35aa719618a8b7c748be659717a9fd003bfa186017Wang Long	OPER_REMOVE_NODE,		/* Delete a node */
36aa719618a8b7c748be659717a9fd003bfa186017Wang Long	OPER_DELETE_PROP,		/* Delete a property in a node */
37f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass};
38f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass
391ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glassstruct display_info {
40f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	enum oper_type oper;	/* operation to perform */
411ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int type;		/* data type (s/i/u/x or 0 for default) */
421ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int size;		/* data size (1/2/4) */
431ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int verbose;		/* verbose output */
44f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	int auto_path;		/* automatically create all path components */
451ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass};
461ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
473553dfac224435233f2c0d33169194098e979c88Simon Glass
483553dfac224435233f2c0d33169194098e979c88Simon Glass/**
493553dfac224435233f2c0d33169194098e979c88Simon Glass * Report an error with a particular node.
503553dfac224435233f2c0d33169194098e979c88Simon Glass *
513553dfac224435233f2c0d33169194098e979c88Simon Glass * @param name		Node name to report error on
523553dfac224435233f2c0d33169194098e979c88Simon Glass * @param namelen	Length of node name, or -1 to use entire string
533553dfac224435233f2c0d33169194098e979c88Simon Glass * @param err		Error number to report (-FDT_ERR_...)
543553dfac224435233f2c0d33169194098e979c88Simon Glass */
553553dfac224435233f2c0d33169194098e979c88Simon Glassstatic void report_error(const char *name, int namelen, int err)
561ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass{
573553dfac224435233f2c0d33169194098e979c88Simon Glass	if (namelen == -1)
583553dfac224435233f2c0d33169194098e979c88Simon Glass		namelen = strlen(name);
593553dfac224435233f2c0d33169194098e979c88Simon Glass	fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
603553dfac224435233f2c0d33169194098e979c88Simon Glass		fdt_strerror(err));
611ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass}
621ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
631ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass/**
641ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * Encode a series of arguments in a property value.
651ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass *
661ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * @param disp		Display information / options
671ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * @param arg		List of arguments from command line
681ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * @param arg_count	Number of arguments (may be 0)
691ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass * @param valuep	Returns buffer containing value
70c17a811c62ebdcb3ad6e7b5c9a0e0f64d5d64d8bNicolas Iooss * @param value_len	Returns length of value encoded
711ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass */
721ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glassstatic int encode_value(struct display_info *disp, char **arg, int arg_count,
731ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			char **valuep, int *value_len)
741ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass{
751ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	char *value = NULL;	/* holding area for value */
761ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int value_size = 0;	/* size of holding area */
771ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	char *ptr;		/* pointer to current value position */
781ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int len;		/* length of this cell/string/byte */
791ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int ival;
801ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int upto;	/* the number of bytes we have written to buf */
811ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	char fmt[3];
821ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
831ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	upto = 0;
841ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
851ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (disp->verbose)
861ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		fprintf(stderr, "Decoding value:\n");
871ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
881ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	fmt[0] = '%';
891ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	fmt[1] = disp->type ? disp->type : 'd';
901ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	fmt[2] = '\0';
911ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	for (; arg_count > 0; arg++, arg_count--, upto += len) {
921ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		/* assume integer unless told otherwise */
931ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		if (disp->type == 's')
941ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			len = strlen(*arg) + 1;
951ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		else
961ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			len = disp->size == -1 ? 4 : disp->size;
971ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
981ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		/* enlarge our value buffer by a suitable margin if needed */
991ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		if (upto + len > value_size) {
1001ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			value_size = (upto + len) + 500;
1018ce36476ae8d2541e9bf3a6c23c345ec03694ee3Heinrich Schuchardt			value = xrealloc(value, value_size);
1021ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		}
1031ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
1041ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		ptr = value + upto;
1051ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		if (disp->type == 's') {
1061ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			memcpy(ptr, *arg, len);
1071ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			if (disp->verbose)
1081ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass				fprintf(stderr, "\tstring: '%s'\n", ptr);
1091ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		} else {
110bad5b28049e5e0562a8ad91797fb77953a53fa20David Gibson			fdt32_t *iptr = (fdt32_t *)ptr;
1111ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			sscanf(*arg, fmt, &ival);
1121ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			if (len == 4)
1131ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass				*iptr = cpu_to_fdt32(ival);
1141ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			else
1151ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass				*ptr = (uint8_t)ival;
1161ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			if (disp->verbose) {
1171ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass				fprintf(stderr, "\t%s: %d\n",
1181ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass					disp->size == 1 ? "byte" :
1191ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass					disp->size == 2 ? "short" : "int",
1201ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass					ival);
1211ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			}
1221ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		}
1231ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	}
1241ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	*value_len = upto;
1251ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	*valuep = value;
1261ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (disp->verbose)
1271ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		fprintf(stderr, "Value size %d\n", upto);
1281ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	return 0;
1291ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass}
1301ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
131d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla#define ALIGN(x)		(((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
132d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
133d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatlastatic char *_realloc_fdt(char *fdt, int delta)
134d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla{
135d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	int new_sz = fdt_totalsize(fdt) + delta;
136d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	fdt = xrealloc(fdt, new_sz);
137d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	fdt_open_into(fdt, fdt, new_sz);
138d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	return fdt;
139d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla}
140d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
141d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatlastatic char *realloc_node(char *fdt, const char *name)
142d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla{
143d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	int delta;
144d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
145d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
146d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla			+ FDT_TAGSIZE;
147d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	return _realloc_fdt(fdt, delta);
148d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla}
149d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
150d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatlastatic char *realloc_property(char *fdt, int nodeoffset,
151d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		const char *name, int newlen)
152d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla{
153d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	int delta = 0;
154d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	int oldlen = 0;
155d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
156d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	if (!fdt_get_property(fdt, nodeoffset, name, &oldlen))
157d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		/* strings + property header */
158d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		delta = sizeof(struct fdt_property) + strlen(name) + 1;
159d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
160d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	if (newlen > oldlen)
161d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		/* actual value in off_struct */
162d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		delta += ALIGN(newlen) - ALIGN(oldlen);
163d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
164d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	return _realloc_fdt(fdt, delta);
165d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla}
166d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
167d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatlastatic int store_key_value(char **blob, const char *node_name,
1681ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		const char *property, const char *buf, int len)
1691ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass{
1701ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int node;
1711ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int err;
1721ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
173d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	node = fdt_path_offset(*blob, node_name);
1741ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (node < 0) {
1753553dfac224435233f2c0d33169194098e979c88Simon Glass		report_error(node_name, -1, node);
1761ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		return -1;
1771ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	}
1781ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
179d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	err = fdt_setprop(*blob, node, property, buf, len);
180d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	if (err == -FDT_ERR_NOSPACE) {
181d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		*blob = realloc_property(*blob, node, property, len);
182d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		err = fdt_setprop(*blob, node, property, buf, len);
183d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	}
1841ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (err) {
1853553dfac224435233f2c0d33169194098e979c88Simon Glass		report_error(property, -1, err);
1861ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		return -1;
1871ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	}
1881ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	return 0;
1891ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass}
1901ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
191d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass/**
192f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass * Create paths as needed for all components of a path
193f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass *
194f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass * Any components of the path that do not exist are created. Errors are
195f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass * reported.
196f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass *
197f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass * @param blob		FDT blob to write into
198f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass * @param in_path	Path to process
199f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass * @return 0 if ok, -1 on error
200f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass */
201d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatlastatic int create_paths(char **blob, const char *in_path)
202f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass{
203f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	const char *path = in_path;
204f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	const char *sep;
205f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	int node, offset = 0;
206f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass
207f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	/* skip leading '/' */
208f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	while (*path == '/')
209f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		path++;
210f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass
211f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	for (sep = path; *sep; path = sep + 1, offset = node) {
212f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		/* equivalent to strchrnul(), but it requires _GNU_SOURCE */
213f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		sep = strchr(path, '/');
214f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		if (!sep)
215f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			sep = path + strlen(path);
216f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass
217d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		node = fdt_subnode_offset_namelen(*blob, offset, path,
218f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass				sep - path);
219f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		if (node == -FDT_ERR_NOTFOUND) {
220d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla			*blob = realloc_node(*blob, path);
221d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla			node = fdt_add_subnode_namelen(*blob, offset, path,
222f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass						       sep - path);
223f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		}
224f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		if (node < 0) {
225f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			report_error(path, sep - path, node);
226f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			return -1;
227f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		}
228f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	}
229f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass
230f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass	return 0;
231f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass}
232f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass
233f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass/**
234d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass * Create a new node in the fdt.
235d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass *
236d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass * This will overwrite the node_name string. Any error is reported.
237d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass *
238d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
239d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass *
240d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass * @param blob		FDT blob to write into
241d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass * @param node_name	Name of node to create
242d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass * @return new node offset if found, or -1 on failure
243d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass */
244d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatlastatic int create_node(char **blob, const char *node_name)
245d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass{
246d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	int node = 0;
247d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	char *p;
248d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass
249d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	p = strrchr(node_name, '/');
250d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	if (!p) {
2513553dfac224435233f2c0d33169194098e979c88Simon Glass		report_error(node_name, -1, -FDT_ERR_BADPATH);
252d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass		return -1;
253d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	}
254d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	*p = '\0';
255d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass
256d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	*blob = realloc_node(*blob, p + 1);
257d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla
258d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	if (p > node_name) {
259d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		node = fdt_path_offset(*blob, node_name);
260d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass		if (node < 0) {
2613553dfac224435233f2c0d33169194098e979c88Simon Glass			report_error(node_name, -1, node);
262d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass			return -1;
263d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass		}
264d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	}
265d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass
266d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	node = fdt_add_subnode(*blob, node, p + 1);
267d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	if (node < 0) {
2683553dfac224435233f2c0d33169194098e979c88Simon Glass		report_error(p + 1, -1, node);
269d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass		return -1;
270d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	}
271d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass
272d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	return 0;
273d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass}
274d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass
275aa719618a8b7c748be659717a9fd003bfa186017Wang Long/**
276aa719618a8b7c748be659717a9fd003bfa186017Wang Long * Delete a property of a node in the fdt.
277aa719618a8b7c748be659717a9fd003bfa186017Wang Long *
278aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @param blob		FDT blob to write into
279aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @param node_name	Path to node containing the property to delete
280aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @param prop_name	Name of property to delete
281aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @return 0 on success, or -1 on failure
282aa719618a8b7c748be659717a9fd003bfa186017Wang Long */
283aa719618a8b7c748be659717a9fd003bfa186017Wang Longstatic int delete_prop(char *blob, const char *node_name, const char *prop_name)
284aa719618a8b7c748be659717a9fd003bfa186017Wang Long{
285aa719618a8b7c748be659717a9fd003bfa186017Wang Long	int node = 0;
286aa719618a8b7c748be659717a9fd003bfa186017Wang Long
287aa719618a8b7c748be659717a9fd003bfa186017Wang Long	node = fdt_path_offset(blob, node_name);
288aa719618a8b7c748be659717a9fd003bfa186017Wang Long	if (node < 0) {
289aa719618a8b7c748be659717a9fd003bfa186017Wang Long		report_error(node_name, -1, node);
290aa719618a8b7c748be659717a9fd003bfa186017Wang Long		return -1;
291aa719618a8b7c748be659717a9fd003bfa186017Wang Long	}
292aa719618a8b7c748be659717a9fd003bfa186017Wang Long
293aa719618a8b7c748be659717a9fd003bfa186017Wang Long	node = fdt_delprop(blob, node, prop_name);
294aa719618a8b7c748be659717a9fd003bfa186017Wang Long	if (node < 0) {
295aa719618a8b7c748be659717a9fd003bfa186017Wang Long		report_error(node_name, -1, node);
296aa719618a8b7c748be659717a9fd003bfa186017Wang Long		return -1;
297aa719618a8b7c748be659717a9fd003bfa186017Wang Long	}
298aa719618a8b7c748be659717a9fd003bfa186017Wang Long
299aa719618a8b7c748be659717a9fd003bfa186017Wang Long	return 0;
300aa719618a8b7c748be659717a9fd003bfa186017Wang Long}
301aa719618a8b7c748be659717a9fd003bfa186017Wang Long
302aa719618a8b7c748be659717a9fd003bfa186017Wang Long/**
303aa719618a8b7c748be659717a9fd003bfa186017Wang Long * Delete a node in the fdt.
304aa719618a8b7c748be659717a9fd003bfa186017Wang Long *
305aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @param blob		FDT blob to write into
306aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @param node_name	Name of node to delete
307aa719618a8b7c748be659717a9fd003bfa186017Wang Long * @return 0 on success, or -1 on failure
308aa719618a8b7c748be659717a9fd003bfa186017Wang Long */
309aa719618a8b7c748be659717a9fd003bfa186017Wang Longstatic int delete_node(char *blob, const char *node_name)
310aa719618a8b7c748be659717a9fd003bfa186017Wang Long{
311aa719618a8b7c748be659717a9fd003bfa186017Wang Long	int node = 0;
312aa719618a8b7c748be659717a9fd003bfa186017Wang Long
313aa719618a8b7c748be659717a9fd003bfa186017Wang Long	node = fdt_path_offset(blob, node_name);
314aa719618a8b7c748be659717a9fd003bfa186017Wang Long	if (node < 0) {
315aa719618a8b7c748be659717a9fd003bfa186017Wang Long		report_error(node_name, -1, node);
316aa719618a8b7c748be659717a9fd003bfa186017Wang Long		return -1;
317aa719618a8b7c748be659717a9fd003bfa186017Wang Long	}
318aa719618a8b7c748be659717a9fd003bfa186017Wang Long
319aa719618a8b7c748be659717a9fd003bfa186017Wang Long	node = fdt_del_node(blob, node);
320aa719618a8b7c748be659717a9fd003bfa186017Wang Long	if (node < 0) {
321aa719618a8b7c748be659717a9fd003bfa186017Wang Long		report_error(node_name, -1, node);
322aa719618a8b7c748be659717a9fd003bfa186017Wang Long		return -1;
323aa719618a8b7c748be659717a9fd003bfa186017Wang Long	}
324aa719618a8b7c748be659717a9fd003bfa186017Wang Long
325aa719618a8b7c748be659717a9fd003bfa186017Wang Long	return 0;
326aa719618a8b7c748be659717a9fd003bfa186017Wang Long}
327aa719618a8b7c748be659717a9fd003bfa186017Wang Long
3281ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glassstatic int do_fdtput(struct display_info *disp, const char *filename,
3291ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		    char **arg, int arg_count)
3301ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass{
331c539075ba8ba61fffbf7e005ce2e834868a9e0abJean-Christophe Dubois	char *value = NULL;
3321ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	char *blob;
333aa719618a8b7c748be659717a9fd003bfa186017Wang Long	char *node;
3341ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	int len, ret = 0;
3351ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
3365543b88d5e3047b781552eb431bc2e3bdd9ade06Jon Loeliger	blob = utilfdt_read(filename);
3371ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (!blob)
3381ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		return -1;
3391ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
340f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	switch (disp->oper) {
341f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	case OPER_WRITE_PROP:
342f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		/*
343f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		 * Convert the arguments into a single binary value, then
344f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		 * store them into the property.
345f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		 */
346f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		assert(arg_count >= 2);
347d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		if (disp->auto_path && create_paths(&blob, *arg))
348f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			return -1;
349f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
350d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla			store_key_value(&blob, *arg, arg[1], value, len))
351f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass			ret = -1;
352f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		break;
353d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	case OPER_CREATE_NODE:
354f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		for (; ret >= 0 && arg_count--; arg++) {
355f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			if (disp->auto_path)
356d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla				ret = create_paths(&blob, *arg);
357f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			else
358d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla				ret = create_node(&blob, *arg);
359f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		}
360d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass		break;
361aa719618a8b7c748be659717a9fd003bfa186017Wang Long	case OPER_REMOVE_NODE:
362aa719618a8b7c748be659717a9fd003bfa186017Wang Long		for (; ret >= 0 && arg_count--; arg++)
363aa719618a8b7c748be659717a9fd003bfa186017Wang Long			ret = delete_node(blob, *arg);
364aa719618a8b7c748be659717a9fd003bfa186017Wang Long		break;
365aa719618a8b7c748be659717a9fd003bfa186017Wang Long	case OPER_DELETE_PROP:
366aa719618a8b7c748be659717a9fd003bfa186017Wang Long		node = *arg;
367aa719618a8b7c748be659717a9fd003bfa186017Wang Long		for (arg++; ret >= 0 && arg_count-- > 1; arg++)
368aa719618a8b7c748be659717a9fd003bfa186017Wang Long			ret = delete_prop(blob, node, *arg);
369aa719618a8b7c748be659717a9fd003bfa186017Wang Long		break;
370f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	}
371d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	if (ret >= 0) {
372d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla		fdt_pack(blob);
3731ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		ret = utilfdt_write(filename, blob);
374d214655904b49938dafcb83797de3f6a0dc725c8Srinivas Kandagatla	}
3751ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
3761ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	free(blob);
377c539075ba8ba61fffbf7e005ce2e834868a9e0abJean-Christophe Dubois
378c539075ba8ba61fffbf7e005ce2e834868a9e0abJean-Christophe Dubois	if (value) {
379c539075ba8ba61fffbf7e005ce2e834868a9e0abJean-Christophe Dubois		free(value);
380c539075ba8ba61fffbf7e005ce2e834868a9e0abJean-Christophe Dubois	}
381c539075ba8ba61fffbf7e005ce2e834868a9e0abJean-Christophe Dubois
3821ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	return ret;
3831ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass}
3841ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
38503449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger/* Usage related data. */
38603449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic const char usage_synopsis[] =
38703449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"write a property value to a device tree\n"
388bb21f0a766056114e4d9336324b4c294f640d9d1Simon Glass	"	fdtput <options> <dt file> <node> <property> [<value>...]\n"
389d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass	"	fdtput -c <options> <dt file> [<node>...]\n"
390aa719618a8b7c748be659717a9fd003bfa186017Wang Long	"	fdtput -r <options> <dt file> [<node>...]\n"
391aa719618a8b7c748be659717a9fd003bfa186017Wang Long	"	fdtput -d <options> <dt file> <node> [<property>...]\n"
39203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"\n"
39303449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"The command line arguments are joined together into a single value.\n"
3941ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	USAGE_TYPE_MSG;
395aa719618a8b7c748be659717a9fd003bfa186017Wang Longstatic const char usage_short_opts[] = "crdpt:v" USAGE_COMMON_SHORT_OPTS;
39603449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic struct option const usage_long_opts[] = {
39703449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"create",           no_argument, NULL, 'c'},
398aa719618a8b7c748be659717a9fd003bfa186017Wang Long	{"remove",	     no_argument, NULL, 'r'},
399aa719618a8b7c748be659717a9fd003bfa186017Wang Long	{"delete",	     no_argument, NULL, 'd'},
40003449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"auto-path",        no_argument, NULL, 'p'},
40103449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"type",              a_argument, NULL, 't'},
40203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	{"verbose",          no_argument, NULL, 'v'},
40303449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	USAGE_COMMON_LONG_OPTS,
40403449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger};
40503449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysingerstatic const char * const usage_opts_help[] = {
40603449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Create nodes if they don't already exist",
407aa719618a8b7c748be659717a9fd003bfa186017Wang Long	"Delete nodes (and any subnodes) if they already exist",
408aa719618a8b7c748be659717a9fd003bfa186017Wang Long	"Delete properties if they already exist",
40903449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Automatically create nodes as needed for the node path",
41003449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Type of data",
41103449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	"Display each value decoded from command line",
41203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	USAGE_COMMON_OPTS_HELP
41303449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger};
4141ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
4151ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glassint main(int argc, char *argv[])
4161ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass{
41703449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	int opt;
4181ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	struct display_info disp;
4191ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	char *filename = NULL;
4201ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
4211ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	memset(&disp, '\0', sizeof(disp));
4221ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	disp.size = -1;
423f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	disp.oper = OPER_WRITE_PROP;
42403449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger	while ((opt = util_getopt_long()) != EOF) {
4251ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		/*
4261ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		 * TODO: add options to:
4271ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		 * - rename node
4281ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		 * - pack fdt before writing
4291ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		 * - set amount of free space when writing
4301ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		 */
43103449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger		switch (opt) {
43203449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger		case_USAGE_COMMON_FLAGS
43303449b84c8f9aee2bf2f438bec2c2ec4606bea48Mike Frysinger
434d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass		case 'c':
435d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass			disp.oper = OPER_CREATE_NODE;
436d46c2de5700fd8d43de67ca3709c276beba39b39Simon Glass			break;
437aa719618a8b7c748be659717a9fd003bfa186017Wang Long		case 'r':
438aa719618a8b7c748be659717a9fd003bfa186017Wang Long			disp.oper = OPER_REMOVE_NODE;
439aa719618a8b7c748be659717a9fd003bfa186017Wang Long			break;
440aa719618a8b7c748be659717a9fd003bfa186017Wang Long		case 'd':
441aa719618a8b7c748be659717a9fd003bfa186017Wang Long			disp.oper = OPER_DELETE_PROP;
442aa719618a8b7c748be659717a9fd003bfa186017Wang Long			break;
443f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass		case 'p':
444f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			disp.auto_path = 1;
445f807af192828222dee7a5c9f94d999673bb4d8a1Simon Glass			break;
4461ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		case 't':
4471ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			if (utilfdt_decode_type(optarg, &disp.type,
4481ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass					&disp.size))
449b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger				usage("Invalid type string");
4501ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			break;
4511ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
4521ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		case 'v':
4531ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			disp.verbose = 1;
4541ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass			break;
4551ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		}
4561ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	}
4571ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
4581ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (optind < argc)
4591ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		filename = argv[optind++];
4601ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (!filename)
461b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger		usage("missing filename");
4621ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
4631ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	argv += optind;
4641ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	argc -= optind;
4651ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
466f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	if (disp.oper == OPER_WRITE_PROP) {
467f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		if (argc < 1)
468b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger			usage("missing node");
469f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass		if (argc < 2)
470b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3Mike Frysinger			usage("missing property");
471f58dff50407c0ee56b372ab201469c18dc042f56Simon Glass	}
4721ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass
473aa719618a8b7c748be659717a9fd003bfa186017Wang Long	if (disp.oper == OPER_DELETE_PROP)
474aa719618a8b7c748be659717a9fd003bfa186017Wang Long		if (argc < 1)
475aa719618a8b7c748be659717a9fd003bfa186017Wang Long			usage("missing node");
476aa719618a8b7c748be659717a9fd003bfa186017Wang Long
4771ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	if (do_fdtput(&disp, filename, argv, argc))
4781ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass		return 1;
4791ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass	return 0;
4801ede50c3559bbfca79fadcbfd8acb9388f4aac87Simon Glass}
481