1*4882a593SmuzhiyunDesign Notes on Exporting U-Boot Functions to Standalone Applications: 2*4882a593Smuzhiyun====================================================================== 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun1. The functions are exported by U-Boot via a jump table. The jump 5*4882a593Smuzhiyun table is allocated and initialized in the jumptable_init() routine 6*4882a593Smuzhiyun (common/exports.c). Other routines may also modify the jump table, 7*4882a593Smuzhiyun however. The jump table can be accessed as the 'jt' field of the 8*4882a593Smuzhiyun 'global_data' structure. The struct members for the jump table are 9*4882a593Smuzhiyun defined in the <include/exports.h> header. E.g., to substitute the 10*4882a593Smuzhiyun malloc() and free() functions that will be available to standalone 11*4882a593Smuzhiyun applications, one should do the following: 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR; 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun gd->jt->malloc = my_malloc; 16*4882a593Smuzhiyun gd->jt->free = my_free; 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun Note that the pointers to the functions are real function pointers 19*4882a593Smuzhiyun so the compiler can perform type checks on these assignments. 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun2. The pointer to the jump table is passed to the application in a 22*4882a593Smuzhiyun machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II 23*4882a593Smuzhiyun architectures use a dedicated register to hold the pointer to the 24*4882a593Smuzhiyun 'global_data' structure: r2 on PowerPC, r9 on ARM, k0 on MIPS, 25*4882a593Smuzhiyun P3 on Blackfin and gp on Nios II. The x86 architecture does not 26*4882a593Smuzhiyun use such a register; instead, the pointer to the 'global_data' 27*4882a593Smuzhiyun structure is passed as 'argv[-1]' pointer. 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun The application can access the 'global_data' structure in the same 30*4882a593Smuzhiyun way as U-Boot does: 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR; 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun printf("U-Boot relocation offset: %x\n", gd->reloc_off); 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun3. The application should call the app_startup() function before any 37*4882a593Smuzhiyun call to the exported functions. Also, implementor of the 38*4882a593Smuzhiyun application may want to check the version of the ABI provided by 39*4882a593Smuzhiyun U-Boot. To facilitate this, a get_version() function is exported 40*4882a593Smuzhiyun that returns the ABI version of the running U-Boot. I.e., a 41*4882a593Smuzhiyun typical application startup may look like this: 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun int my_app (int argc, char * const argv[]) 44*4882a593Smuzhiyun { 45*4882a593Smuzhiyun app_startup (argv); 46*4882a593Smuzhiyun if (get_version () != XF_VERSION) 47*4882a593Smuzhiyun return 1; 48*4882a593Smuzhiyun } 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun4. The default load and start addresses of the applications are as 51*4882a593Smuzhiyun follows: 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun Load address Start address 54*4882a593Smuzhiyun x86 0x00040000 0x00040000 55*4882a593Smuzhiyun PowerPC 0x00040000 0x00040004 56*4882a593Smuzhiyun ARM 0x0c100000 0x0c100000 57*4882a593Smuzhiyun MIPS 0x80200000 0x80200000 58*4882a593Smuzhiyun Blackfin 0x00001000 0x00001000 59*4882a593Smuzhiyun NDS32 0x00300000 0x00300000 60*4882a593Smuzhiyun Nios II 0x02000000 0x02000000 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun For example, the "hello world" application may be loaded and 63*4882a593Smuzhiyun executed on a PowerPC board with the following commands: 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun => tftp 0x40000 hello_world.bin 66*4882a593Smuzhiyun => go 0x40004 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun5. To export some additional function long foobar(int i,char c), the following steps 69*4882a593Smuzhiyun should be undertaken: 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun - Append the following line at the end of the include/_exports.h 72*4882a593Smuzhiyun file: 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun EXPORT_FUNC(foobar, long, foobar, int, char) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun Parameters to EXPORT_FUNC: 77*4882a593Smuzhiyun - the first parameter is the function that is exported (default implementation) 78*4882a593Smuzhiyun - the second parameter is the return value type 79*4882a593Smuzhiyun - the third parameter is the name of the member in struct jt_funcs 80*4882a593Smuzhiyun this is also the name that the standalone application will used. 81*4882a593Smuzhiyun the rest of the parameters are the function arguments 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun - Add the prototype for this function to the include/exports.h 84*4882a593Smuzhiyun file: 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun long foobar(int i, char c); 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun Initialization with the default implementation is done in jumptable_init() 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun You can override the default implementation using: 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun gd->jt->foobar = another_foobar; 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun The signature of another_foobar must then match the declaration of foobar. 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun - Increase the XF_VERSION value by one in the include/exports.h 97*4882a593Smuzhiyun file 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun - If you want to export a function which depends on a CONFIG_XXX 100*4882a593Smuzhiyun use 2 lines like this: 101*4882a593Smuzhiyun #ifdef CONFIG_FOOBAR 102*4882a593Smuzhiyun EXPORT_FUNC(foobar, long, foobar, int, char) 103*4882a593Smuzhiyun #else 104*4882a593Smuzhiyun EXPORT_FUNC(dummy, void, foobar, void) 105*4882a593Smuzhiyun #endif 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun6. The code for exporting the U-Boot functions to applications is 109*4882a593Smuzhiyun mostly machine-independent. The only places written in assembly 110*4882a593Smuzhiyun language are stub functions that perform the jump through the jump 111*4882a593Smuzhiyun table. That said, to port this code to a new architecture, the 112*4882a593Smuzhiyun only thing to be provided is the code in the examples/stubs.c 113*4882a593Smuzhiyun file. If this architecture, however, uses some uncommon method of 114*4882a593Smuzhiyun passing the 'global_data' pointer (like x86 does), one should add 115*4882a593Smuzhiyun the respective code to the app_startup() function in that file. 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun Note that these functions may only use call-clobbered registers; 118*4882a593Smuzhiyun those registers that are used to pass the function's arguments, 119*4882a593Smuzhiyun the stack contents and the return address should be left intact. 120