Is there a way to call U-Boot API functions from within an ARM program loaded with the go command ?
I see that the U-Boot API is available after startup at an address defined in the environment variable api_address but i can't make sens of how to use it.
For example, if i want to call the getc function that ones see in U-Boot api/api.c, how do i actually call it from within an assembly program ?
I tried this (on ARM1176JZF-S board) but this crash :
.global _start
_start:
ldr r0, =0x1BB89148 ; api_address value
ldr r1, [r0, #32] ; offset to get getc location
bx r1 ; call getc
The rational was to call the second function (API_getc) from the syscall_table initialized in U-Boot api.c with r0 being the value of api_address.
Looks like i was misguided with api_address as it is not the address of the jump table but the api_signature struct defined in api/api.c, this hold a syscall member which is the address of the syscall function defined in that same file, this function can be used to call the U-Boot API (the api example show that)
So for API call this works :
// U-Boot API call
ldr r4, =0x1bba50b0 // "api_address" value (U-Boot env. variable)
mov r0, #1 // U-Boot syscall number (getc)
mov r1, #0 // retval argument
add r2, sp, #4 // address of getc returned value
mov lr, pc
ldr pc, [r4, #16] // call syscall(1, 0, &v)
ldr r3, [sp, #4] // get getc returned value in r3
This works to call any API functions defined in include/api_public.h below the api_signature struct
The standalone example works a bit differently doc/README.standalone and has much less features than the API, the examples/standalone/stubs.c show some assembly code, this code use the U-Boot global data pointer stored in R9 on ARM (global_data struct in include/asm-generic/global_data.h) plus some computed offset to locate the jump table (struct jt member) which contains pointers to U-Boot exported functions, it then call a function stored in that table.
So in this case this works :
.global _start
_start:
// U-Boot call
adr lr, halt // get back to "halt" after calling getc
ldr ip, [r9, #124] // load jump table address (global data pointer is in r9 + offset to the *jt* member)
ldr pc, [ip, #4] // call getc then r0 hold getc returned value
//
halt:
wfe
b halt
Note that the offset to locate the jump table may change with different U-Boot config. options so it may be better to use the U-Boot API since the API address is available in an environment variable.