u-boot-brain/doc/README.standalone
Wolfgang Denk 54841ab50c Make sure that argv[] argument pointers are not modified.
The hush shell dynamically allocates (and re-allocates) memory for the
argument strings in the "char *argv[]" argument vector passed to
commands.  Any code that modifies these pointers will cause serious
corruption of the malloc data structures and crash U-Boot, so make
sure the compiler can check that no such modifications are being done
by changing the code into "char * const argv[]".

This modification is the result of debugging a strange crash caused
after adding a new command, which used the following argument
processing code which has been working perfectly fine in all Unix
systems since version 6 - but not so in U-Boot:

int main (int argc, char **argv)
{
	while (--argc > 0 && **++argv == '-') {
/* ====> */	while (*++*argv) {
			switch (**argv) {
			case 'd':
				debug++;
				break;
			...
			default:
				usage ();
			}
		}
	}
	...
}

The line marked "====>" will corrupt the malloc data structures and
usually cause U-Boot to crash when the next command gets executed by
the shell.  With the modification, the compiler will prevent this with
an
	error: increment of read-only location '*argv'

N.B.: The code above can be trivially rewritten like this:

	while (--argc > 0 && **++argv == '-') {
		char *arg = *argv;
		while (*++arg) {
			switch (*arg) {
			...

Signed-off-by: Wolfgang Denk <wd@denx.de>
Acked-by: Mike Frysinger <vapier@gentoo.org>
2010-07-04 23:55:42 +02:00

100 lines
3.7 KiB
Plaintext

Design Notes on Exporting U-Boot Functions to Standalone Applications:
======================================================================
1. The functions are exported by U-Boot via a jump table. The jump
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
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;
Note that the pointers to the functions all have 'void *' type and
thus the compiler cannot 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
architectures use a dedicated register to hold the pointer to the
'global_data' structure: r2 on PowerPC, r8 on ARM, k0 on MIPS,
P3 on Blackfin and gp on Nios II. The x86 architecture does not
use such a register; instead, the pointer to the 'global_data'
structure is passed as 'argv[-1]' pointer.
The application can access the 'global_data' structure in the same
way as U-Boot does:
DECLARE_GLOBAL_DATA_PTR;
printf("U-Boot relocation offset: %x\n", gd->reloc_off);
3. The application should call the app_startup() function before any
call to the exported functions. Also, implementor of the
application may want to check the version of the ABI provided by
U-Boot. To facilitate this, a get_version() function is exported
that returns the ABI version of the running U-Boot. I.e., a
typical application startup may look like this:
int my_app (int argc, char * const argv[])
{
app_startup (argv);
if (get_version () != XF_VERSION)
return 1;
}
4. The default load and start addresses of the applications are as
follows:
Load address Start address
x86 0x00040000 0x00040000
PowerPC 0x00040000 0x00040004
ARM 0x0c100000 0x0c100000
MIPS 0x80200000 0x80200000
Blackfin 0x00001000 0x00001000
Nios II 0x02000000 0x02000000
For example, the "hello world" application may be loaded and
executed on a PowerPC board with the following commands:
=> tftp 0x40000 hello_world.bin
=> go 0x40004
5. To export some additional function foobar(), the following steps
should be undertaken:
- Append the following line at the end of the include/_exports.h
file:
EXPORT_FUNC(foobar)
- Add the prototype for this function to the include/exports.h
file:
void foobar(void);
- Add the initialization of the jump table slot wherever
appropriate (most likely, to the jumptable_init() function):
gd->jt[XF_foobar] = foobar;
- Increase the XF_VERSION value by one in the include/exports.h
file
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
table. That said, to port this code to a new architecture, the
only thing to be provided is the code in the examples/stubs.c
file. If this architecture, however, uses some uncommon method of
passing the 'global_data' pointer (like x86 does), one should add
the respective code to the app_startup() function in that file.
Note that these functions may only use call-clobbered registers;
those registers that are used to pass the function's arguments,
the stack contents and the return address should be left intact.