fdtput: Add -p option to create subnodes along entire path
This option mimics mkdir's -p option. It automatically creates nodes as needed along the path provided. If the node already exists, no error is given. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
3553dfac22
commit
f807af1928
2 changed files with 68 additions and 4 deletions
59
fdtput.c
59
fdtput.c
|
@ -39,6 +39,7 @@ struct display_info {
|
|||
int type; /* data type (s/i/u/x or 0 for default) */
|
||||
int size; /* data size (1/2/4) */
|
||||
int verbose; /* verbose output */
|
||||
int auto_path; /* automatically create all path components */
|
||||
};
|
||||
|
||||
|
||||
|
@ -150,6 +151,47 @@ static int store_key_value(void *blob, const char *node_name,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create paths as needed for all components of a path
|
||||
*
|
||||
* Any components of the path that do not exist are created. Errors are
|
||||
* reported.
|
||||
*
|
||||
* @param blob FDT blob to write into
|
||||
* @param in_path Path to process
|
||||
* @return 0 if ok, -1 on error
|
||||
*/
|
||||
static int create_paths(void *blob, const char *in_path)
|
||||
{
|
||||
const char *path = in_path;
|
||||
const char *sep;
|
||||
int node, offset = 0;
|
||||
|
||||
/* skip leading '/' */
|
||||
while (*path == '/')
|
||||
path++;
|
||||
|
||||
for (sep = path; *sep; path = sep + 1, offset = node) {
|
||||
/* equivalent to strchrnul(), but it requires _GNU_SOURCE */
|
||||
sep = strchr(path, '/');
|
||||
if (!sep)
|
||||
sep = path + strlen(path);
|
||||
|
||||
node = fdt_subnode_offset_namelen(blob, offset, path,
|
||||
sep - path);
|
||||
if (node == -FDT_ERR_NOTFOUND) {
|
||||
node = fdt_add_subnode_namelen(blob, offset, path,
|
||||
sep - path);
|
||||
}
|
||||
if (node < 0) {
|
||||
report_error(path, sep - path, node);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node in the fdt.
|
||||
*
|
||||
|
@ -208,13 +250,19 @@ static int do_fdtput(struct display_info *disp, const char *filename,
|
|||
* store them into the property.
|
||||
*/
|
||||
assert(arg_count >= 2);
|
||||
if (disp->auto_path && create_paths(blob, *arg))
|
||||
return -1;
|
||||
if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
|
||||
store_key_value(blob, *arg, arg[1], value, len))
|
||||
ret = -1;
|
||||
break;
|
||||
case OPER_CREATE_NODE:
|
||||
for (; ret >= 0 && arg_count--; arg++)
|
||||
ret = create_node(blob, *arg);
|
||||
for (; ret >= 0 && arg_count--; arg++) {
|
||||
if (disp->auto_path)
|
||||
ret = create_paths(blob, *arg);
|
||||
else
|
||||
ret = create_node(blob, *arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ret >= 0)
|
||||
|
@ -234,6 +282,7 @@ static const char *usage_msg =
|
|||
" fdtput -c <options> <dt file> [<node>...]\n"
|
||||
"Options:\n"
|
||||
"\t-c\t\tCreate nodes if they don't already exist\n"
|
||||
"\t-p\t\tAutomatically create nodes as needed for the node path\n"
|
||||
"\t-t <type>\tType of data\n"
|
||||
"\t-v\t\tVerbose: display each value decoded from command line\n"
|
||||
"\t-h\t\tPrint this help\n\n"
|
||||
|
@ -257,7 +306,7 @@ int main(int argc, char *argv[])
|
|||
disp.size = -1;
|
||||
disp.oper = OPER_WRITE_PROP;
|
||||
for (;;) {
|
||||
int c = getopt(argc, argv, "cht:v");
|
||||
int c = getopt(argc, argv, "chpt:v");
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
@ -277,7 +326,9 @@ int main(int argc, char *argv[])
|
|||
case 'h':
|
||||
case '?':
|
||||
usage(NULL);
|
||||
|
||||
case 'p':
|
||||
disp.auto_path = 1;
|
||||
break;
|
||||
case 't':
|
||||
if (utilfdt_decode_type(optarg, &disp.type,
|
||||
&disp.size))
|
||||
|
|
|
@ -549,6 +549,19 @@ fdtput_tests () {
|
|||
run_wrap_error_test $DTPUT $dtb -c /chosen
|
||||
run_wrap_error_test $DTPUT $dtb -c /chosen/son
|
||||
|
||||
# Automatic node creation
|
||||
run_wrap_test $DTPUT $dtb -cp /blackadder/the-second/turnip \
|
||||
/blackadder/the-second/potato
|
||||
run_fdtput_test 1000 $dtb /blackadder/the-second/turnip cost "" 1000
|
||||
run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \
|
||||
"-ts" "fine wine"
|
||||
run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice
|
||||
run_wrap_error_test $DTPUT $dtb -cp "$(cat $text $text)/longish"
|
||||
|
||||
# Allowed to create an existing node with -p
|
||||
run_wrap_test $DTPUT $dtb -cp /chosen
|
||||
run_wrap_test $DTPUT $dtb -cp /chosen/son
|
||||
|
||||
# TODO: Add tests for verbose mode?
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue