2007-12-18 07:06:42 +03:00
/*
* ( C ) Copyright David Gibson < dwg @ au1 . ibm . com > , IBM Corporation . 2005.
*
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation ; either version 2 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA
*/
2016-01-26 18:04:11 +03:00
# include <sys/stat.h>
2007-12-18 07:06:42 +03:00
# include "dtc.h"
# include "srcpos.h"
/*
* Command line options
*/
int quiet ; /* Level of quietness */
int reservenum ; /* Number of memory reservation slots */
int minsize ; /* Minimum blob size */
int padsize ; /* Additional padding to blob */
2017-01-04 19:45:20 +03:00
int alignsize ; /* Additional padding to blob accroding to the alignsize */
2017-10-03 19:37:04 +03:00
int phandle_format = PHANDLE_EPAPR ; /* Use linux,phandle or phandle properties */
2017-01-04 19:45:20 +03:00
int generate_symbols ; /* enable symbols & fixup support */
int generate_fixups ; /* suppress generation of fixups on symbol support */
int auto_label_aliases ; /* auto generate labels -> aliases */
static int is_power_of_2 ( int x )
{
return ( x > 0 ) & & ( ( x & ( x - 1 ) ) = = 0 ) ;
}
2007-12-18 07:06:42 +03:00
2008-08-07 06:24:17 +04:00
static void fill_fullpaths ( struct node * tree , const char * prefix )
2007-12-18 07:06:42 +03:00
{
struct node * child ;
const char * unit ;
tree - > fullpath = join_path ( prefix , tree - > name ) ;
unit = strchr ( tree - > name , ' @ ' ) ;
if ( unit )
tree - > basenamelen = unit - tree - > name ;
else
tree - > basenamelen = strlen ( tree - > name ) ;
for_each_child ( tree , child )
fill_fullpaths ( child , tree - > fullpath ) ;
}
2014-01-21 16:54:49 +04:00
/* Usage related data. */
static const char usage_synopsis [ ] = " dtc [options] <input file> " ;
2017-01-04 19:45:20 +03:00
static const char usage_short_opts [ ] = " qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv " ;
2014-01-21 16:54:49 +04:00
static struct option const usage_long_opts [ ] = {
{ " quiet " , no_argument , NULL , ' q ' } ,
{ " in-format " , a_argument , NULL , ' I ' } ,
{ " out " , a_argument , NULL , ' o ' } ,
{ " out-format " , a_argument , NULL , ' O ' } ,
{ " out-version " , a_argument , NULL , ' V ' } ,
{ " out-dependency " , a_argument , NULL , ' d ' } ,
{ " reserve " , a_argument , NULL , ' R ' } ,
{ " space " , a_argument , NULL , ' S ' } ,
{ " pad " , a_argument , NULL , ' p ' } ,
2017-01-04 19:45:20 +03:00
{ " align " , a_argument , NULL , ' a ' } ,
2014-01-21 16:54:49 +04:00
{ " boot-cpu " , a_argument , NULL , ' b ' } ,
{ " force " , no_argument , NULL , ' f ' } ,
{ " include " , a_argument , NULL , ' i ' } ,
{ " sort " , no_argument , NULL , ' s ' } ,
{ " phandle " , a_argument , NULL , ' H ' } ,
{ " warning " , a_argument , NULL , ' W ' } ,
{ " error " , a_argument , NULL , ' E ' } ,
2017-01-04 19:45:20 +03:00
{ " symbols " , no_argument , NULL , ' @ ' } ,
{ " auto-alias " , no_argument , NULL , ' A ' } ,
2014-01-21 16:54:49 +04:00
{ " help " , no_argument , NULL , ' h ' } ,
{ " version " , no_argument , NULL , ' v ' } ,
{ NULL , no_argument , NULL , 0x0 } ,
} ;
static const char * const usage_opts_help [ ] = {
" \n \t Quiet: -q suppress warnings, -qq errors, -qqq all " ,
" \n \t Input formats are: \n "
" \t \t dts - device tree source text \n "
" \t \t dtb - device tree blob \n "
" \t \t fs - /proc/device-tree style directory " ,
" \n \t Output file " ,
" \n \t Output formats are: \n "
" \t \t dts - device tree source text \n "
" \t \t dtb - device tree blob \n "
" \t \t asm - assembler source " ,
2018-02-28 02:40:38 +03:00
" \n \t Blob version to produce, defaults to " stringify ( DEFAULT_FDT_VERSION ) " (for dtb and asm output) " ,
2014-01-21 16:54:49 +04:00
" \n \t Output dependency file " ,
2015-04-30 00:00:05 +03:00
" \n \t Make space for <number> reserve map entries (for dtb and asm output) " ,
2014-01-21 16:54:49 +04:00
" \n \t Make the blob at least <bytes> long (extra space) " ,
" \n \t Add padding to the blob of <bytes> long (extra space) " ,
2017-01-04 19:45:20 +03:00
" \n \t Make the blob align to the <bytes> (extra space) " ,
2014-01-21 16:54:49 +04:00
" \n \t Set the physical boot cpu " ,
" \n \t Try to produce output even if the input tree has errors " ,
" \n \t Add a path to search for include files " ,
" \n \t Sort nodes and properties before outputting (useful for comparing trees) " ,
" \n \t Valid phandle formats are: \n "
" \t \t legacy - \" linux,phandle \" properties only \n "
" \t \t epapr - \" phandle \" properties only \n "
" \t \t both - Both \" linux,phandle \" and \" phandle \" properties " ,
" \n \t Enable/disable warnings (prefix with \" no- \" ) " ,
" \n \t Enable/disable errors (prefix with \" no- \" ) " ,
2017-01-04 19:45:20 +03:00
" \n \t Enable generation of symbols " ,
" \n \t Enable auto-alias of labels " ,
2014-01-21 16:54:49 +04:00
" \n \t Print this help and exit " ,
" \n \t Print version and exit " ,
NULL ,
} ;
2007-12-18 07:06:42 +03:00
2016-01-26 18:04:11 +03:00
static const char * guess_type_by_name ( const char * fname , const char * fallback )
{
const char * s ;
s = strrchr ( fname , ' . ' ) ;
if ( s = = NULL )
return fallback ;
if ( ! strcasecmp ( s , " .dts " ) )
return " dts " ;
if ( ! strcasecmp ( s , " .dtb " ) )
return " dtb " ;
return fallback ;
}
static const char * guess_input_format ( const char * fname , const char * fallback )
{
struct stat statbuf ;
2017-03-21 17:01:08 +03:00
fdt32_t magic ;
2016-01-26 18:04:11 +03:00
FILE * f ;
if ( stat ( fname , & statbuf ) ! = 0 )
return fallback ;
if ( S_ISDIR ( statbuf . st_mode ) )
return " fs " ;
if ( ! S_ISREG ( statbuf . st_mode ) )
return fallback ;
f = fopen ( fname , " r " ) ;
if ( f = = NULL )
return fallback ;
if ( fread ( & magic , 4 , 1 , f ) ! = 1 ) {
fclose ( f ) ;
return fallback ;
}
fclose ( f ) ;
2017-03-21 17:01:08 +03:00
if ( fdt32_to_cpu ( magic ) = = FDT_MAGIC )
2016-01-26 18:04:11 +03:00
return " dtb " ;
return guess_type_by_name ( fname , fallback ) ;
}
2007-12-18 07:06:42 +03:00
int main ( int argc , char * argv [ ] )
{
2017-01-04 19:45:20 +03:00
struct dt_info * dti ;
2016-01-26 18:04:11 +03:00
const char * inform = NULL ;
const char * outform = NULL ;
2007-12-18 07:06:42 +03:00
const char * outname = " - " ;
2012-01-11 04:27:52 +04:00
const char * depname = NULL ;
2015-04-30 00:00:05 +03:00
bool force = false , sort = false ;
2007-12-18 07:06:42 +03:00
const char * arg ;
int opt ;
FILE * outf = NULL ;
int outversion = DEFAULT_FDT_VERSION ;
2008-08-07 06:24:17 +04:00
long long cmdline_boot_cpuid = - 1 ;
2007-12-18 07:06:42 +03:00
quiet = 0 ;
reservenum = 0 ;
minsize = 0 ;
padsize = 0 ;
2017-01-04 19:45:20 +03:00
alignsize = 0 ;
2007-12-18 07:06:42 +03:00
2014-01-21 16:54:49 +04:00
while ( ( opt = util_getopt_long ( ) ) ! = EOF ) {
2007-12-18 07:06:42 +03:00
switch ( opt ) {
case ' I ' :
inform = optarg ;
break ;
case ' O ' :
outform = optarg ;
break ;
case ' o ' :
outname = optarg ;
break ;
case ' V ' :
outversion = strtol ( optarg , NULL , 0 ) ;
break ;
2012-01-11 04:27:52 +04:00
case ' d ' :
depname = optarg ;
break ;
2007-12-18 07:06:42 +03:00
case ' R ' :
reservenum = strtol ( optarg , NULL , 0 ) ;
break ;
case ' S ' :
minsize = strtol ( optarg , NULL , 0 ) ;
break ;
case ' p ' :
padsize = strtol ( optarg , NULL , 0 ) ;
break ;
2017-01-04 19:45:20 +03:00
case ' a ' :
alignsize = strtol ( optarg , NULL , 0 ) ;
if ( ! is_power_of_2 ( alignsize ) )
die ( " Invalid argument \" %d \" to -a option \n " ,
2017-03-21 17:01:08 +03:00
alignsize ) ;
2017-01-04 19:45:20 +03:00
break ;
2007-12-18 07:06:42 +03:00
case ' f ' :
2015-04-30 00:00:05 +03:00
force = true ;
2007-12-18 07:06:42 +03:00
break ;
case ' q ' :
quiet + + ;
break ;
case ' b ' :
2008-08-07 06:24:17 +04:00
cmdline_boot_cpuid = strtoll ( optarg , NULL , 0 ) ;
2007-12-18 07:06:42 +03:00
break ;
2012-09-29 01:25:59 +04:00
case ' i ' :
srcfile_add_search_path ( optarg ) ;
break ;
2007-12-18 07:06:42 +03:00
case ' v ' :
2014-01-21 16:54:49 +04:00
util_version ( ) ;
2010-11-18 02:28:20 +03:00
case ' H ' :
if ( streq ( optarg , " legacy " ) )
phandle_format = PHANDLE_LEGACY ;
else if ( streq ( optarg , " epapr " ) )
phandle_format = PHANDLE_EPAPR ;
else if ( streq ( optarg , " both " ) )
phandle_format = PHANDLE_BOTH ;
else
die ( " Invalid argument \" %s \" to -H option \n " ,
optarg ) ;
break ;
case ' s ' :
2015-04-30 00:00:05 +03:00
sort = true ;
2010-11-18 02:28:20 +03:00
break ;
2012-09-29 01:25:59 +04:00
case ' W ' :
parse_checks_option ( true , false , optarg ) ;
break ;
case ' E ' :
parse_checks_option ( false , true , optarg ) ;
break ;
2017-01-04 19:45:20 +03:00
case ' @ ' :
generate_symbols = 1 ;
break ;
case ' A ' :
auto_label_aliases = 1 ;
break ;
2007-12-18 07:06:42 +03:00
case ' h ' :
2014-01-21 16:54:49 +04:00
usage ( NULL ) ;
2007-12-18 07:06:42 +03:00
default :
2014-01-21 16:54:49 +04:00
usage ( " unknown option " ) ;
2007-12-18 07:06:42 +03:00
}
}
if ( argc > ( optind + 1 ) )
2014-01-21 16:54:49 +04:00
usage ( " missing files " ) ;
2007-12-18 07:06:42 +03:00
else if ( argc < ( optind + 1 ) )
arg = " - " ;
else
arg = argv [ optind ] ;
/* minsize and padsize are mutually exclusive */
2008-08-07 06:24:17 +04:00
if ( minsize & & padsize )
2007-12-18 07:06:42 +03:00
die ( " Can't set both -p and -S \n " ) ;
2012-01-11 04:27:52 +04:00
if ( depname ) {
depfile = fopen ( depname , " w " ) ;
if ( ! depfile )
die ( " Couldn't open dependency file %s: %s \n " , depname ,
strerror ( errno ) ) ;
fprintf ( depfile , " %s: " , outname ) ;
}
2016-01-26 18:04:11 +03:00
if ( inform = = NULL )
inform = guess_input_format ( arg , " dts " ) ;
if ( outform = = NULL ) {
outform = guess_type_by_name ( outname , NULL ) ;
if ( outform = = NULL ) {
if ( streq ( inform , " dts " ) )
outform = " dtb " ;
else
outform = " dts " ;
}
}
2008-08-07 06:24:17 +04:00
if ( streq ( inform , " dts " ) )
2017-01-04 19:45:20 +03:00
dti = dt_from_source ( arg ) ;
2008-08-07 06:24:17 +04:00
else if ( streq ( inform , " fs " ) )
2017-01-04 19:45:20 +03:00
dti = dt_from_fs ( arg ) ;
2008-08-07 06:24:17 +04:00
else if ( streq ( inform , " dtb " ) )
2017-01-04 19:45:20 +03:00
dti = dt_from_blob ( arg ) ;
2008-08-07 06:24:17 +04:00
else
2007-12-18 07:06:42 +03:00
die ( " Unknown input format \" %s \" \n " , inform ) ;
2017-03-21 17:01:08 +03:00
dti - > outname = outname ;
2012-01-11 04:27:52 +04:00
if ( depfile ) {
fputc ( ' \n ' , depfile ) ;
fclose ( depfile ) ;
}
2008-08-07 06:24:17 +04:00
if ( cmdline_boot_cpuid ! = - 1 )
2017-01-04 19:45:20 +03:00
dti - > boot_cpuid_phys = cmdline_boot_cpuid ;
fill_fullpaths ( dti - > dt , " " ) ;
/* on a plugin, generate by default */
if ( dti - > dtsflags & DTSF_PLUGIN ) {
generate_fixups = 1 ;
}
2007-12-18 07:06:42 +03:00
2018-02-28 02:40:38 +03:00
process_checks ( force , dti ) ;
2017-01-04 19:45:20 +03:00
if ( auto_label_aliases )
generate_label_tree ( dti , " aliases " , false ) ;
if ( generate_symbols )
generate_label_tree ( dti , " __symbols__ " , true ) ;
if ( generate_fixups ) {
generate_fixups_tree ( dti , " __fixups__ " ) ;
generate_local_fixups_tree ( dti , " __local_fixups__ " ) ;
}
2007-12-18 07:06:42 +03:00
2010-11-18 02:28:20 +03:00
if ( sort )
2017-01-04 19:45:20 +03:00
sort_tree ( dti ) ;
2007-12-18 07:06:42 +03:00
if ( streq ( outname , " - " ) ) {
outf = stdout ;
} else {
2015-04-30 00:00:05 +03:00
outf = fopen ( outname , " wb " ) ;
2007-12-18 07:06:42 +03:00
if ( ! outf )
die ( " Couldn't open output file %s: %s \n " ,
outname , strerror ( errno ) ) ;
}
if ( streq ( outform , " dts " ) ) {
2017-01-04 19:45:20 +03:00
dt_to_source ( outf , dti ) ;
2007-12-18 07:06:42 +03:00
} else if ( streq ( outform , " dtb " ) ) {
2017-01-04 19:45:20 +03:00
dt_to_blob ( outf , dti , outversion ) ;
2007-12-18 07:06:42 +03:00
} else if ( streq ( outform , " asm " ) ) {
2017-01-04 19:45:20 +03:00
dt_to_asm ( outf , dti , outversion ) ;
2007-12-18 07:06:42 +03:00
} else if ( streq ( outform , " null " ) ) {
/* do nothing */
} else {
die ( " Unknown output format \" %s \" \n " , outform ) ;
}
exit ( 0 ) ;
}