Skip to content

Commit

Permalink
Add fdt dup which allows to duplicate and append at the end
Browse files Browse the repository at this point in the history
  • Loading branch information
ayufan authored and longsleep committed May 6, 2017
1 parent a8beba9 commit b4a5d35
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 4 deletions.
142 changes: 142 additions & 0 deletions common/cmd_fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int fdt_valid(struct fdt_header **blobp);
static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
static int fdt_print(const char *pathp, char *prop, int depth);
static int fdt_dup(const char *pathp, char *old_prop, char *new_prop);
static int is_printable_string(const void *data, int len);

extern int sunxi_flash_update_fdt(void* fdt_buf, size_t size);
Expand Down Expand Up @@ -434,6 +435,26 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (ret != 0)
return ret;

/*
* Duplicate node
*/
} else if ((argv[1][0] == 'd')) {
char *pathp; /* path */
char *old_prop; /* property */
char *new_prop; /* property */
int ret; /* return value */

if (argc < 5)
return CMD_RET_USAGE;

pathp = argv[2];
old_prop = argv[3];
new_prop = argv[4];

ret = fdt_dup(pathp, old_prop, new_prop);
if (ret != 0)
return ret;

/*
* Remove a property/node
*/
Expand Down Expand Up @@ -1013,6 +1034,126 @@ static int fdt_print(const char *pathp, char *prop, int depth)
return 0;
}

static int fdt_dup(const char *pathp, char *old_prop, char *new_prop)
{
static char tabs[MAX_LEVEL+2] =
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
const void *nodep; /* property node pointer */
int parentoffset;
int nodeoffset; /* node offset from libfdt */
int nextoffset; /* next node offset from libfdt */
uint32_t tag; /* tag */
int len; /* length of the property */
int level = 0; /* keep track of nesting level */
int ret;
const struct fdt_property *fdt_prop;
int newoffset[MAX_LEVEL];

printf("[FDT] duplicating %s of %s to %s...\n", old_prop, pathp, new_prop);

parentoffset = fdt_path_offset (working_fdt, pathp);
if (parentoffset < 0) {
printf ("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(parentoffset));
return 1;
}

nodeoffset = fdt_subnode_offset (working_fdt, parentoffset, old_prop);
if (nodeoffset < 0) {
printf ("libfdt fdt_subnode_offset() returned %s\n",
fdt_strerror(nodeoffset));
return 1;
}

newoffset[level] = parentoffset;

/*
* The user passed in a node path and no property,
* print the node and all subnodes.
*/
while(level >= 0) {
tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
switch(tag) {
case FDT_BEGIN_NODE:
pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
if (pathp == NULL)
pathp = "/* NULL pointer error */";
if (*pathp == '\0')
pathp = "/"; /* root is nameless */
printf("%s%s {\n",
&tabs[MAX_LEVEL - level], pathp);

// Overwrite the name of created node
if (level == 0) {
pathp = new_prop;
}

level++;
if (level >= MAX_LEVEL) {
printf("Nested too deep, aborting.\n");
return 1;
}

newoffset[level] = fdt_add_subnode_namelen(working_fdt, newoffset[level-1],
pathp, strlen(pathp), 1);
if (newoffset[level] < 0) {
printf ("libfdt fdt_add_subnode() returned %s\n",
fdt_strerror(newoffset[level]));
return 1;
}
break;
case FDT_END_NODE:
level--;

printf("%s};\n", &tabs[MAX_LEVEL - level]);

if (level == 0) {
level = -1; /* exit the loop */
}
break;
case FDT_PROP:
fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
sizeof(*fdt_prop));
pathp = fdt_string(working_fdt,
fdt32_to_cpu(fdt_prop->nameoff));
len = fdt32_to_cpu(fdt_prop->len);
nodep = fdt_prop->data;
if (len < 0) {
printf ("libfdt fdt_getprop(): %s\n",
fdt_strerror(len));
return 1;
} else if(len == 0) {
printf("%s%s;\n",
&tabs[MAX_LEVEL - level],
pathp);
} else {
printf("%s%s = ",
&tabs[MAX_LEVEL - level],
pathp);
print_data (nodep, len);
printf(";\n");
}
ret = fdt_appendprop(working_fdt, newoffset[level], pathp, nodep, len);
if (ret < 0) {
printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
return 1;
}
break;
case FDT_NOP:
printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
break;
case FDT_END:
return 1;
default:
printf("Unknown tag 0x%08X\n", tag);
return 1;
}
nodeoffset = nextoffset;
}
return 0;
}

/********************************************************************/
#ifdef CONFIG_SYS_LONGHELP
static char fdt_help_text[] =
Expand All @@ -1031,6 +1172,7 @@ static char fdt_help_text[] =
"fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
"fdt mknode <path> <node> - Create a new node after <path>\n"
"fdt rm <path> [<prop>] - Delete the node or <property>\n"
"fdt dup <path> <old> <new> - Duplicate the <old-node> under <path> to <new>"
"fdt header - Display header info\n"
"fdt bootcpu <id> - Set boot cpuid\n"
"fdt memory <addr> <size> - Add/Update memory node\n"
Expand Down
2 changes: 1 addition & 1 deletion include/libfdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1449,7 +1449,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* full path.
*/
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
const char *name, int namelen);
const char *name, int namelen, int atend);

/**
* fdt_add_subnode - creates a new node
Expand Down
20 changes: 17 additions & 3 deletions lib/libfdt/fdt_rw.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,13 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
}

int fdt_add_subnode_namelen(void *fdt, int parentoffset,
const char *name, int namelen)
const char *name, int namelen, int atend)
{
struct fdt_node_header *nh;
int offset, nextoffset;
int nodelen;
int err;
int level = 0;
uint32_t tag;
fdt32_t *endtag;

Expand All @@ -310,10 +311,23 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,

/* Try to place the new node after the parent's properties */
fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
level = 1;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
if ((tag == FDT_PROP) || (tag == FDT_NOP)) {
continue;
} else if (atend && tag == FDT_BEGIN_NODE) {
++level;
} else if (atend && tag == FDT_END_NODE) {
--level;
if (level <= 0) {
break;
}
} else {
break;
}
} while (true);

nh = _fdt_offset_ptr_w(fdt, offset);
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
Expand All @@ -333,7 +347,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,

int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
{
return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name), 0);
}

int fdt_del_node(void *fdt, int nodeoffset)
Expand Down

0 comments on commit b4a5d35

Please sign in to comment.