Subject: RFA & Update: Using libfdt in u-boot for fdt command

From: Jerry Van Baren <[email-masked]>
Date: Thu, 01 Mar 2007 09:01:24 -0500

Hi all,

This is a Request for Advice.

First off, for those on both the u-boot and linuxppc-dev lists, sorry 
for cross posting.  :-)

Git repo pointers...
libfdt hacks:
<http://www.cideas.us/cgi-bin/gitweb.cgi?p=linux/libfdt.git;a=summary>
u-boot hacks:
<http://www.cideas.us/cgi-bin/gitweb.cgi?p=u-boot/u-boot-mpc83xx;a=summary>

I have a proof-of-concept (actually, somewhat more than PoC) fdt command 
built using libfdt.  Now I'm looking for advice on the best way to turn 
the PoC into Real Code[tm].

Current commands:
-----------------
fdt address        - set the base address of the blob
fdt get <property> - get a property
fdt print <node>   - print the subtree starting at <node>[1]

Planned commands:
-----------------
fdt set <property> <value> - set a property value (do we want an
                        "=" as in <property> = <value>?)
fdt ?synthesize?   - create the "chosen" branch and optionally the
                        u-boot variables branch.  The OF code/calls
                        currently in bootm would be moved to this
                        command.  I'm open to suggestions for a good
                        subcommand name.

Other commands:
---------------
fdt node <name>    - create a node that can then be populated with 
properties (have not thought about this in any detail yet).

[1] If <node> is actually a <property> (which is a usage error, but I 
expect will happen all the time), "fdt print" actually does a "fdt get 
<property>"  This makes "fdt get" redundant and likely will make it go away.

Philosophy question primarily for David Gibson and Wolfgang Denk:  What 
is the best way to integrate libfdt with u-boot?  Currently it is in its 
own git repository.  Options?
1) Do we want to capture the source in the u-boot git repository?  If 
so, it becomes a snapshot and will require cross pushing/pulling between 
the libfdt repo and the u-boot repo or they will drift apart.  However, 
it makes problems #1 and #2 (below) simpler to solve but causes drift.
2) Not capturing libfdt in the u-boot repo makes it more difficult for 
integrating it with and maintaining it in u-boot, I'm not sure how to 
actually do it in a useful/usable manner.

There are three problem areas with libfdt:
1) The official Makefile is stand-alone which doesn't work well with 
u-boot.  I took the expedient route for the PoC of simply replacing it 
with a u-boot style Makefile from a different lib* subdirectory.  There 
should be a better way.

2) The official libfdt uses two header files that are not in u-boot.  I 
"fixed" this by substituting u-boot headers with equivalent functionality.
* I need to address this and see what the best compromise for header 
files is...
   a) If the u-boot headers are acceptable for the stand-alone version
        of libfdt, that would be the simplest.
   b) It may be more effective to add the necessary linux headers to
        u-boot.
   c) We could use #ifdefs to conditionally include the right files. (but
        does u-boot have a distinctive configuration def?  Probably...)

3) I added a "fdt_next_tag()" function to fdt_ro.c to allow me to step 
through the blob's tags:
   uint32_t fdt_next_tag(const void *fdt, int offset,
                         int *nextoffset, char **namep);

This is similar to "_fdt_next_tag()" (a "private" function, note the 
leading underscore) in fdt.c, but with a related but different purpose - 
  the "_fdt_next_tag()" steps through _node_ tags (skipping property 
tags) where I need to step through all tags sequentially.

Usability trivia for David: libfdt distinguishes between nodes and 
properties, which makes sense since that is how the fdt is structured. 
 From a usability standpoint, however, it is annoying to have to 
separate the property name from the node, find the node, then find the 
property.  I will probably create Yet Another Function:
   int fdt_split(char *path, char **property);
Call it with a path string and the function will separate it into the 
node portion and the property name.  If the path is invalid, it will 
return an error.  If the path is a node, it will set **property to NULL 
and return the node's offset.  If the path is a property, it will return 
the owning node's offset and set the **property pointer to point to the 
start of the property portion of the path (i.e. the next character after 
the last '/').

If you got this far, thank you for your attention.  :-)

Best regards,
gvb