Skip to content

Commit

Permalink
Export redesign
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
Martin Dorwig authored and sjg20 committed Jan 30, 2015
1 parent 2017aae commit 49cad54
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 121 deletions.
3 changes: 2 additions & 1 deletion arch/blackfin/cpu/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "cpu.h"
#include "initcode.h"
#include "exports.h"

ulong bfin_poweron_retx;
DECLARE_GLOBAL_DATA_PTR;
Expand Down Expand Up @@ -121,7 +122,7 @@ static void display_global_data(void)
printf(" |-ram_size: %lx\n", gd->ram_size);
printf(" |-env_addr: %lx\n", gd->env_addr);
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(" |-bi_boot_params: %lx\n", bd->bi_boot_params);
printf(" |-bi_memstart: %lx\n", bd->bi_memstart);
Expand Down
2 changes: 1 addition & 1 deletion board/BuS/eb_cpux9k2/cpux9k2.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ int misc_init_r(void)
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
status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
Expand Down
2 changes: 1 addition & 1 deletion common/cmd_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ static int read_record(char *buf, ulong len)
}

/* Check for the console hangup (if any different from serial) */
if (gd->jt[XF_getc] != getc) {
if (gd->jt->getc != getc) {
if (ctrlc()) {
return (-1);
}
Expand Down
20 changes: 10 additions & 10 deletions common/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ static int console_setfile(int file, struct stdio_dev * dev)
*/
switch (file) {
case stdin:
gd->jt[XF_getc] = getc;
gd->jt[XF_tstc] = tstc;
gd->jt->getc = getc;
gd->jt->tstc = tstc;
break;
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;
Expand Down Expand Up @@ -758,11 +758,11 @@ int console_init_r(void)
#endif

/* 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 */
/* scan for it */
Expand Down
29 changes: 3 additions & 26 deletions common/exports.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <common.h>
#include <exports.h>
#include <spi.h>
#include <i2c.h>

DECLARE_GLOBAL_DATA_PTR;

Expand All @@ -13,34 +14,10 @@ unsigned long get_version(void)
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)
{
gd->jt = malloc(XF_MAX * sizeof(void *));
gd->jt = malloc(sizeof(struct jt_funcs));
#include <_exports.h>
}
41 changes: 30 additions & 11 deletions doc/README.standalone
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications:
table is allocated and initialized in the jumptable_init() routine
(common/exports.c). Other routines may also modify the jump table,
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
malloc() and free() functions that will be available to standalone
applications, one should do the following:

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
machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II
Expand Down Expand Up @@ -65,27 +65,46 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications:
=> tftp 0x40000 hello_world.bin
=> 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:

- Append the following line at the end of the include/_exports.h
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
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
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
mostly machine-independent. The only places written in assembly
language are stub functions that perform the jump through the jump
Expand Down
Loading

0 comments on commit 49cad54

Please sign in to comment.