Есть ли способ вызвать функции U-Boot API из программы ARM, загруженной с помощью команды go?
Я вижу, что U-Boot API доступен после запуска по адресу, определенному в переменной среды api_address, но я не могу понять, как его использовать.
Например, если я хочу вызвать функцию getc, которую можно увидеть в U-Boot api/api.c, как мне на самом деле вызвать ее из ассемблерной программы?
Я попробовал это (на плате ARM1176JZF-S), но произошел сбой:
.global _start
_start:
ldr r0, =0x1BB89148 ; api_address value
ldr r1, [r0, #32] ; offset to get getc location
bx r1 ; call getc
Разумным было вызвать вторую функцию (API_getc) из таблицы syscall_table, инициализированной в U-Boot api.c, где r0 — это значение api_address.
Похоже, я ошибся с api_address, поскольку это не адрес таблицы переходов, а структура api_signature, определенная в api/api.c, она содержит элемент системного вызова, который является адресом функции системного вызова, определенной в том же файле, эта функция может использоваться для вызова U-Boot API (пример API показывает это)
Итак, для вызова API это работает:
// 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
Это работает для вызова любых функций API, определенных в include/api_public.h под структурой api_signature.
Автономный пример работает немного по-другому doc/README.standalone и имеет гораздо меньше функций, чем API, в example/standalone/stubs.c показан некоторый ассемблерный код, этот код использует глобальный указатель данных U-Boot, хранящийся в R9. в ARM (структура global_data в include/asm-generic/global_data.h) плюс некоторое вычисленное смещение для поиска таблицы переходов (член структуры jt), которая содержит указатели на экспортированные функции U-Boot, затем он вызывает функцию, хранящуюся в этой таблице.
Итак, в этом случае это работает:
.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
Обратите внимание, что смещение для расположения таблицы переходов может меняться в зависимости от конфигурации U-Boot. параметры, поэтому, возможно, лучше использовать U-Boot API, поскольку адрес API доступен в переменной среды.
Вы изучали doc/README.standalone?