@ -19,6 +19,7 @@
# include <errno.h>
# include <mapmem.h>
# include <asm/io.h>
# include <malloc.h>
DECLARE_GLOBAL_DATA_PTR ;
# endif /* !USE_HOSTCC*/
@ -434,6 +435,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
printf ( " 0x%08lx \n " , load ) ;
}
/* optional load address for FDT */
if ( type = = IH_TYPE_FLATDT & & ! fit_image_get_load ( fit , image_noffset , & load ) )
printf ( " %s Load Address: 0x%08lx \n " , p , load ) ;
if ( ( type = = IH_TYPE_KERNEL ) | | ( type = = IH_TYPE_STANDALONE ) | |
( type = = IH_TYPE_RAMDISK ) ) {
ret = fit_image_get_entry ( fit , image_noffset , & entry ) ;
@ -1454,6 +1459,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
{
int noffset , confs_noffset ;
int len ;
const char * s ;
char * conf_uname_copy = NULL ;
confs_noffset = fdt_path_offset ( fit , FIT_CONFS_PATH ) ;
if ( confs_noffset < 0 ) {
@ -1475,12 +1482,29 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
debug ( " Found default configuration: '%s' \n " , conf_uname ) ;
}
s = strchr ( conf_uname , ' # ' ) ;
if ( s ) {
len = s - conf_uname ;
conf_uname_copy = malloc ( len + 1 ) ;
if ( ! conf_uname_copy ) {
debug ( " Can't allocate uname copy: '%s' \n " ,
conf_uname ) ;
return - ENOMEM ;
}
memcpy ( conf_uname_copy , conf_uname , len ) ;
conf_uname_copy [ len ] = ' \0 ' ;
conf_uname = conf_uname_copy ;
}
noffset = fdt_subnode_offset ( fit , confs_noffset , conf_uname ) ;
if ( noffset < 0 ) {
debug ( " Can't get node offset for configuration unit name: '%s' (%s) \n " ,
conf_uname , fdt_strerror ( noffset ) ) ;
}
if ( conf_uname_copy )
free ( conf_uname_copy ) ;
return noffset ;
}
@ -1527,7 +1551,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
char * desc ;
const char * uname ;
int ret ;
int loadables_index ;
int fdt_index , loadables_index ;
/* Mandatory properties */
ret = fit_get_desc ( fit , noffset , & desc ) ;
@ -1549,9 +1573,17 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
if ( uname )
printf ( " %s Init Ramdisk: %s \n " , p , uname ) ;
uname = fdt_getprop ( fit , noffset , FIT_FDT_PROP , NULL ) ;
if ( uname )
printf ( " %s FDT: %s \n " , p , uname ) ;
for ( fdt_index = 0 ;
uname = fdt_stringlist_get ( fit , noffset , FIT_FDT_PROP ,
fdt_index , NULL ) , uname ;
fdt_index + + ) {
if ( fdt_index = = 0 )
printf ( " %s FDT: " , p ) ;
else
printf ( " %s " , p ) ;
printf ( " %s \n " , uname ) ;
}
uname = fdt_getprop ( fit , noffset , FIT_FPGA_PROP , NULL ) ;
if ( uname )
@ -1888,3 +1920,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
return ret ;
}
# ifndef USE_HOSTCC
int boot_get_fdt_fit ( bootm_headers_t * images , ulong addr ,
const char * * fit_unamep , const char * * fit_uname_configp ,
int arch , ulong * datap , ulong * lenp )
{
int fdt_noffset , cfg_noffset , count ;
const void * fit ;
const char * fit_uname = NULL ;
const char * fit_uname_config = NULL ;
char * fit_uname_config_copy = NULL ;
char * next_config = NULL ;
ulong load , len ;
# ifdef CONFIG_OF_LIBFDT_OVERLAY
ulong image_start , image_end ;
ulong ovload , ovlen ;
const char * uconfig ;
const char * uname ;
void * base , * ov ;
int i , err , noffset , ov_noffset ;
# endif
fit_uname = fit_unamep ? * fit_unamep : NULL ;
if ( fit_uname_configp & & * fit_uname_configp ) {
fit_uname_config_copy = strdup ( * fit_uname_configp ) ;
if ( ! fit_uname_config_copy )
return - ENOMEM ;
next_config = strchr ( fit_uname_config_copy , ' # ' ) ;
if ( next_config )
* next_config + + = ' \0 ' ;
if ( next_config - 1 > fit_uname_config_copy )
fit_uname_config = fit_uname_config_copy ;
}
fdt_noffset = fit_image_load ( images ,
addr , & fit_uname , & fit_uname_config ,
arch , IH_TYPE_FLATDT ,
BOOTSTAGE_ID_FIT_FDT_START ,
FIT_LOAD_OPTIONAL , & load , & len ) ;
if ( fdt_noffset < 0 )
goto out ;
debug ( " fit_uname=%s, fit_uname_config=%s \n " ,
fit_uname ? fit_uname : " <NULL> " ,
fit_uname_config ? fit_uname_config : " <NULL> " ) ;
fit = map_sysmem ( addr , 0 ) ;
cfg_noffset = fit_conf_get_node ( fit , fit_uname_config ) ;
/* single blob, or error just return as well */
count = fit_conf_get_prop_node_count ( fit , cfg_noffset , FIT_FDT_PROP ) ;
if ( count < = 1 & & ! next_config )
goto out ;
/* we need to apply overlays */
# ifdef CONFIG_OF_LIBFDT_OVERLAY
image_start = addr ;
image_end = addr + fit_get_size ( fit ) ;
/* verify that relocation took place by load address not being in fit */
if ( load > = image_start & & load < image_end ) {
/* check is simplified; fit load checks for overlaps */
printf ( " Overlayed FDT requires relocation \n " ) ;
fdt_noffset = - EBADF ;
goto out ;
}
base = map_sysmem ( load , len ) ;
/* apply extra configs in FIT first, followed by args */
for ( i = 1 ; ; i + + ) {
if ( i < count ) {
noffset = fit_conf_get_prop_node_index ( fit , cfg_noffset ,
FIT_FDT_PROP , i ) ;
uname = fit_get_name ( fit , noffset , NULL ) ;
uconfig = NULL ;
} else {
if ( ! next_config )
break ;
uconfig = next_config ;
next_config = strchr ( next_config , ' # ' ) ;
if ( next_config )
* next_config + + = ' \0 ' ;
uname = NULL ;
}
debug ( " %d: using uname=%s uconfig=%s \n " , i , uname , uconfig ) ;
ov_noffset = fit_image_load ( images ,
addr , & uname , & uconfig ,
arch , IH_TYPE_FLATDT ,
BOOTSTAGE_ID_FIT_FDT_START ,
FIT_LOAD_REQUIRED , & ovload , & ovlen ) ;
if ( ov_noffset < 0 ) {
printf ( " load of %s failed \n " , uname ) ;
continue ;
}
debug ( " %s loaded at 0x%08lx len=0x%08lx \n " ,
uname , ovload , ovlen ) ;
ov = map_sysmem ( ovload , ovlen ) ;
base = map_sysmem ( load , len + ovlen ) ;
err = fdt_open_into ( base , base , len + ovlen ) ;
if ( err < 0 ) {
printf ( " failed on fdt_open_into \n " ) ;
fdt_noffset = err ;
goto out ;
}
/* the verbose method prints out messages on error */
err = fdt_overlay_apply_verbose ( base , ov ) ;
if ( err < 0 ) {
fdt_noffset = err ;
goto out ;
}
fdt_pack ( base ) ;
len = fdt_totalsize ( base ) ;
}
# else
printf ( " config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set \n " ) ;
fdt_noffset = - EBADF ;
# endif
out :
if ( datap )
* datap = load ;
if ( lenp )
* lenp = len ;
if ( fit_unamep )
* fit_unamep = fit_uname ;
if ( fit_uname_configp )
* fit_uname_configp = fit_uname_config ;
if ( fit_uname_config_copy )
free ( fit_uname_config_copy ) ;
return fdt_noffset ;
}
# endif