@ -28,19 +28,19 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
if ( ! val )
return 0 ;
if ( ( * val = = ( uint32_t ) - 1 ) | | ( len ! = sizeof ( * val ) ) )
if ( ( len ! = sizeof ( * val ) ) | | ( * val = = ( uint32_t ) - 1 ) )
return ( uint32_t ) - 1 ;
return fdt32_to_cpu ( * val ) ;
}
/**
* overlay_get_target - retrieves the target phandle of a fragmen t
* overlay_get_target - retrieves the offset of a fragment ' s targe t
* @ fdt : Base device tree blob
* @ fdto : Device tree overlay blob
* @ fragment : node offset of the fragment in the overlay
*
* overlay_get_target ( ) retrieves the target phandle in the base
* overlay_get_target ( ) retrieves the target offset in the base
* device tree of a fragment , no matter how the actual targetting is
* done ( through a phandle or a path )
*
@ -53,6 +53,7 @@ static int overlay_get_target(const void *fdt, const void *fdto,
{
uint32_t phandle ;
const char * path ;
int path_len ;
/* Try first to do a phandle based lookup */
phandle = overlay_get_target_phandle ( fdto , fragment ) ;
@ -63,9 +64,20 @@ static int overlay_get_target(const void *fdt, const void *fdto,
return fdt_node_offset_by_phandle ( fdt , phandle ) ;
/* And then a path based lookup */
path = fdt_getprop ( fdto , fragment , " target-path " , NULL ) ;
if ( ! path )
return - FDT_ERR_NOTFOUND ;
path = fdt_getprop ( fdto , fragment , " target-path " , & path_len ) ;
if ( ! path ) {
/*
* If we haven ' t found either a target or a
* target - path property in a node that contains a
* __overlay__ subnode ( we wouldn ' t be called
* otherwise ) , consider it a improperly written
* overlay
*/
if ( path_len = = - FDT_ERR_NOTFOUND )
return - FDT_ERR_BADOVERLAY ;
return path_len ;
}
return fdt_path_offset ( fdt , path ) ;
}
@ -96,13 +108,16 @@ static int overlay_phandle_add_offset(void *fdt, int node,
return len ;
if ( len ! = sizeof ( * val ) )
return - FDT_ERR_BADSTRUCTUR E ;
return - FDT_ERR_BADPHANDL E ;
adj_val = fdt32_to_cpu ( * val ) ;
if ( ( adj_val + delta ) < adj_val )
return - FDT_ERR_BADPHANDLE ;
return - FDT_ERR_NOPHANDLES ;
adj_val + = delta ;
if ( adj_val = = ( uint32_t ) - 1 )
return - FDT_ERR_NOPHANDLES ;
return fdt_setprop_inplace_u32 ( fdt , node , name , adj_val ) ;
}
@ -124,7 +139,6 @@ static int overlay_phandle_add_offset(void *fdt, int node,
static int overlay_adjust_node_phandles ( void * fdto , int node ,
uint32_t delta )
{
bool found = false ;
int child ;
int ret ;
@ -132,22 +146,15 @@ static int overlay_adjust_node_phandles(void *fdto, int node,
if ( ret & & ret ! = - FDT_ERR_NOTFOUND )
return ret ;
if ( ! ret )
found = true ;
ret = overlay_phandle_add_offset ( fdto , node , " linux,phandle " , delta ) ;
if ( ret & & ret ! = - FDT_ERR_NOTFOUND )
return ret ;
/*
* If neither phandle nor linux , phandle have been found return
* an error .
*/
if ( ! found & & ! ret )
return ret ;
fdt_for_each_subnode ( child , fdto , node )
overlay_adjust_node_phandles ( fdto , child , delta ) ;
fdt_for_each_subnode ( child , fdto , node ) {
ret = overlay_adjust_node_phandles ( fdto , child , delta ) ;
if ( ret )
return ret ;
}
return 0 ;
}
@ -203,7 +210,8 @@ static int overlay_update_local_node_references(void *fdto,
int ret ;
fdt_for_each_property_offset ( fixup_prop , fdto , fixup_node ) {
const unsigned char * fixup_val , * tree_val ;
const uint32_t * fixup_val ;
const char * tree_val ;
const char * name ;
int fixup_len ;
int tree_len ;
@ -214,15 +222,21 @@ static int overlay_update_local_node_references(void *fdto,
if ( ! fixup_val )
return fixup_len ;
if ( fixup_len % sizeof ( uint32_t ) )
return - FDT_ERR_BADOVERLAY ;
tree_val = fdt_getprop ( fdto , tree_node , name , & tree_len ) ;
if ( ! tree_val )
if ( ! tree_val ) {
if ( tree_len = = - FDT_ERR_NOTFOUND )
return - FDT_ERR_BADOVERLAY ;
return tree_len ;
}
for ( i = 0 ; i < fixup_len ; i + = sizeof ( uint32_t ) ) {
uint32_t adj_val , index ;
for ( i = 0 ; i < ( fixup_len / sizeof ( uint32_t ) ) ; i + + ) {
uint32_t adj_val , poffset ;
index = * ( uint32_t * ) ( fixup_val + i ) ;
index = fdt32_to_cpu ( index ) ;
poffset = fdt32_to_cpu ( fixup_val [ i ] ) ;
/*
* phandles to fixup can be unaligned .
@ -230,7 +244,7 @@ static int overlay_update_local_node_references(void *fdto,
* Use a memcpy for the architectures that do
* not support unaligned accesses .
*/
memcpy ( & adj_val , tree_val + index , sizeof ( uint32_t ) ) ;
memcpy ( & adj_val , tree_val + poffset , sizeof ( adj_val ) ) ;
adj_val = fdt32_to_cpu ( adj_val ) ;
adj_val + = delta ;
@ -240,9 +254,12 @@ static int overlay_update_local_node_references(void *fdto,
tree_node ,
name ,
strlen ( name ) ,
index ,
poffset ,
& adj_val ,
sizeof ( adj_val ) ) ;
if ( ret = = - FDT_ERR_NOSPACE )
return - FDT_ERR_BADOVERLAY ;
if ( ret )
return ret ;
}
@ -255,6 +272,8 @@ static int overlay_update_local_node_references(void *fdto,
tree_child = fdt_subnode_offset ( fdto , tree_node ,
fixup_child_name ) ;
if ( ret = = - FDT_ERR_NOTFOUND )
return - FDT_ERR_BADOVERLAY ;
if ( tree_child < 0 )
return tree_child ;
@ -315,7 +334,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
* @ path_len : number of path characters to consider
* @ name : Name of the property holding the phandle reference in the overlay
* @ name_len : number of name characters to consider
* @ index : Index in the overlay property where the phandle is stored
* @ poffset : Offset with in the overlay property where the phandle is stored
* @ label : Label of the node referenced by the phandle
*
* overlay_fixup_one_phandle ( ) resolves an overlay phandle pointing to
@ -333,7 +352,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
int symbols_off ,
const char * path , uint32_t path_len ,
const char * name , uint32_t name_len ,
int index , const char * label )
int poffset , const char * label )
{
const char * symbol_path ;
uint32_t phandle ;
@ -343,7 +362,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
symbol_path = fdt_getprop ( fdt , symbols_off , label ,
& prop_len ) ;
if ( ! symbol_path )
return - FDT_ERR_NOTFOUND ;
return prop_len ;
symbol_off = fdt_path_offset ( fdt , symbol_path ) ;
if ( symbol_off < 0 )
@ -354,12 +373,14 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
return - FDT_ERR_NOTFOUND ;
fixup_off = fdt_path_offset_namelen ( fdto , path , path_len ) ;
if ( fixup_off = = - FDT_ERR_NOTFOUND )
return - FDT_ERR_BADOVERLAY ;
if ( fixup_off < 0 )
return fixup_off ;
phandle = cpu_to_fdt32 ( phandle ) ;
return fdt_setprop_inplace_namelen_partial ( fdto , fixup_off ,
name , name_len , index ,
name , name_len , poffset ,
& phandle , sizeof ( phandle ) ) ;
} ;
@ -371,8 +392,8 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
* @ property : Property offset in the overlay holding the list of fixups
*
* overlay_fixup_phandle ( ) resolves all the overlay phandles pointed
* to in a __local_ fixup__ property , and updates them to match the
* phandles in use in the base device tree .
* to in a __fixups __ property , and updates them to match the phandles
* in use in the base device tree .
*
* This is part of the device tree overlay application process , when
* you want all the phandles in the overlay to point to the actual
@ -391,40 +412,55 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
value = fdt_getprop_by_offset ( fdto , property ,
& label , & len ) ;
if ( ! value )
if ( ! value ) {
if ( len = = - FDT_ERR_NOTFOUND )
return - FDT_ERR_INTERNAL ;
return len ;
}
do {
const char * prop_string = value ;
const char * path , * name ;
uint32_t prop_len = strlen ( value ) ;
const char * path , * name , * fixup_end ;
const char * fixup_str = value ;
uint32_t path_len , name_len ;
uint32_t fixup_len ;
char * sep , * endptr ;
int index ;
int ret ;
int poffset , ret ;
fixup_end = memchr ( value , ' \0 ' , len ) ;
if ( ! fixup_end )
return - FDT_ERR_BADOVERLAY ;
fixup_len = fixup_end - fixup_str ;
len - = fixup_len + 1 ;
value + = fixup_len + 1 ;
path = fixup_str ;
sep = memchr ( fixup_str , ' : ' , fixup_len ) ;
if ( ! sep | | * sep ! = ' : ' )
return - FDT_ERR_BADOVERLAY ;
path = prop_string ;
sep = memchr ( prop_string , ' : ' , prop_len ) ;
if ( * sep ! = ' : ' )
return - FDT_ERR_BADSTRUCTURE ;
path_len = sep - path ;
if ( path_len = = ( fixup_len - 1 ) )
return - FDT_ERR_BADOVERLAY ;
fixup_len - = path_len + 1 ;
name = sep + 1 ;
sep = memchr ( name , ' : ' , prop_len ) ;
if ( * sep ! = ' : ' )
return - FDT_ERR_BADSTRUCTURE ;
sep = memchr ( name , ' : ' , fixup_len ) ;
if ( ! sep | | * sep ! = ' : ' )
return - FDT_ERR_BADOVERLAY ;
name_len = sep - name ;
if ( ! name_len )
return - FDT_ERR_BADOVERLAY ;
index = strtoul ( sep + 1 , & endptr , 10 ) ;
poffset = strtoul ( sep + 1 , & endptr , 10 ) ;
if ( ( * endptr ! = ' \0 ' ) | | ( endptr < = ( sep + 1 ) ) )
return - FDT_ERR_BADSTRUCTURE ;
len - = prop_len + 1 ;
value + = prop_len + 1 ;
return - FDT_ERR_BADOVERLAY ;
ret = overlay_fixup_one_phandle ( fdt , fdto , symbols_off ,
path , path_len , name , name_len ,
index , label ) ;
poffset , label ) ;
if ( ret )
return ret ;
} while ( len > 0 ) ;
@ -454,8 +490,15 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
int fixups_off , symbols_off ;
int property ;
symbols_off = fdt_path_offset ( fdt , " /__symbols__ " ) ;
/* We can have overlays without any fixups */
fixups_off = fdt_path_offset ( fdto , " /__fixups__ " ) ;
if ( ( fixups_off < 0 & & ( fixups_off ! = - FDT_ERR_NOTFOUND ) ) )
return fixups_off ;
/* And base DTs without symbols */
symbols_off = fdt_path_offset ( fdt , " /__symbols__ " ) ;
if ( ( symbols_off < 0 & & ( symbols_off ! = - FDT_ERR_NOTFOUND ) ) )
return symbols_off ;
fdt_for_each_property_offset ( property , fdto , fixups_off ) {
int ret ;
@ -469,14 +512,14 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
}
/**
* overlay_apply_node - Merge an overlay fragment into the base device tree
* overlay_apply_node - Merges a node into the base device tree
* @ fdt : Base Device Tree blob
* @ target : Node offset in the base device tree to apply the fragment to
* @ fdto : Device tree overlay blob
* @ fragment : Node offset in the overlay holding the changes to merge
* @ node : Node offset in the overlay holding the changes to merge
*
* overlay_apply_node ( ) merges an overlay fragment into a target base
* device tree node pointed .
* overlay_apply_node ( ) merges a node into a target base device tre e
* node pointed .
*
* This is part of the final step in the device tree overlay
* application process , when all the phandles have been adjusted and
@ -488,12 +531,12 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
* Negative error code on failure
*/
static int overlay_apply_node ( void * fdt , int target ,
void * fdto , int fragment )
void * fdto , int node )
{
int property ;
int node ;
int sub node;
fdt_for_each_property_offset ( property , fdto , fragment ) {
fdt_for_each_property_offset ( property , fdto , node ) {
const char * name ;
const void * prop ;
int prop_len ;
@ -511,19 +554,22 @@ static int overlay_apply_node(void *fdt, int target,
return ret ;
}
fdt_for_each_subnode ( node , fdto , fragment ) {
const char * name = fdt_get_name ( fdto , node , NULL ) ;
fdt_for_each_subnode ( sub node, fdto , node ) {
const char * name = fdt_get_name ( fdto , sub node, NULL ) ;
int nnode ;
int ret ;
nnode = fdt_add_subnode ( fdt , target , name ) ;
if ( nnode = = - FDT_ERR_EXISTS )
if ( nnode = = - FDT_ERR_EXISTS ) {
nnode = fdt_subnode_offset ( fdt , target , name ) ;
if ( nnode = = - FDT_ERR_NOTFOUND )
return - FDT_ERR_INTERNAL ;
}
if ( nnode < 0 )
return nnode ;
ret = overlay_apply_node ( fdt , nnode , fdto , node ) ;
ret = overlay_apply_node ( fdt , nnode , fdto , sub node) ;
if ( ret )
return ret ;
}
@ -546,24 +592,31 @@ static int overlay_apply_node(void *fdt, int target,
* 0 on success
* Negative error code on failure
*/
static int overlay_merge ( void * dt , void * dto )
static int overlay_merge ( void * f dt, void * f dto)
{
int fragment ;
fdt_for_each_subnode ( fragment , dto , 0 ) {
fdt_for_each_subnode ( fragment , f dto, 0 ) {
int overlay ;
int target ;
int ret ;
target = overlay_get_target ( dt , dto , fragment ) ;
if ( target < 0 )
/*
* Each fragments will have an __overlay__ node . If
* they don ' t , it ' s not supposed to be merged
*/
overlay = fdt_subnode_offset ( fdto , fragment , " __overlay__ " ) ;
if ( overlay = = - FDT_ERR_NOTFOUND )
continue ;
overlay = fdt_subnode_offset ( dto , fragment , " __overlay__ " ) ;
if ( overlay < 0 )
return overlay ;
ret = overlay_apply_node ( dt , target , dto , overlay ) ;
target = overlay_get_target ( fdt , fdto , fragment ) ;
if ( target < 0 )
return target ;
ret = overlay_apply_node ( fdt , target , fdto , overlay ) ;
if ( ret )
return ret ;
}
@ -573,7 +626,7 @@ static int overlay_merge(void *dt, void *dto)
int fdt_overlay_apply ( void * fdt , void * fdto )
{
uint32_t delta = fdt_get_max_phandle ( fdt ) + 1 ;
uint32_t delta = fdt_get_max_phandle ( fdt ) ;
int ret ;
FDT_CHECK_HEADER ( fdt ) ;