Browse Source

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: Martin Dorwig <dorwig@tetronik.com>
Acked-by: Simon Glass <sjg@chromium.org>

Signed-off-by: Simon Glass <sjg@chromium.org>
(resending to the list since my tweaks are not quite trivial)
Martin Dorwig 10 years ago
parent
commit
49cad54788

+ 2 - 1
arch/blackfin/cpu/cpu.c

@@ -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)
 	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);

+ 1 - 1
board/BuS/eb_cpux9k2/cpux9k2.c

@@ -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);

+ 1 - 1
common/cmd_load.c

@@ -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);
 		}
 		}

+ 10 - 10
common/console.c

@@ -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[XF_tstc] = tstc;
+			gd->jt->getc = getc;
+			gd->jt->tstc = tstc;
 			break;
 			break;
 		case stdout:
 		case stdout:
-			gd->jt[XF_putc] = putc;
-			gd->jt[XF_puts] = puts;
-			gd->jt[XF_printf] = printf;
+			gd->jt->putc  = putc;
+			gd->jt->puts  = puts;
+			gd->jt->printf = printf;
 			break;
 			break;
 		}
 		}
 		break;
 		break;
@@ -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[XF_tstc] = serial_tstc;
-	gd->jt[XF_putc] = serial_putc;
-	gd->jt[XF_puts] = serial_puts;
-	gd->jt[XF_printf] = serial_printf;
+	gd->jt->getc  = serial_getc;
+	gd->jt->tstc  = serial_tstc;
+	gd->jt->putc  = serial_putc;
+	gd->jt->puts  = serial_puts;
+	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 */

+ 3 - 26
common/exports.c

@@ -1,6 +1,7 @@
 #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)
 	return XF_VERSION;
 	return XF_VERSION;
 }
 }
 
 
-/* Reuse _exports.h with a little trickery to avoid bitrot */
-#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
+#define EXPORT_FUNC(f, a, x, ...)  gd->jt->x = f;
 
 
 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>
 }
 }

+ 30 - 11
doc/README.standalone

@@ -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[XF_free]		= my_free;
+	gd->jt->malloc	= my_malloc;
+	gd->jt->free = my_free;
 
 
-   Note that the pointers to the functions all have 'void *' type and
-   thus the compiler cannot perform type checks on these assignments.
+   Note that the pointers to the functions are real function pointers
+   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:
    => 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
-     appropriate (most likely, to the jumptable_init() function):
+	gd->jt->foobar = another_foobar;
 
 
-	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

+ 33 - 31
examples/standalone/stubs.c

@@ -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 @@
  * 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;
 "	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;
  * 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;
 "	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;
 "	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;
 		"	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;
 "	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;
 "	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;
 "	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"			\*/

+ 70 - 29
include/_exports.h

@@ -1,32 +1,73 @@
 /*
 /*
- * 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)
-EXPORT_FUNC(getc)
-EXPORT_FUNC(tstc)
-EXPORT_FUNC(putc)
-EXPORT_FUNC(puts)
-EXPORT_FUNC(printf)
-EXPORT_FUNC(install_hdlr)
-EXPORT_FUNC(free_hdlr)
-EXPORT_FUNC(malloc)
-EXPORT_FUNC(free)
-EXPORT_FUNC(udelay)
-EXPORT_FUNC(get_timer)
-EXPORT_FUNC(vprintf)
-EXPORT_FUNC(do_reset)
-EXPORT_FUNC(getenv)
-EXPORT_FUNC(setenv)
-EXPORT_FUNC(simple_strtoul)
-EXPORT_FUNC(strict_strtoul)
-EXPORT_FUNC(simple_strtol)
-EXPORT_FUNC(strcmp)
-EXPORT_FUNC(i2c_write)
-EXPORT_FUNC(i2c_read)
-EXPORT_FUNC(spi_init)
-EXPORT_FUNC(spi_setup_slave)
-EXPORT_FUNC(spi_free_slave)
-EXPORT_FUNC(spi_claim_bus)
-EXPORT_FUNC(spi_release_bus)
-EXPORT_FUNC(spi_xfer)
+#ifndef EXPORT_FUNC
+#define EXPORT_FUNC(a, b, c, ...)
+#endif
+	EXPORT_FUNC(get_version, unsigned long, get_version, void)
+	EXPORT_FUNC(getc, int, getc, void)
+	EXPORT_FUNC(tstc, int, tstc, void)
+	EXPORT_FUNC(putc, void, putc, const char)
+	EXPORT_FUNC(puts, void, puts, const char *)
+	EXPORT_FUNC(printf, int, printf, const char*, ...)
+#if defined(CONFIG_X86) || defined(CONFIG_PPC)
+	EXPORT_FUNC(irq_install_handler, void, install_hdlr,
+		    int, interrupt_handler_t, void*)
+
+	EXPORT_FUNC(irq_free_handler, void, free_hdlr, int)
+#else
+	EXPORT_FUNC(dummy, void, install_hdlr, void)
+	EXPORT_FUNC(dummy, void, free_hdlr, void)
+#endif
+	EXPORT_FUNC(malloc, void *, malloc, size_t)
+	EXPORT_FUNC(free, void, free, void *)
+	EXPORT_FUNC(udelay, void, udelay, unsigned long)
+	EXPORT_FUNC(get_timer, unsigned long, get_timer, unsigned long)
+	EXPORT_FUNC(vprintf, int, vprintf, const char *, va_list)
+	EXPORT_FUNC(do_reset, int, do_reset, cmd_tbl_t *,
+		    int , int , char * const [])
+	EXPORT_FUNC(getenv, char  *, getenv, const char*)
+	EXPORT_FUNC(setenv, int, setenv, const char *, const char *)
+	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)

+ 1 - 1
include/asm-generic/global_data.h

@@ -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 */

+ 12 - 10
include/exports.h

@@ -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);
 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);
 void *malloc(size_t);
 void free(void*);
 void free(void*);
 void __udelay(unsigned long);
 void __udelay(unsigned long);
 unsigned long get_timer(unsigned long);
 unsigned long get_timer(unsigned long);
 int vprintf(const char *, va_list);
 int vprintf(const char *, va_list);
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base);
 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
 char *getenv (const char *name);
 char *getenv (const char *name);
 int setenv (const char *varname, const char *varvalue);
 int setenv (const char *varname, const char *varvalue);
-long simple_strtol(const char *cp,char **endp,unsigned int base);
-int strcmp(const char * cs,const char * ct);
+long simple_strtol(const char *cp, char **endp, unsigned int base);
+int strcmp(const char *cs, const char *ct);
 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base);
 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base);
 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base);
 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base);
-#if defined(CONFIG_CMD_I2C)
+#if defined(CONFIG_CMD_I2C) && \
+		(!defined(CONFIG_DM_I2C) || defined(CONFIG_DM_I2C_COMPAT))
 int i2c_write (uchar, uint, int , uchar* , int);
 int i2c_write (uchar, uint, int , uchar* , int);
 int i2c_read (uchar, uint, int , uchar* , int);
 int i2c_read (uchar, uint, int , uchar* , int);
 #endif
 #endif
@@ -34,15 +37,14 @@ void app_startup(char * const *);
 
 
 #endif    /* ifndef __ASSEMBLY__ */
 #endif    /* ifndef __ASSEMBLY__ */
 
 
-enum {
-#define EXPORT_FUNC(x) XF_ ## x ,
+struct jt_funcs {
+#define EXPORT_FUNC(impl, res, func, ...) res(*func)(__VA_ARGS__);
 #include <_exports.h>
 #include <_exports.h>
 #undef EXPORT_FUNC
 #undef EXPORT_FUNC
-
-	XF_MAX
 };
 };
 
 
-#define XF_VERSION	6
+
+#define XF_VERSION	7
 
 
 #if defined(CONFIG_X86)
 #if defined(CONFIG_X86)
 extern gd_t *global_data;
 extern gd_t *global_data;