Commit 49cad547 authored by Martin Dorwig's avatar Martin Dorwig Committed by Simon Glass

Export redesign

this is an atempt to make the export of functions typesafe.
I replaced the jumptable void ** by a struct (jt_funcs) with function pointers.
The EXPORT_FUNC macro now has 3 fixed parameters and one
variadic parameter
The first is the name of the exported function,
the rest of the parameters are used to format a functionpointer
in the jumptable,

the EXPORT_FUNC macros are expanded three times,
1. to declare the members of the struct
2. to initialize the structmember pointers
3. to call the functions in stubs.c
Signed-off-by: 's avatarMartin Dorwig <dorwig@tetronik.com>
Acked-by: 's avatarSimon Glass <sjg@chromium.org>
Signed-off-by: 's avatarSimon Glass <sjg@chromium.org>
(resending to the list since my tweaks are not quite trivial)
parent 2017aaef
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "cpu.h" #include "cpu.h"
#include "initcode.h" #include "initcode.h"
#include "exports.h"
ulong bfin_poweron_retx; ulong bfin_poweron_retx;
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
...@@ -121,7 +122,7 @@ static void display_global_data(void) ...@@ -121,7 +122,7 @@ static void display_global_data(void)
printf(" |-ram_size: %lx\n", gd->ram_size); printf(" |-ram_size: %lx\n", gd->ram_size);
printf(" |-env_addr: %lx\n", gd->env_addr); printf(" |-env_addr: %lx\n", gd->env_addr);
printf(" |-env_valid: %lx\n", gd->env_valid); printf(" |-env_valid: %lx\n", gd->env_valid);
printf(" |-jt(%p): %p\n", gd->jt, *(gd->jt)); printf(" |-jt(%p): %p\n", gd->jt, gd->jt->get_version);
printf(" \\-bd: %p\n", gd->bd); printf(" \\-bd: %p\n", gd->bd);
printf(" |-bi_boot_params: %lx\n", bd->bi_boot_params); printf(" |-bi_boot_params: %lx\n", bd->bi_boot_params);
printf(" |-bi_memstart: %lx\n", bd->bi_memstart); printf(" |-bi_memstart: %lx\n", bd->bi_memstart);
......
...@@ -98,7 +98,7 @@ int misc_init_r(void) ...@@ -98,7 +98,7 @@ int misc_init_r(void)
puts("Error: invalid MAC at EEPROM\n"); puts("Error: invalid MAC at EEPROM\n");
} }
} }
gd->jt[XF_do_reset] = (void *) do_reset; gd->jt->do_reset = do_reset;
#ifdef CONFIG_STATUS_LED #ifdef CONFIG_STATUS_LED
status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
......
...@@ -222,7 +222,7 @@ static int read_record(char *buf, ulong len) ...@@ -222,7 +222,7 @@ static int read_record(char *buf, ulong len)
} }
/* Check for the console hangup (if any different from serial) */ /* Check for the console hangup (if any different from serial) */
if (gd->jt[XF_getc] != getc) { if (gd->jt->getc != getc) {
if (ctrlc()) { if (ctrlc()) {
return (-1); return (-1);
} }
......
...@@ -125,13 +125,13 @@ static int console_setfile(int file, struct stdio_dev * dev) ...@@ -125,13 +125,13 @@ static int console_setfile(int file, struct stdio_dev * dev)
*/ */
switch (file) { switch (file) {
case stdin: case stdin:
gd->jt[XF_getc] = getc; gd->jt->getc = getc;
gd->jt[XF_tstc] = tstc; gd->jt->tstc = tstc;
break; break;
case stdout: case stdout:
gd->jt[XF_putc] = putc; gd->jt->putc = putc;
gd->jt[XF_puts] = puts; gd->jt->puts = puts;
gd->jt[XF_printf] = printf; gd->jt->printf = printf;
break; break;
} }
break; break;
...@@ -758,11 +758,11 @@ int console_init_r(void) ...@@ -758,11 +758,11 @@ int console_init_r(void)
#endif #endif
/* set default handlers at first */ /* set default handlers at first */
gd->jt[XF_getc] = serial_getc; gd->jt->getc = serial_getc;
gd->jt[XF_tstc] = serial_tstc; gd->jt->tstc = serial_tstc;
gd->jt[XF_putc] = serial_putc; gd->jt->putc = serial_putc;
gd->jt[XF_puts] = serial_puts; gd->jt->puts = serial_puts;
gd->jt[XF_printf] = serial_printf; gd->jt->printf = serial_printf;
/* stdin stdout and stderr are in environment */ /* stdin stdout and stderr are in environment */
/* scan for it */ /* scan for it */
......
#include <common.h> #include <common.h>
#include <exports.h> #include <exports.h>
#include <spi.h> #include <spi.h>
#include <i2c.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
...@@ -13,34 +14,10 @@ unsigned long get_version(void) ...@@ -13,34 +14,10 @@ unsigned long get_version(void)
return XF_VERSION; return XF_VERSION;
} }
/* Reuse _exports.h with a little trickery to avoid bitrot */ #define EXPORT_FUNC(f, a, x, ...) gd->jt->x = f;
#define EXPORT_FUNC(sym) gd->jt[XF_##sym] = (void *)sym;
#if !defined(CONFIG_X86) && !defined(CONFIG_PPC)
# define install_hdlr dummy
# define free_hdlr dummy
#else /* kludge for non-standard function naming */
# define install_hdlr irq_install_handler
# define free_hdlr irq_free_handler
#endif
#if !defined(CONFIG_CMD_I2C) || \
(defined(CONFIG_DM_I2C) && !defined(CONFIG_DM_I2C_COMPAT))
# define i2c_write dummy
# define i2c_read dummy
#endif
#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
# define spi_init dummy
# define spi_setup_slave dummy
# define spi_free_slave dummy
#endif
#ifndef CONFIG_CMD_SPI
# define spi_claim_bus dummy
# define spi_release_bus dummy
# define spi_xfer dummy
#endif
void jumptable_init(void) void jumptable_init(void)
{ {
gd->jt = malloc(XF_MAX * sizeof(void *)); gd->jt = malloc(sizeof(struct jt_funcs));
#include <_exports.h> #include <_exports.h>
} }
...@@ -5,18 +5,18 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications: ...@@ -5,18 +5,18 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications:
table is allocated and initialized in the jumptable_init() routine table is allocated and initialized in the jumptable_init() routine
(common/exports.c). Other routines may also modify the jump table, (common/exports.c). Other routines may also modify the jump table,
however. The jump table can be accessed as the 'jt' field of the however. The jump table can be accessed as the 'jt' field of the
'global_data' structure. The slot numbers for the jump table are 'global_data' structure. The struct members for the jump table are
defined in the <include/exports.h> header. E.g., to substitute the defined in the <include/exports.h> header. E.g., to substitute the
malloc() and free() functions that will be available to standalone malloc() and free() functions that will be available to standalone
applications, one should do the following: applications, one should do the following:
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
gd->jt[XF_malloc] = my_malloc; gd->jt->malloc = my_malloc;
gd->jt[XF_free] = my_free; gd->jt->free = my_free;
Note that the pointers to the functions all have 'void *' type and Note that the pointers to the functions are real function pointers
thus the compiler cannot perform type checks on these assignments. so the compiler can perform type checks on these assignments.
2. The pointer to the jump table is passed to the application in a 2. The pointer to the jump table is passed to the application in a
machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II
...@@ -65,27 +65,46 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications: ...@@ -65,27 +65,46 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications:
=> tftp 0x40000 hello_world.bin => tftp 0x40000 hello_world.bin
=> go 0x40004 => go 0x40004
5. To export some additional function foobar(), the following steps 5. To export some additional function long foobar(int i,char c), the following steps
should be undertaken: should be undertaken:
- Append the following line at the end of the include/_exports.h - Append the following line at the end of the include/_exports.h
file: file:
EXPORT_FUNC(foobar) EXPORT_FUNC(foobar, long, foobar, int, char)
Parameters to EXPORT_FUNC:
- the first parameter is the function that is exported (default implementation)
- the second parameter is the return value type
- the third parameter is the name of the member in struct jt_funcs
this is also the name that the standalone application will used.
the rest of the parameters are the function arguments
- Add the prototype for this function to the include/exports.h - Add the prototype for this function to the include/exports.h
file: file:
void foobar(void); long foobar(int i, char c);
Initialization with the default implementation is done in jumptable_init()
You can override the default implementation using:
- Add the initialization of the jump table slot wherever gd->jt->foobar = another_foobar;
appropriate (most likely, to the jumptable_init() function):
gd->jt[XF_foobar] = foobar; The signature of another_foobar must then match the declaration of foobar.
- Increase the XF_VERSION value by one in the include/exports.h - Increase the XF_VERSION value by one in the include/exports.h
file file
- If you want to export a function which depends on a CONFIG_XXX
use 2 lines like this:
#ifdef CONFIG_FOOBAR
EXPORT_FUNC(foobar, long, foobar, int, char)
#else
EXPORT_FUNC(dummy, void, foobar, void)
#endif
6. The code for exporting the U-Boot functions to applications is 6. The code for exporting the U-Boot functions to applications is
mostly machine-independent. The only places written in assembly mostly machine-independent. The only places written in assembly
language are stub functions that perform the jump through the jump language are stub functions that perform the jump through the jump
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <exports.h> #include <exports.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#define FO(x) offsetof(struct jt_funcs, x)
#if defined(CONFIG_X86) #if defined(CONFIG_X86)
/* /*
* x86 does not have a dedicated register to store the pointer to * x86 does not have a dedicated register to store the pointer to
...@@ -10,23 +12,23 @@ ...@@ -10,23 +12,23 @@
* from flash memory. The global_data address is passed as argv[-1] * from flash memory. The global_data address is passed as argv[-1]
* to the application program. * to the application program.
*/ */
static void **jt; static struct jt_funcs *jt;
gd_t *global_data; gd_t *global_data;
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
" movl %0, %%eax\n" \ " movl %0, %%eax\n" \
" movl jt, %%ecx\n" \ " movl jt, %%ecx\n" \
" jmp *(%%ecx, %%eax)\n" \ " jmp *(%%ecx, %%eax)\n" \
: : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx"); : : "i"(FO(x)) : "eax", "ecx");
#elif defined(CONFIG_PPC) #elif defined(CONFIG_PPC)
/* /*
* r2 holds the pointer to the global_data, r11 is a call-clobbered * r2 holds the pointer to the global_data, r11 is a call-clobbered
* register * register
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
...@@ -34,33 +36,33 @@ gd_t *global_data; ...@@ -34,33 +36,33 @@ gd_t *global_data;
" lwz %%r11, %1(%%r11)\n" \ " lwz %%r11, %1(%%r11)\n" \
" mtctr %%r11\n" \ " mtctr %%r11\n" \
" bctr\n" \ " bctr\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r11");
#elif defined(CONFIG_ARM) #elif defined(CONFIG_ARM)
#ifdef CONFIG_ARM64 #ifdef CONFIG_ARM64
/* /*
* x18 holds the pointer to the global_data, x9 is a call-clobbered * x18 holds the pointer to the global_data, x9 is a call-clobbered
* register * register
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
" ldr x9, [x18, %0]\n" \ " ldr x9, [x18, %0]\n" \
" ldr x9, [x9, %1]\n" \ " ldr x9, [x9, %1]\n" \
" br x9\n" \ " br x9\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "x9"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "x9");
#else #else
/* /*
* r9 holds the pointer to the global_data, ip is a call-clobbered * r9 holds the pointer to the global_data, ip is a call-clobbered
* register * register
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
" ldr ip, [r9, %0]\n" \ " ldr ip, [r9, %0]\n" \
" ldr pc, [ip, %1]\n" \ " ldr pc, [ip, %1]\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "ip");
#endif #endif
#elif defined(CONFIG_MIPS) #elif defined(CONFIG_MIPS)
/* /*
...@@ -70,19 +72,19 @@ gd_t *global_data; ...@@ -70,19 +72,19 @@ gd_t *global_data;
* it; however, GCC/mips generates an additional `nop' after each asm * it; however, GCC/mips generates an additional `nop' after each asm
* statement * statement
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
" lw $25, %0($26)\n" \ " lw $25, %0($26)\n" \
" lw $25, %1($25)\n" \ " lw $25, %1($25)\n" \
" jr $25\n" \ " jr $25\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t9");
#elif defined(CONFIG_NIOS2) #elif defined(CONFIG_NIOS2)
/* /*
* gp holds the pointer to the global_data, r8 is call-clobbered * gp holds the pointer to the global_data, r8 is call-clobbered
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
...@@ -92,13 +94,13 @@ gd_t *global_data; ...@@ -92,13 +94,13 @@ gd_t *global_data;
" ldw r8, 0(r8)\n" \ " ldw r8, 0(r8)\n" \
" ldw r8, %1(r8)\n" \ " ldw r8, %1(r8)\n" \
" jmp r8\n" \ " jmp r8\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "gp"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "gp");
#elif defined(CONFIG_M68K) #elif defined(CONFIG_M68K)
/* /*
* d7 holds the pointer to the global_data, a0 is a call-clobbered * d7 holds the pointer to the global_data, a0 is a call-clobbered
* register * register
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
...@@ -108,50 +110,50 @@ gd_t *global_data; ...@@ -108,50 +110,50 @@ gd_t *global_data;
" adda.l %1, %%a0\n" \ " adda.l %1, %%a0\n" \
" move.l (%%a0), %%a0\n" \ " move.l (%%a0), %%a0\n" \
" jmp (%%a0)\n" \ " jmp (%%a0)\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "a0"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "a0");
#elif defined(CONFIG_MICROBLAZE) #elif defined(CONFIG_MICROBLAZE)
/* /*
* r31 holds the pointer to the global_data. r5 is a call-clobbered. * r31 holds the pointer to the global_data. r5 is a call-clobbered.
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
" lwi r5, r31, %0\n" \ " lwi r5, r31, %0\n" \
" lwi r5, r5, %1\n" \ " lwi r5, r5, %1\n" \
" bra r5\n" \ " bra r5\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r5"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r5");
#elif defined(CONFIG_BLACKFIN) #elif defined(CONFIG_BLACKFIN)
/* /*
* P3 holds the pointer to the global_data, P0 is a call-clobbered * P3 holds the pointer to the global_data, P0 is a call-clobbered
* register * register
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl _" #x "\n_" \ " .globl _" #x "\n_" \
#x ":\n" \ #x ":\n" \
" P0 = [P3 + %0]\n" \ " P0 = [P3 + %0]\n" \
" P0 = [P0 + %1]\n" \ " P0 = [P0 + %1]\n" \
" JUMP (P0)\n" \ " JUMP (P0)\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "P0"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "P0");
#elif defined(CONFIG_AVR32) #elif defined(CONFIG_AVR32)
/* /*
* r6 holds the pointer to the global_data. r8 is call clobbered. * r6 holds the pointer to the global_data. r8 is call clobbered.
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile( \ asm volatile( \
" .globl\t" #x "\n" \ " .globl\t" #x "\n" \
#x ":\n" \ #x ":\n" \
" ld.w r8, r6[%0]\n" \ " ld.w r8, r6[%0]\n" \
" ld.w pc, r8[%1]\n" \ " ld.w pc, r8[%1]\n" \
: \ : \
: "i"(offsetof(gd_t, jt)), "i"(XF_ ##x) \ : "i"(offsetof(gd_t, jt)), "i"(FO(x)) \
: "r8"); : "r8");
#elif defined(CONFIG_SH) #elif defined(CONFIG_SH)
/* /*
* r13 holds the pointer to the global_data. r1 is a call clobbered. * r13 holds the pointer to the global_data. r1 is a call clobbered.
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .align 2\n" \ " .align 2\n" \
" .globl " #x "\n" \ " .globl " #x "\n" \
...@@ -164,12 +166,12 @@ gd_t *global_data; ...@@ -164,12 +166,12 @@ gd_t *global_data;
" jmp @r1\n" \ " jmp @r1\n" \
" nop\n" \ " nop\n" \
" nop\n" \ " nop\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r1", "r2"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r1", "r2");
#elif defined(CONFIG_SPARC) #elif defined(CONFIG_SPARC)
/* /*
* g7 holds the pointer to the global_data. g1 is call clobbered. * g7 holds the pointer to the global_data. g1 is call clobbered.
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile( \ asm volatile( \
" .globl\t" #x "\n" \ " .globl\t" #x "\n" \
#x ":\n" \ #x ":\n" \
...@@ -179,26 +181,26 @@ gd_t *global_data; ...@@ -179,26 +181,26 @@ gd_t *global_data;
" ld [%%g1 + %1], %%g1\n" \ " ld [%%g1 + %1], %%g1\n" \
" jmp %%g1\n" \ " jmp %%g1\n" \
" nop\n" \ " nop\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "g1" ); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "g1");
#elif defined(CONFIG_NDS32) #elif defined(CONFIG_NDS32)
/* /*
* r16 holds the pointer to the global_data. gp is call clobbered. * r16 holds the pointer to the global_data. gp is call clobbered.
* not support reduced register (16 GPR). * not support reduced register (16 GPR).
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
" lwi $r16, [$gp + (%0)]\n" \ " lwi $r16, [$gp + (%0)]\n" \
" lwi $r16, [$r16 + (%1)]\n" \ " lwi $r16, [$r16 + (%1)]\n" \
" jr $r16\n" \ " jr $r16\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "$r16"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "$r16");
#elif defined(CONFIG_OPENRISC) #elif defined(CONFIG_OPENRISC)
/* /*
* r10 holds the pointer to the global_data, r13 is a call-clobbered * r10 holds the pointer to the global_data, r13 is a call-clobbered
* register * register
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile ( \ asm volatile ( \
" .globl " #x "\n" \ " .globl " #x "\n" \
#x ":\n" \ #x ":\n" \
...@@ -206,12 +208,12 @@ gd_t *global_data; ...@@ -206,12 +208,12 @@ gd_t *global_data;
" l.lwz r13, %1(r13)\n" \ " l.lwz r13, %1(r13)\n" \
" l.jr r13\n" \ " l.jr r13\n" \
" l.nop\n" \ " l.nop\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r13"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r13");
#elif defined(CONFIG_ARC) #elif defined(CONFIG_ARC)
/* /*
* r25 holds the pointer to the global_data. r10 is call clobbered. * r25 holds the pointer to the global_data. r10 is call clobbered.
*/ */
#define EXPORT_FUNC(x) \ #define EXPORT_FUNC(f, a, x, ...) \
asm volatile( \ asm volatile( \
" .align 4\n" \ " .align 4\n" \
" .globl " #x "\n" \ " .globl " #x "\n" \
...@@ -219,7 +221,7 @@ gd_t *global_data; ...@@ -219,7 +221,7 @@ gd_t *global_data;
" ld r10, [r25, %0]\n" \ " ld r10, [r25, %0]\n" \
" ld r10, [r10, %1]\n" \ " ld r10, [r10, %1]\n" \
" j [r10]\n" \ " j [r10]\n" \
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r10"); : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
#else #else
/*" addi $sp, $sp, -24\n" \ /*" addi $sp, $sp, -24\n" \
" br $r16\n" \*/ " br $r16\n" \*/
......
/* /*
* You do not need to use #ifdef around functions that may not exist * You need to use #ifdef around functions that may not exist
* in the final configuration (such as i2c). * in the final configuration (such as i2c).
* use a dummyfunction as first parameter to EXPORT_FUNC.
* As an example see the CONFIG_CMD_I2C section below
*/ */
EXPORT_FUNC(get_version) #ifndef EXPORT_FUNC
EXPORT_FUNC(getc) #define EXPORT_FUNC(a, b, c, ...)
EXPORT_FUNC(tstc) #endif
EXPORT_FUNC(putc) EXPORT_FUNC(get_version, unsigned long, get_version, void)
EXPORT_FUNC(puts) EXPORT_FUNC(getc, int, getc, void)
EXPORT_FUNC(printf) EXPORT_FUNC(tstc, int, tstc, void)
EXPORT_FUNC(install_hdlr) EXPORT_FUNC(putc, void, putc, const char)
EXPORT_FUNC(free_hdlr) EXPORT_FUNC(puts, void, puts, const char *)
EXPORT_FUNC(malloc) EXPORT_FUNC(printf, int, printf, const char*, ...)
EXPORT_FUNC(free) #if defined(CONFIG_X86) || defined(CONFIG_PPC)
EXPORT_FUNC(udelay) EXPORT_FUNC(irq_install_handler, void, install_hdlr,
EXPORT_FUNC(get_timer) int, interrupt_handler_t, void*)
EXPORT_FUNC(vprintf)
EXPORT_FUNC(do_reset) EXPORT_FUNC(irq_free_handler, void, free_hdlr, int)
EXPORT_FUNC(getenv) #else
EXPORT_FUNC(setenv) EXPORT_FUNC(dummy, void, install_hdlr, void)
EXPORT_FUNC(simple_strtoul) EXPORT_FUNC(dummy, void, free_hdlr, void)
EXPORT_FUNC(strict_strtoul) #endif
EXPORT_FUNC(simple_strtol) EXPORT_FUNC(malloc, void *, malloc, size_t)
EXPORT_FUNC(strcmp) EXPORT_FUNC(free, void, free, void *)
EXPORT_FUNC(i2c_write) EXPORT_FUNC(udelay, void, udelay, unsigned long)
EXPORT_FUNC(i2c_read) EXPORT_FUNC(get_timer, unsigned long, get_timer, unsigned long)
EXPORT_FUNC(spi_init) EXPORT_FUNC(vprintf, int, vprintf, const char *, va_list)
EXPORT_FUNC(spi_setup_slave) EXPORT_FUNC(do_reset, int, do_reset, cmd_tbl_t *,
EXPORT_FUNC(spi_free_slave) int , int , char * const [])
EXPORT_FUNC(spi_claim_bus) EXPORT_FUNC(getenv, char *, getenv, const char*)
EXPORT_FUNC(spi_release_bus) EXPORT_FUNC(setenv, int, setenv, const char *, const char *)
EXPORT_FUNC(spi_xfer) EXPORT_FUNC(simple_strtoul, unsigned long, simple_strtoul,
const char *, char **, unsigned int)
EXPORT_FUNC(strict_strtoul, int, strict_strtoul,
const char *, unsigned int , unsigned long *)
EXPORT_FUNC(simple_strtol, long, simple_strtol,
const char *, char **, unsigned int)
EXPORT_FUNC(strcmp, int, strcmp, const char *cs, const char *ct)
#if defined(CONFIG_CMD_I2C) && \
(!defined(CONFIG_DM_I2C) || defined(CONFIG_DM_I2C_COMPAT))
EXPORT_FUNC(i2c_write, int, i2c_write, uchar, uint, int , uchar * , int)
EXPORT_FUNC(i2c_read, int, i2c_read, uchar, uint, int , uchar * , int)
#else
EXPORT_FUNC(dummy, void, i2c_write, void)
EXPORT_FUNC(dummy, void, i2c_read, void)
#endif
#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
EXPORT_FUNC(dummy, void, spi_init, void)
EXPORT_FUNC(dummy, void, spi_setup_slave, void)
EXPORT_FUNC(dummy, void, spi_free_slave, void)
#else
EXPORT_FUNC(spi_init, void, spi_init, void)
EXPORT_FUNC(spi_setup_slave, struct spi_slave *, spi_setup_slave,
unsigned int, unsigned int, unsigned int, unsigned int)
EXPORT_FUNC(spi_free_slave, void, spi_free_slave, struct spi_slave *)
#endif
#ifndef CONFIG_CMD_SPI
EXPORT_FUNC(dummy, void, spi_claim_bus, void)
EXPORT_FUNC(dummy, void, spi_release_bus, void)
EXPORT_FUNC(dummy, void, spi_xfer, void)
#else
EXPORT_FUNC(spi_claim_bus, int, spi_claim_bus, struct spi_slave *)
EXPORT_FUNC(spi_release_bus, void, spi_release_bus, struct spi_slave *)
EXPORT_FUNC(spi_xfer, int, spi_xfer, struct spi_slave *,
unsigned int, const void *, void *, unsigned long)
#endif
EXPORT_FUNC(ustrtoul, unsigned long, ustrtoul,
const char *, char **, unsigned int)
EXPORT_FUNC(ustrtoull, unsigned long long, ustrtoull,
const char *, char **, unsigned int)
...@@ -73,7 +73,7 @@ typedef struct global_data { ...@@ -73,7 +73,7 @@ typedef struct global_data {
const void *fdt_blob; /* Our device tree, NULL if none */ const void *fdt_blob; /* Our device tree, NULL if none */
void *new_fdt; /* Relocated FDT */ void *new_fdt; /* Relocated FDT */
unsigned long fdt_size; /* Space reserved for relocated FDT */ unsigned long fdt_size; /* Space reserved for relocated FDT */
void **jt; /* jump table */ struct jt_funcs *jt; /* jump table */
char env_buf[32]; /* buffer for getenv() before reloc. */ char env_buf[32]; /* buffer for getenv() before reloc. */
#ifdef CONFIG_TRACE #ifdef CONFIG_TRACE
void *trace_buff; /* The trace buffer */ void *trace_buff; /* The trace buffer */
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct spi_slave;
/* These are declarations of exported functions available in C code */ /* These are declarations of exported functions available in C code */
unsigned long get_version(void); unsigned long get_version(void);
int getc(void); int getc(void);
...@@ -10,22 +12,23 @@ int tstc(void); ...@@ -10,22 +12,23 @@ int tstc(void);
void putc(const char); void putc(const char);
void puts(const char*); void puts(const char*);
int printf(const char* fmt, ...); int printf(const char* fmt, ...);
void install_hdlr(int, void (*interrupt_handler_t)(void *), void*); void install_hdlr(int, interrupt_handler_t, void*);
void free_hdlr(int); void free_hdlr(int);
void *malloc(size_t);