@ -29,31 +29,120 @@ __weak void arch_setup_gd(struct global_data *gd_ptr)
}
# endif /* !CONFIG_X86 */
ulong board_init_f_mem ( ulong top )
/*
* Allocate reserved space for use as ' globals ' from ' top ' address and
* return ' bottom ' address of allocated space
*
* Notes :
*
* Actual reservation cannot be done from within this function as
* it requires altering the C stack pointer , so this will be done by
* the caller upon return from this function .
*
* IMPORTANT :
*
* Alignment constraints may differ for each ' chunk ' allocated . For now :
*
* - GD is aligned down on a 16 - byte boundary
*
* - the early malloc arena is not aligned , therefore it follows the stack
* alignment constraint of the architecture for which we are bulding .
*
* - GD is allocated last , so that the return value of this functions is
* both the bottom of the reserved area and the address of GD , should
* the calling context need it .
*/
ulong board_init_f_alloc_reserve ( ulong top )
{
/* Reserve early malloc arena */
# if defined(CONFIG_SYS_MALLOC_F)
top - = CONFIG_SYS_MALLOC_F_LEN ;
# endif
/* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
top = rounddown ( top - sizeof ( struct global_data ) , 16 ) ;
return top ;
}
/*
* Initialize reserved space ( which has been safely allocated on the C
* stack from the C runtime environment handling code ) .
*
* Notes :
*
* Actual reservation was done by the caller ; the locations from base
* to base + size - 1 ( where ' size ' is the value returned by the allocation
* function above ) can be accessed freely without risk of corrupting the
* C runtime environment .
*
* IMPORTANT :
*
* Upon return from the allocation function above , on some architectures
* the caller will set gd to the lowest reserved location . Therefore , in
* this initialization function , the global data MUST be placed at base .
*
* ALSO IMPORTANT :
*
* On some architectures , gd will already be good when entering this
* function . On others , it will only be good once arch_setup_gd ( ) returns .
* Therefore , global data accesses must be done :
*
* - through gd_ptr if before the call to arch_setup_gd ( ) ;
*
* - through gd once arch_setup_gd ( ) has been called .
*
* Do not use ' gd - > ' until arch_setup_gd ( ) has been called !
*
* IMPORTANT TOO :
*
* Initialization for each " chunk " ( GD , early malloc arena . . . ) ends with
* an incrementation line of the form ' base + = < some size > ' . The last of
* these incrementations seems useless , as base will not be used any
* more after this incrementation ; but if / when a new " chunk " is appended ,
* this increment will be essential as it will give base right value for
* this new chunk ( which will have to end with its own incrementation
* statement ) . Besides , the compiler ' s optimizer will silently detect
* and remove the last base incrementation , therefore leaving that last
* ( seemingly useless ) incrementation causes no code increase .
*/
void board_init_f_init_reserve ( ulong base )
{
struct global_data * gd_ptr ;
# ifndef _USE_MEMCPY
int * ptr ;
# endif
/* Leave space for the stack we are running with now */
top - = 0x40 ;
/*
* clear GD entirely and set it up .
* Use gd_ptr , as gd may not be properly set yet .
*/
top - = sizeof ( struct global_data ) ;
top = ALIGN ( top , 16 ) ;
gd_ptr = ( struct global_data * ) top ;
gd_ptr = ( struct global_data * ) base ;
/* zero the area */
# ifdef _USE_MEMCPY
memset ( gd_ptr , ' \0 ' , sizeof ( * gd ) ) ;
# else
for ( ptr = ( int * ) gd_ptr ; ptr < ( int * ) ( gd_ptr + 1 ) ; )
* ptr + + = 0 ;
# endif
/* set GD unless architecture did it already */
# ifndef CONFIG_X86
arch_setup_gd ( gd_ptr ) ;
# endif
/* next alloc will be higher by one GD plus 16-byte alignment */
base + = roundup ( sizeof ( struct global_data ) , 16 ) ;
/*
* record early malloc arena start .
* Use gd as it is now properly set for all architectures .
*/
# if defined(CONFIG_SYS_MALLOC_F)
top - = CONFIG_SYS_MALLOC_F_LEN ;
gd - > malloc_base = top ;
/* go down one 'early malloc arena' */
gd - > malloc_base = base ;
/* next alloc will be higher by one 'early malloc arena' size */
base + = CONFIG_SYS_MALLOC_F_LEN ;
# endif
return top ;
}