2019-06-21 08:18:32 -06:00
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2007-12-10 14:28:39 +11:00
/*
* libfdt - Flat Device Tree manipulation
* Copyright ( C ) 2006 David Gibson , IBM Corporation .
*/
# include "libfdt_env.h"
# include <fdt.h>
# include <libfdt.h>
# include "libfdt_internal.h"
2018-02-27 17:40:38 -06:00
static int fdt_blocks_misordered_ ( const void * fdt ,
int mem_rsv_size , int struct_size )
2007-12-10 14:28:39 +11:00
{
2008-08-07 12:24:17 +10:00
return ( fdt_off_mem_rsvmap ( fdt ) < FDT_ALIGN ( sizeof ( struct fdt_header ) , 8 ) )
2007-12-10 14:28:39 +11:00
| | ( fdt_off_dt_struct ( fdt ) <
( fdt_off_mem_rsvmap ( fdt ) + mem_rsv_size ) )
| | ( fdt_off_dt_strings ( fdt ) <
( fdt_off_dt_struct ( fdt ) + struct_size ) )
| | ( fdt_totalsize ( fdt ) <
( fdt_off_dt_strings ( fdt ) + fdt_size_dt_strings ( fdt ) ) ) ;
}
2018-09-13 08:59:25 -05:00
static int fdt_rw_probe_ ( void * fdt )
2007-12-10 14:28:39 +11:00
{
2020-03-13 08:56:58 -05:00
if ( can_assume ( VALID_DTB ) )
return 0 ;
2018-09-13 08:59:25 -05:00
FDT_RO_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
2020-03-13 08:56:58 -05:00
if ( ! can_assume ( LATEST ) & & fdt_version ( fdt ) < 17 )
2007-12-10 14:28:39 +11:00
return - FDT_ERR_BADVERSION ;
2018-02-27 17:40:38 -06:00
if ( fdt_blocks_misordered_ ( fdt , sizeof ( struct fdt_reserve_entry ) ,
2008-08-07 12:24:17 +10:00
fdt_size_dt_struct ( fdt ) ) )
2007-12-10 14:28:39 +11:00
return - FDT_ERR_BADLAYOUT ;
2020-03-13 08:56:58 -05:00
if ( ! can_assume ( LATEST ) & & fdt_version ( fdt ) > 17 )
2007-12-10 14:28:39 +11:00
fdt_set_version ( fdt , 17 ) ;
return 0 ;
}
2018-09-13 08:59:25 -05:00
# define FDT_RW_PROBE(fdt) \
2007-12-10 14:28:39 +11:00
{ \
2018-02-27 17:40:38 -06:00
int err_ ; \
2018-09-13 08:59:25 -05:00
if ( ( err_ = fdt_rw_probe_ ( fdt ) ) ! = 0 ) \
2018-02-27 17:40:38 -06:00
return err_ ; \
2007-12-10 14:28:39 +11:00
}
2020-03-13 08:56:58 -05:00
static inline unsigned int fdt_data_size_ ( void * fdt )
2007-12-10 14:28:39 +11:00
{
return fdt_off_dt_strings ( fdt ) + fdt_size_dt_strings ( fdt ) ;
}
2018-02-27 17:40:38 -06:00
static int fdt_splice_ ( void * fdt , void * splicepoint , int oldlen , int newlen )
2007-12-10 14:28:39 +11:00
{
2008-08-07 12:24:17 +10:00
char * p = splicepoint ;
2020-03-13 08:56:58 -05:00
unsigned int dsize = fdt_data_size_ ( fdt ) ;
size_t soff = p - ( char * ) fdt ;
2007-12-10 14:28:39 +11:00
2020-03-13 08:56:58 -05:00
if ( ( oldlen < 0 ) | | ( soff + oldlen < soff ) | | ( soff + oldlen > dsize ) )
2007-12-10 14:28:39 +11:00
return - FDT_ERR_BADOFFSET ;
2020-10-12 09:58:15 -05:00
if ( ( p < ( char * ) fdt ) | | ( dsize + newlen < ( unsigned ) oldlen ) )
2016-01-26 09:04:11 -06:00
return - FDT_ERR_BADOFFSET ;
2020-03-13 08:56:58 -05:00
if ( dsize - oldlen + newlen > fdt_totalsize ( fdt ) )
2007-12-10 14:28:39 +11:00
return - FDT_ERR_NOSPACE ;
2020-03-13 08:56:58 -05:00
memmove ( p + newlen , p + oldlen , ( ( char * ) fdt + dsize ) - ( p + oldlen ) ) ;
2007-12-10 14:28:39 +11:00
return 0 ;
}
2018-02-27 17:40:38 -06:00
static int fdt_splice_mem_rsv_ ( void * fdt , struct fdt_reserve_entry * p ,
2008-08-07 12:24:17 +10:00
int oldn , int newn )
2007-12-10 14:28:39 +11:00
{
int delta = ( newn - oldn ) * sizeof ( * p ) ;
int err ;
2018-02-27 17:40:38 -06:00
err = fdt_splice_ ( fdt , p , oldn * sizeof ( * p ) , newn * sizeof ( * p ) ) ;
2007-12-10 14:28:39 +11:00
if ( err )
return err ;
fdt_set_off_dt_struct ( fdt , fdt_off_dt_struct ( fdt ) + delta ) ;
fdt_set_off_dt_strings ( fdt , fdt_off_dt_strings ( fdt ) + delta ) ;
return 0 ;
}
2018-02-27 17:40:38 -06:00
static int fdt_splice_struct_ ( void * fdt , void * p ,
2008-08-07 12:24:17 +10:00
int oldlen , int newlen )
2007-12-10 14:28:39 +11:00
{
int delta = newlen - oldlen ;
int err ;
2018-02-27 17:40:38 -06:00
if ( ( err = fdt_splice_ ( fdt , p , oldlen , newlen ) ) )
2007-12-10 14:28:39 +11:00
return err ;
fdt_set_size_dt_struct ( fdt , fdt_size_dt_struct ( fdt ) + delta ) ;
fdt_set_off_dt_strings ( fdt , fdt_off_dt_strings ( fdt ) + delta ) ;
return 0 ;
}
2019-06-12 07:05:52 -06:00
/* Must only be used to roll back in case of error */
static void fdt_del_last_string_ ( void * fdt , const char * s )
{
int newlen = strlen ( s ) + 1 ;
fdt_set_size_dt_strings ( fdt , fdt_size_dt_strings ( fdt ) - newlen ) ;
}
2018-02-27 17:40:38 -06:00
static int fdt_splice_string_ ( void * fdt , int newlen )
2007-12-10 14:28:39 +11:00
{
2008-08-07 12:24:17 +10:00
void * p = ( char * ) fdt
+ fdt_off_dt_strings ( fdt ) + fdt_size_dt_strings ( fdt ) ;
2007-12-10 14:28:39 +11:00
int err ;
2018-02-27 17:40:38 -06:00
if ( ( err = fdt_splice_ ( fdt , p , 0 , newlen ) ) )
2007-12-10 14:28:39 +11:00
return err ;
fdt_set_size_dt_strings ( fdt , fdt_size_dt_strings ( fdt ) + newlen ) ;
return 0 ;
}
2020-03-13 08:56:58 -05:00
/**
* fdt_find_add_string_ ( ) - Find or allocate a string
*
* @ fdt : pointer to the device tree to check / adjust
* @ s : string to find / add
* @ allocated : Set to 0 if the string was found , 1 if not found and so
* allocated . Ignored if can_assume ( NO_ROLLBACK )
* @ return offset of string in the string table ( whether found or added )
*/
2019-06-12 07:05:52 -06:00
static int fdt_find_add_string_ ( void * fdt , const char * s , int * allocated )
2007-12-10 14:28:39 +11:00
{
char * strtab = ( char * ) fdt + fdt_off_dt_strings ( fdt ) ;
const char * p ;
char * new ;
int len = strlen ( s ) + 1 ;
int err ;
2020-03-13 08:56:58 -05:00
if ( ! can_assume ( NO_ROLLBACK ) )
* allocated = 0 ;
2019-06-12 07:05:52 -06:00
2018-02-27 17:40:38 -06:00
p = fdt_find_string_ ( strtab , fdt_size_dt_strings ( fdt ) , s ) ;
2007-12-10 14:28:39 +11:00
if ( p )
/* found it */
return ( p - strtab ) ;
new = strtab + fdt_size_dt_strings ( fdt ) ;
2018-02-27 17:40:38 -06:00
err = fdt_splice_string_ ( fdt , len ) ;
2007-12-10 14:28:39 +11:00
if ( err )
return err ;
2020-03-13 08:56:58 -05:00
if ( ! can_assume ( NO_ROLLBACK ) )
* allocated = 1 ;
2019-06-12 07:05:52 -06:00
2007-12-10 14:28:39 +11:00
memcpy ( new , s , len ) ;
return ( new - strtab ) ;
}
int fdt_add_mem_rsv ( void * fdt , uint64_t address , uint64_t size )
{
struct fdt_reserve_entry * re ;
int err ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
re = fdt_mem_rsv_w_ ( fdt , fdt_num_mem_rsv ( fdt ) ) ;
err = fdt_splice_mem_rsv_ ( fdt , re , 0 , 1 ) ;
2007-12-10 14:28:39 +11:00
if ( err )
return err ;
re - > address = cpu_to_fdt64 ( address ) ;
re - > size = cpu_to_fdt64 ( size ) ;
return 0 ;
}
int fdt_del_mem_rsv ( void * fdt , int n )
{
2018-02-27 17:40:38 -06:00
struct fdt_reserve_entry * re = fdt_mem_rsv_w_ ( fdt , n ) ;
2007-12-10 14:28:39 +11:00
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2008-08-07 12:24:17 +10:00
2007-12-10 14:28:39 +11:00
if ( n > = fdt_num_mem_rsv ( fdt ) )
return - FDT_ERR_NOTFOUND ;
2018-02-27 17:40:38 -06:00
return fdt_splice_mem_rsv_ ( fdt , re , 1 , 0 ) ;
2007-12-10 14:28:39 +11:00
}
2018-02-27 17:40:38 -06:00
static int fdt_resize_property_ ( void * fdt , int nodeoffset , const char * name ,
2008-08-07 12:24:17 +10:00
int len , struct fdt_property * * prop )
2007-12-10 14:28:39 +11:00
{
int oldlen ;
int err ;
* prop = fdt_get_property_w ( fdt , nodeoffset , name , & oldlen ) ;
2017-10-03 11:37:04 -05:00
if ( ! * prop )
2007-12-10 14:28:39 +11:00
return oldlen ;
2018-02-27 17:40:38 -06:00
if ( ( err = fdt_splice_struct_ ( fdt , ( * prop ) - > data , FDT_TAGALIGN ( oldlen ) ,
2008-08-07 12:24:17 +10:00
FDT_TAGALIGN ( len ) ) ) )
2007-12-10 14:28:39 +11:00
return err ;
( * prop ) - > len = cpu_to_fdt32 ( len ) ;
return 0 ;
}
2018-02-27 17:40:38 -06:00
static int fdt_add_property_ ( void * fdt , int nodeoffset , const char * name ,
2008-08-07 12:24:17 +10:00
int len , struct fdt_property * * prop )
2007-12-10 14:28:39 +11:00
{
int proplen ;
int nextoffset ;
int namestroff ;
int err ;
2019-06-12 07:05:52 -06:00
int allocated ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
if ( ( nextoffset = fdt_check_node_offset_ ( fdt , nodeoffset ) ) < 0 )
2008-08-07 12:24:17 +10:00
return nextoffset ;
2007-12-10 14:28:39 +11:00
2019-06-12 07:05:52 -06:00
namestroff = fdt_find_add_string_ ( fdt , name , & allocated ) ;
2007-12-10 14:28:39 +11:00
if ( namestroff < 0 )
return namestroff ;
2018-02-27 17:40:38 -06:00
* prop = fdt_offset_ptr_w_ ( fdt , nextoffset ) ;
2008-08-07 12:24:17 +10:00
proplen = sizeof ( * * prop ) + FDT_TAGALIGN ( len ) ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
err = fdt_splice_struct_ ( fdt , * prop , 0 , proplen ) ;
2019-06-12 07:05:52 -06:00
if ( err ) {
2020-03-13 08:56:58 -05:00
/* Delete the string if we failed to add it */
if ( ! can_assume ( NO_ROLLBACK ) & & allocated )
2019-06-12 07:05:52 -06:00
fdt_del_last_string_ ( fdt , name ) ;
2007-12-10 14:28:39 +11:00
return err ;
2019-06-12 07:05:52 -06:00
}
2007-12-10 14:28:39 +11:00
( * prop ) - > tag = cpu_to_fdt32 ( FDT_PROP ) ;
( * prop ) - > nameoff = cpu_to_fdt32 ( namestroff ) ;
( * prop ) - > len = cpu_to_fdt32 ( len ) ;
return 0 ;
}
2008-08-07 12:24:17 +10:00
int fdt_set_name ( void * fdt , int nodeoffset , const char * name )
{
char * namep ;
int oldlen , newlen ;
int err ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2008-08-07 12:24:17 +10:00
namep = ( char * ) ( uintptr_t ) fdt_get_name ( fdt , nodeoffset , & oldlen ) ;
if ( ! namep )
return oldlen ;
newlen = strlen ( name ) ;
2018-02-27 17:40:38 -06:00
err = fdt_splice_struct_ ( fdt , namep , FDT_TAGALIGN ( oldlen + 1 ) ,
2008-08-07 12:24:17 +10:00
FDT_TAGALIGN ( newlen + 1 ) ) ;
if ( err )
return err ;
memcpy ( namep , name , newlen + 1 ) ;
return 0 ;
}
2017-10-03 11:37:04 -05:00
int fdt_setprop_placeholder ( void * fdt , int nodeoffset , const char * name ,
int len , void * * prop_data )
2007-12-10 14:28:39 +11:00
{
struct fdt_property * prop ;
int err ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
err = fdt_resize_property_ ( fdt , nodeoffset , name , len , & prop ) ;
2007-12-10 14:28:39 +11:00
if ( err = = - FDT_ERR_NOTFOUND )
2018-02-27 17:40:38 -06:00
err = fdt_add_property_ ( fdt , nodeoffset , name , len , & prop ) ;
2007-12-10 14:28:39 +11:00
if ( err )
return err ;
2017-10-03 11:37:04 -05:00
* prop_data = prop - > data ;
return 0 ;
}
int fdt_setprop ( void * fdt , int nodeoffset , const char * name ,
const void * val , int len )
{
void * prop_data ;
int err ;
err = fdt_setprop_placeholder ( fdt , nodeoffset , name , len , & prop_data ) ;
if ( err )
return err ;
2017-03-21 09:01:08 -05:00
if ( len )
2017-10-03 11:37:04 -05:00
memcpy ( prop_data , val , len ) ;
2007-12-10 14:28:39 +11:00
return 0 ;
}
2012-09-28 21:25:59 +00:00
int fdt_appendprop ( void * fdt , int nodeoffset , const char * name ,
const void * val , int len )
{
struct fdt_property * prop ;
int err , oldlen , newlen ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2012-09-28 21:25:59 +00:00
prop = fdt_get_property_w ( fdt , nodeoffset , name , & oldlen ) ;
if ( prop ) {
newlen = len + oldlen ;
2018-02-27 17:40:38 -06:00
err = fdt_splice_struct_ ( fdt , prop - > data ,
2012-09-28 21:25:59 +00:00
FDT_TAGALIGN ( oldlen ) ,
FDT_TAGALIGN ( newlen ) ) ;
if ( err )
return err ;
prop - > len = cpu_to_fdt32 ( newlen ) ;
memcpy ( prop - > data + oldlen , val , len ) ;
} else {
2018-02-27 17:40:38 -06:00
err = fdt_add_property_ ( fdt , nodeoffset , name , len , & prop ) ;
2012-09-28 21:25:59 +00:00
if ( err )
return err ;
memcpy ( prop - > data , val , len ) ;
}
return 0 ;
}
2007-12-10 14:28:39 +11:00
int fdt_delprop ( void * fdt , int nodeoffset , const char * name )
{
struct fdt_property * prop ;
int len , proplen ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
prop = fdt_get_property_w ( fdt , nodeoffset , name , & len ) ;
2017-10-03 11:37:04 -05:00
if ( ! prop )
2007-12-10 14:28:39 +11:00
return len ;
2008-08-07 12:24:17 +10:00
proplen = sizeof ( * prop ) + FDT_TAGALIGN ( len ) ;
2018-02-27 17:40:38 -06:00
return fdt_splice_struct_ ( fdt , prop , proplen , 0 ) ;
2007-12-10 14:28:39 +11:00
}
int fdt_add_subnode_namelen ( void * fdt , int parentoffset ,
const char * name , int namelen )
{
struct fdt_node_header * nh ;
int offset , nextoffset ;
int nodelen ;
int err ;
uint32_t tag ;
2015-04-29 16:00:05 -05:00
fdt32_t * endtag ;
2007-12-10 14:28:39 +11:00
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
offset = fdt_subnode_offset_namelen ( fdt , parentoffset , name , namelen ) ;
if ( offset > = 0 )
return - FDT_ERR_EXISTS ;
else if ( offset ! = - FDT_ERR_NOTFOUND )
return offset ;
/* Try to place the new node after the parent's properties */
2021-10-25 11:05:45 -05:00
tag = fdt_next_tag ( fdt , parentoffset , & nextoffset ) ;
/* the fdt_subnode_offset_namelen() should ensure this never hits */
if ( ! can_assume ( LIBFDT_FLAWLESS ) & & ( tag ! = FDT_BEGIN_NODE ) )
return - FDT_ERR_INTERNAL ;
2007-12-10 14:28:39 +11:00
do {
offset = nextoffset ;
tag = fdt_next_tag ( fdt , offset , & nextoffset ) ;
2008-08-07 12:24:17 +10:00
} while ( ( tag = = FDT_PROP ) | | ( tag = = FDT_NOP ) ) ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
nh = fdt_offset_ptr_w_ ( fdt , offset ) ;
2008-08-07 12:24:17 +10:00
nodelen = sizeof ( * nh ) + FDT_TAGALIGN ( namelen + 1 ) + FDT_TAGSIZE ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
err = fdt_splice_struct_ ( fdt , nh , 0 , nodelen ) ;
2007-12-10 14:28:39 +11:00
if ( err )
return err ;
nh - > tag = cpu_to_fdt32 ( FDT_BEGIN_NODE ) ;
2008-08-07 12:24:17 +10:00
memset ( nh - > name , 0 , FDT_TAGALIGN ( namelen + 1 ) ) ;
2007-12-10 14:28:39 +11:00
memcpy ( nh - > name , name , namelen ) ;
2015-04-29 16:00:05 -05:00
endtag = ( fdt32_t * ) ( ( char * ) nh + nodelen - FDT_TAGSIZE ) ;
2007-12-10 14:28:39 +11:00
* endtag = cpu_to_fdt32 ( FDT_END_NODE ) ;
return offset ;
}
int fdt_add_subnode ( void * fdt , int parentoffset , const char * name )
{
return fdt_add_subnode_namelen ( fdt , parentoffset , name , strlen ( name ) ) ;
}
int fdt_del_node ( void * fdt , int nodeoffset )
{
int endoffset ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
2018-02-27 17:40:38 -06:00
endoffset = fdt_node_end_offset_ ( fdt , nodeoffset ) ;
2007-12-10 14:28:39 +11:00
if ( endoffset < 0 )
return endoffset ;
2018-02-27 17:40:38 -06:00
return fdt_splice_struct_ ( fdt , fdt_offset_ptr_w_ ( fdt , nodeoffset ) ,
2008-08-07 12:24:17 +10:00
endoffset - nodeoffset , 0 ) ;
2007-12-10 14:28:39 +11:00
}
2018-02-27 17:40:38 -06:00
static void fdt_packblocks_ ( const char * old , char * new ,
2021-10-25 11:05:45 -05:00
int mem_rsv_size ,
int struct_size ,
int strings_size )
2007-12-10 14:28:39 +11:00
{
int mem_rsv_off , struct_off , strings_off ;
2008-08-07 12:24:17 +10:00
mem_rsv_off = FDT_ALIGN ( sizeof ( struct fdt_header ) , 8 ) ;
2007-12-10 14:28:39 +11:00
struct_off = mem_rsv_off + mem_rsv_size ;
strings_off = struct_off + struct_size ;
2008-08-07 12:24:17 +10:00
memmove ( new + mem_rsv_off , old + fdt_off_mem_rsvmap ( old ) , mem_rsv_size ) ;
fdt_set_off_mem_rsvmap ( new , mem_rsv_off ) ;
2007-12-10 14:28:39 +11:00
2008-08-07 12:24:17 +10:00
memmove ( new + struct_off , old + fdt_off_dt_struct ( old ) , struct_size ) ;
fdt_set_off_dt_struct ( new , struct_off ) ;
fdt_set_size_dt_struct ( new , struct_size ) ;
2007-12-10 14:28:39 +11:00
2021-10-25 11:05:45 -05:00
memmove ( new + strings_off , old + fdt_off_dt_strings ( old ) , strings_size ) ;
2008-08-07 12:24:17 +10:00
fdt_set_off_dt_strings ( new , strings_off ) ;
fdt_set_size_dt_strings ( new , fdt_size_dt_strings ( old ) ) ;
2007-12-10 14:28:39 +11:00
}
int fdt_open_into ( const void * fdt , void * buf , int bufsize )
{
int err ;
int mem_rsv_size , struct_size ;
int newsize ;
2008-08-07 12:24:17 +10:00
const char * fdtstart = fdt ;
const char * fdtend = fdtstart + fdt_totalsize ( fdt ) ;
char * tmp ;
2007-12-10 14:28:39 +11:00
2018-09-13 08:59:25 -05:00
FDT_RO_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
mem_rsv_size = ( fdt_num_mem_rsv ( fdt ) + 1 )
* sizeof ( struct fdt_reserve_entry ) ;
2020-03-13 08:56:58 -05:00
if ( can_assume ( LATEST ) | | fdt_version ( fdt ) > = 17 ) {
2007-12-10 14:28:39 +11:00
struct_size = fdt_size_dt_struct ( fdt ) ;
2021-02-03 15:26:03 -06:00
} else if ( fdt_version ( fdt ) = = 16 ) {
2007-12-10 14:28:39 +11:00
struct_size = 0 ;
while ( fdt_next_tag ( fdt , struct_size , & struct_size ) ! = FDT_END )
;
2012-09-28 21:25:59 +00:00
if ( struct_size < 0 )
return struct_size ;
2021-02-03 15:26:03 -06:00
} else {
return - FDT_ERR_BADVERSION ;
2007-12-10 14:28:39 +11:00
}
2020-06-29 12:15:13 -06:00
if ( can_assume ( LIBFDT_ORDER ) | |
2020-03-13 08:56:58 -05:00
! fdt_blocks_misordered_ ( fdt , mem_rsv_size , struct_size ) ) {
2007-12-10 14:28:39 +11:00
/* no further work necessary */
err = fdt_move ( fdt , buf , bufsize ) ;
if ( err )
return err ;
fdt_set_version ( buf , 17 ) ;
fdt_set_size_dt_struct ( buf , struct_size ) ;
fdt_set_totalsize ( buf , bufsize ) ;
return 0 ;
}
/* Need to reorder */
2008-08-07 12:24:17 +10:00
newsize = FDT_ALIGN ( sizeof ( struct fdt_header ) , 8 ) + mem_rsv_size
2007-12-10 14:28:39 +11:00
+ struct_size + fdt_size_dt_strings ( fdt ) ;
if ( bufsize < newsize )
return - FDT_ERR_NOSPACE ;
2008-08-07 12:24:17 +10:00
/* First attempt to build converted tree at beginning of buffer */
tmp = buf ;
/* But if that overlaps with the old tree... */
if ( ( ( tmp + newsize ) > fdtstart ) & & ( tmp < fdtend ) ) {
/* Try right after the old tree instead */
tmp = ( char * ) ( uintptr_t ) fdtend ;
if ( ( tmp + newsize ) > ( ( char * ) buf + bufsize ) )
2007-12-10 14:28:39 +11:00
return - FDT_ERR_NOSPACE ;
}
2021-10-25 11:05:45 -05:00
fdt_packblocks_ ( fdt , tmp , mem_rsv_size , struct_size ,
fdt_size_dt_strings ( fdt ) ) ;
2007-12-10 14:28:39 +11:00
memmove ( buf , tmp , newsize ) ;
fdt_set_magic ( buf , FDT_MAGIC ) ;
fdt_set_totalsize ( buf , bufsize ) ;
fdt_set_version ( buf , 17 ) ;
fdt_set_last_comp_version ( buf , 16 ) ;
fdt_set_boot_cpuid_phys ( buf , fdt_boot_cpuid_phys ( fdt ) ) ;
return 0 ;
}
int fdt_pack ( void * fdt )
{
int mem_rsv_size ;
2018-09-13 08:59:25 -05:00
FDT_RW_PROBE ( fdt ) ;
2007-12-10 14:28:39 +11:00
mem_rsv_size = ( fdt_num_mem_rsv ( fdt ) + 1 )
* sizeof ( struct fdt_reserve_entry ) ;
2021-10-25 11:05:45 -05:00
fdt_packblocks_ ( fdt , fdt , mem_rsv_size , fdt_size_dt_struct ( fdt ) ,
fdt_size_dt_strings ( fdt ) ) ;
2018-02-27 17:40:38 -06:00
fdt_set_totalsize ( fdt , fdt_data_size_ ( fdt ) ) ;
2007-12-10 14:28:39 +11:00
return 0 ;
}