[RFC 1/4] dtoc: add POC for dtb shrink
Walter Lozano
walter.lozano at collabora.com
Tue Jul 7 15:57:51 CEST 2020
Hi Simon,
Thanks for your time.
On 6/7/20 16:21, Simon Glass wrote:
> Hi Walter,
>
> On Fri, 19 Jun 2020 at 15:11, Walter Lozano <walter.lozano at collabora.com> wrote:
>> Based on several reports and discussions [1], [2] it is clear that U-Boot's
>> footprint is always a concern, and any kind of reduction is an
>> improvement.
>>
>> In particular dtb is one of the sources of footprint increment, as
>> U-Boot uses the same dtb as Linux. However is interesting to note that
>> U-Boot does not require all the nodes and properties declared in it.
>> Some improvements in this sense are already present, such as
>> removing properties based on configuration and using specific "u-boot"
>> properties to keep only specific node in SPL. However, this require
>> manual configuration.
>>
>> Additionally reducing dtb, will allow ATF for better handing FDT buffer, which
>> is an issue in some contexts [3].
>>
>> In order to improve this situation, this patch adds a proof of concept
>> for dtb shrink. The idea behind this is simple, remove all the nodes
>> from dtb which compatible string is not supported by any driver present.
>> This approach makes sense for those configuration where Linux is
>> expected to have its own dtb.
>>
>> This patch is based on the work of Simon Glass present in [4] which adds
>> support to dtoc for parsing compatible strings.
>>
>> Some early untested results shows that the reduction in size is 50 % in
>> case of mx6_cuboxi_defconfig, which is promising.
>>
>> Some additional reduction could be possible by only keeping the nodes for
>> whose compatible string is supported by any enabled driver. However,
>> this requires to add extra logic to parse config files and map
>> configuration to compatible strings.
>>
>> This proof of concept uses fdtgrep to implement the node removal, but
>> the idea is to implement this logic inside the dtoc for better handling.
>>
>> [1] http://patchwork.ozlabs.org/project/uboot/patch/20200525093539.1.Ibf2d19439cde35e39192a9d4a8dad23539fae2e6@changeid/
>> [2] http://u-boot.10912.n7.nabble.com/PATCH-v1-00-15-add-basic-driver-support-for-broadcom-NS3-soc-tt412411.html#none
>> [3] https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/4512
>> [4] https://gitlab.denx.de/u-boot/custodians/u-boot-dm/-/tree/dtoc-working
>>
>> Signed-off-by: Walter Lozano <walter.lozano at collabora.com>
>> ---
>> tools/dtoc/dtb_platdata.py | 42 +++++++++++++++++++++++++++++++++++---
>> 1 file changed, 39 insertions(+), 3 deletions(-)
>>
>> diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
>> index 21cce5afb5..1df13b2cd2 100644
>> --- a/tools/dtoc/dtb_platdata.py
>> +++ b/tools/dtoc/dtb_platdata.py
>> @@ -399,7 +399,10 @@ class DtbPlatdata(object):
>> """Scan the driver folders to build a list of driver names and possible
>> aliases
>> """
>> - for (dirpath, dirnames, filenames) in os.walk('/home/sglass/u'):
>> + basedir = sys.argv[0].replace('tools/dtoc/dtoc', '')
> Instead of this logic, can we pass the source-tree location into dtoc
> with a flag? It could default to the current dir perhaps.
Sure, no problem at all.
>
>> + if basedir == '':
>> + basedir = './'
>> + for (dirpath, dirnames, filenames) in os.walk(basedir):
>> for fn in filenames:
>> if not fn.endswith('.c'):
>> continue
>> @@ -802,6 +805,32 @@ class DtbPlatdata(object):
>> self.out(''.join(self.get_buf()))
>> self.close_output()
>>
>> + def shrink(self):
>> + """Generate a shrunk version of DTB bases on valid drivers
>> +
>> + This function removes nodes from dtb which compatible string is not
>> + found in drivers. The output is saved in a file with suffix name -shrink.dtb
>> + """
>> + compat = []
>> + cmd = './tools/fdtgrep '
>> + #print(self._drivers)
>> + for dr in self._drivers.values():
>> + compat = compat + dr.compat
>> +
>> + for cp in compat:
>> + #print(cp)
>> + cmd += ' -c ' + cp
>> +
>> + cmd += ' -O dtb -o ' + self._dtb_fname.replace('.dtb', '') + '-shrink.dtb ' + self._dtb_fname
>> +
>> + if False:
>> + with open('dt_shrink.sh', 'w+') as script:
>> + script.write(cmd)
>> +
>> + os.system(cmd)
>> +
>> + return
>> +
>> def run_steps(args, dtb_file, config_file, include_disabled, output):
>> """Run all the steps of the dtoc tool
>>
>> @@ -816,6 +845,10 @@ def run_steps(args, dtb_file, config_file, include_disabled, output):
>> if not args:
>> raise ValueError('Please specify a command: struct, platdata')
>>
>> + skip_scan = False
>> + if args == ['shrink']:
>> + skip_scan = True
> I think that would be better as a positive variable, like 'scan'.
Yes, I agree. The idea was to test the general idea, and check if it
could be useful.
>
>> +
>> plat = DtbPlatdata(dtb_file, config_file, include_disabled)
>> plat.scan_drivers()
>> plat.scan_dtb()
>> @@ -823,14 +856,17 @@ def run_steps(args, dtb_file, config_file, include_disabled, output):
>> plat.scan_config()
>> plat.scan_reg_sizes()
> Are those two needed with this new command?
Probably not in this version, but I was planning to use scan_config to
check which drivers are enabled. Actually a there is a newer version in
the link I previously left. However, as I had some issues working on top
of the dtoc-working branch this version is back ported, in order to make
is user to run some early/quick tests.
https://gitlab.collabora.com/wlozano/u-boot/-/tree/wip
>> plat.setup_output(output)
>> - structs = plat.scan_structs()
>> - plat.scan_phandles()
>> + if not skip_scan:
>> + structs = plat.scan_structs()
>> + plat.scan_phandles()
>>
>> for cmd in args[0].split(','):
>> if cmd == 'struct':
>> plat.generate_structs(structs)
>> elif cmd == 'platdata':
>> plat.generate_tables()
>> + elif cmd == 'shrink':
>> + plat.shrink()
>> else:
>> raise ValueError("Unknown command '%s': (use: struct, platdata)" %
>> cmd)
>> --
>> 2.20.1
>>
Regards,
Walter
More information about the U-Boot
mailing list