[U-Boot-Users] [RFC] raw go command

This patch is just a quick work up to see how to handle a particular problem I've got. The idea is that I want finer control over what happens when I 'go' to piece of code. The idea is it looks more like a native function call than the current go which is more main() like.
The calling convention/num of args is specific to the PPC ABI.
I'm looking for suggestions, better names, etc.
thanks
- k
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index e68f16f..5b0bbe4 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -32,6 +32,42 @@ DECLARE_GLOBAL_DATA_PTR; #endif
+int do_go_raw (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr, i; + ulong r[8] = { 0 }; + + void (*img)(ulong, ulong, ulong, ulong, + ulong, ulong, ulong, ulong); + + if ((argc < 2) || (argc > 9)) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + addr = simple_strtoul(argv[1], NULL, 16); + + img = (void (*)(ulong, ulong, ulong, ulong, + ulong, ulong, ulong, ulong)) addr; + + for (i = 2; i < argc; i++) + r[i-2] = simple_strtoul(argv[i], NULL, 16); + + (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); + /* does not return */ + + return 0; +} + +/* -------------------------------------------------------------------- */ + +U_BOOT_CMD( + go_raw, CFG_MAXARGS, 1, do_go_raw, + "go_raw - start application at address 'addr'\n", + "addr [arg ...]\n - start application at address 'addr'\n" + " passing 'arg' as arguments\n" +); + int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong addr, rc;

In message Pine.LNX.4.64.0802131746070.29374@blarg.am.freescale.net you wrote:
This patch is just a quick work up to see how to handle a particular problem I've got. The idea is that I want finer control over what happens when I 'go' to piece of code. The idea is it looks more like a native function call than the current go which is more main() like.
To me it looks different, but not more native.
Best regards,
Wolfgang Denk

On Feb 13, 2008, at 6:40 PM, Wolfgang Denk wrote:
In message <Pine.LNX. 4.64.0802131746070.29374@blarg.am.freescale.net> you wrote:
This patch is just a quick work up to see how to handle a particular problem I've got. The idea is that I want finer control over what happens when I 'go' to piece of code. The idea is it looks more like a native function call than the current go which is more main() like.
To me it looks different, but not more native.
Maybe my descriptions not the best, but its intended to provide a mechanism similar to how we boot a kernel that the user can specify the values in the registers.
- k

On Wed, 13 Feb 2008 17:50:20 -0600 (CST) Kumar Gala galak@kernel.crashing.org wrote:
The calling convention/num of args is specific to the PPC ABI.
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index e68f16f..5b0bbe4 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c
So what's it doing under common/ with a generic-sounding name?
Haavard

On Feb 14, 2008, at 2:12 AM, Haavard Skinnemoen wrote:
On Wed, 13 Feb 2008 17:50:20 -0600 (CST) Kumar Gala galak@kernel.crashing.org wrote:
The calling convention/num of args is specific to the PPC ABI.
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index e68f16f..5b0bbe4 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c
So what's it doing under common/ with a generic-sounding name?
there is no reason it couldn't be implemented by other arch's but I get your point. Any suggestions on a better name?
I hadn't thought about putting this in lib_ppc, thus the RFC on the email :)
- k

The call command tries to mimic a function call in that the 'arg's to the command are passed in registers according to the PPC ABI.
The prototype that call mimics is some variation of the following depending on how many arguments are passed to the command:
void func(void) void func(unsigned long r3) void func(unsigned long r3, unsigned long r4) ... void func(unsigned long r3, unsigned long r4, ... unsigned long r10)
The maximum number of 'arg's is 8. There are no arguments passed on a stack, no floating point or vector arguments.
Signed-off-by: Kumar Gala galak@kernel.crashing.org ---
This is attempt to at the concept I was trying to get a w/the raw go thread.
lib_ppc/Makefile | 4 ++- lib_ppc/cmd_call.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletions(-) create mode 100644 lib_ppc/cmd_call.c
diff --git a/lib_ppc/Makefile b/lib_ppc/Makefile index afbd5ca..a776052 100644 --- a/lib_ppc/Makefile +++ b/lib_ppc/Makefile @@ -25,9 +25,11 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(ARCH).a
+COBJS-$(CONFIG_CMD_CALL) += cmd_call.o + SOBJS = ppccache.o ppcstring.o ticks.o
-COBJS = board.o \ +COBJS = board.o $(COBJS-y) \ bat_rw.o cache.o extable.o kgdb.o time.o interrupts.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/lib_ppc/cmd_call.c b/lib_ppc/cmd_call.c new file mode 100644 index 0000000..5476f27 --- /dev/null +++ b/lib_ppc/cmd_call.c @@ -0,0 +1,64 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> + +int do_call (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr, i; + ulong r[8] = { 0 }; + + void (*img)(ulong, ulong, ulong, ulong, + ulong, ulong, ulong, ulong); + + if ((argc < 2) || (argc > 10)) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + addr = simple_strtoul(argv[1], NULL, 16); + + img = (void (*)(ulong, ulong, ulong, ulong, + ulong, ulong, ulong, ulong)) addr; + + for (i = 2; i < argc; i++) + r[i-2] = simple_strtoul(argv[i], NULL, 16); + + (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); + + /* may not return */ + + return 0; +} + +/* -------------------------------------------------------------------- */ + +U_BOOT_CMD( + call, CFG_MAXARGS, 1, do_call, + "call - jump to address 'addr'\n", + "addr [arg ...]\n - jump to address 'addr' passing 'arg's" + " as if it were a function call\n" +);

On Friday 15 February 2008, Kumar Gala wrote:
--- /dev/null +++ b/lib_ppc/cmd_call.c
there's nothing ppc specific about this
- if ((argc < 2) || (argc > 10)) {
... +U_BOOT_CMD(
- call, CFG_MAXARGS, 1, do_call,
considering the u-boot infrastructure for commands will do the max checking for you, there's no need to check the upper bound of argc. it's also out of sync: in one place you have a random "10" but in another you have "CFG_MAXARGS".
- (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
- /* may not return */
- return 0;
why not ? you might as well not arbitrarily limit things and have the prototype return an int and have it return that instead of "0": return (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); -mike

On Feb 14, 2008, at 11:54 PM, Mike Frysinger wrote:
On Friday 15 February 2008, Kumar Gala wrote:
--- /dev/null +++ b/lib_ppc/cmd_call.c
there's nothing ppc specific about this
I'm not familiar w/other architecture ABIs to say if that's true or not. Clearly the upper limit may vary based on the differences in the ABIs.
- if ((argc < 2) || (argc > 10)) {
... +U_BOOT_CMD(
- call, CFG_MAXARGS, 1, do_call,
considering the u-boot infrastructure for commands will do the max checking for you, there's no need to check the upper bound of argc. it's also out of sync: in one place you have a random "10" but in another you have "CFG_MAXARGS".
agreed. At first I was going for something more generic.
- (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
- /* may not return */
- return 0;
why not ? you might as well not arbitrarily limit things and have the prototype return an int and have it return that instead of "0": return (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
will do.
- k

The call command tries to mimic a function call in that the 'arg's to the command are passed in registers according to the PPC ABI.
The prototype that call mimics is some variation of the following depending on how many arguments are passed to the command:
void func(void) void func(unsigned long r3) void func(unsigned long r3, unsigned long r4) ... void func(unsigned long r3, unsigned long r4, ... unsigned long r10)
The maximum number of 'arg's is 8. There are no arguments passed on a stack, no floating point or vector arguments.
Signed-off-by: Kumar Gala galak@kernel.crashing.org ---
Incorporate Mike's feedback on using u-boot max arg checking and allow the function to return.
lib_ppc/Makefile | 4 ++- lib_ppc/cmd_call.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletions(-) create mode 100644 lib_ppc/cmd_call.c
diff --git a/lib_ppc/Makefile b/lib_ppc/Makefile index afbd5ca..a776052 100644 --- a/lib_ppc/Makefile +++ b/lib_ppc/Makefile @@ -25,9 +25,11 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(ARCH).a
+COBJS-$(CONFIG_CMD_CALL) += cmd_call.o + SOBJS = ppccache.o ppcstring.o ticks.o
-COBJS = board.o \ +COBJS = board.o $(COBJS-y) \ bat_rw.o cache.o extable.o kgdb.o time.o interrupts.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/lib_ppc/cmd_call.c b/lib_ppc/cmd_call.c new file mode 100644 index 0000000..83a1764 --- /dev/null +++ b/lib_ppc/cmd_call.c @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> + +int do_call (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr, i; + ulong r[8] = { 0 }; + + int (*img)(ulong, ulong, ulong, ulong, + ulong, ulong, ulong, ulong); + + if (argc < 2) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + addr = simple_strtoul(argv[1], NULL, 16); + + img = (int (*)(ulong, ulong, ulong, ulong, + ulong, ulong, ulong, ulong)) addr; + + for (i = 2; i < argc; i++) + r[i-2] = simple_strtoul(argv[i], NULL, 16); + + return (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); +} + +/* -------------------------------------------------------------------- */ + +U_BOOT_CMD( + call, 10, 1, do_call, + "call - jump to address 'addr'\n", + "addr [arg ...]\n - jump to address 'addr' passing 'arg's" + " as if it were a function call\n" +);

In message Pine.LNX.4.64.0802150001460.1512@blarg.am.freescale.net you wrote:
The call command tries to mimic a function call in that the 'arg's to the command are passed in registers according to the PPC ABI.
The prototype that call mimics is some variation of the following depending on how many arguments are passed to the command:
void func(void) void func(unsigned long r3) void func(unsigned long r3, unsigned long r4) ... void func(unsigned long r3, unsigned long r4, ... unsigned long r10)
The maximum number of 'arg's is 8. There are no arguments passed on a stack, no floating point or vector arguments.
This really makes zero sense to me.
- img = (int (*)(ulong, ulong, ulong, ulong,
ulong, ulong, ulong, ulong)) addr;
- for (i = 2; i < argc; i++)
r[i-2] = simple_strtoul(argv[i], NULL, 16);
- return (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
This looks not clean. Either this is a function with exactly 8 arguments, or it isn't. And where is the code that makes sure that ``the 'arg's to the command are passed in registers'' ? I see no difference between this call and what "go" does.
Best regards,
Wolfgang Denk

On Friday 15 February 2008, Wolfgang Denk wrote:
- return (*img)(r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
I see no difference between this call and what "go" does.
well there's an obvious difference. go passes argc/argv[] as parameters where as this passes everything as parameters. as for whether you think it's needed at all, that's a different matter ;) -mike

On Friday 15 February 2008, Kumar Gala wrote:
On Feb 14, 2008, at 11:54 PM, Mike Frysinger wrote:
On Friday 15 February 2008, Kumar Gala wrote:
--- /dev/null +++ b/lib_ppc/cmd_call.c
there's nothing ppc specific about this
I'm not familiar w/other architecture ABIs to say if that's true or not. Clearly the upper limit may vary based on the differences in the ABIs.
if the code were written in assembly, i'd agree. you've written it in pure C though, so the compiler worries about the ABI. if your ABI has different semantics for function pointers than normal function calls, it's a piece of crap. i dont think any ports of u-boot need worry about this. -mike

On Feb 15, 2008, at 12:32 AM, Mike Frysinger wrote:
On Friday 15 February 2008, Kumar Gala wrote:
On Feb 14, 2008, at 11:54 PM, Mike Frysinger wrote:
On Friday 15 February 2008, Kumar Gala wrote:
--- /dev/null +++ b/lib_ppc/cmd_call.c
there's nothing ppc specific about this
I'm not familiar w/other architecture ABIs to say if that's true or not. Clearly the upper limit may vary based on the differences in the ABIs.
if the code were written in assembly, i'd agree. you've written it in pure C though, so the compiler worries about the ABI. if your ABI has different semantics for function pointers than normal function calls, it's a piece of crap. i dont think any ports of u-boot need worry about this.
agreed there.
The main reason for me doing this was to provide a "generic" mechanism that mimic how we boot kernels on PPC.
The other issue w/providing this on all arch's is that the number of params passed via regs may vary and I don't know what is for arm, avr32, blackfin, i386, m68k, microblaze, mips, nios, nios2, and sh.
and each variation will require a different prototype.
if someone can tell me what the number of args are for each arch we can see about providing this everywhere.
- k

On Friday 15 February 2008, Kumar Gala wrote:
On Feb 15, 2008, at 12:32 AM, Mike Frysinger wrote:
On Friday 15 February 2008, Kumar Gala wrote:
On Feb 14, 2008, at 11:54 PM, Mike Frysinger wrote:
On Friday 15 February 2008, Kumar Gala wrote:
--- /dev/null +++ b/lib_ppc/cmd_call.c
there's nothing ppc specific about this
I'm not familiar w/other architecture ABIs to say if that's true or not. Clearly the upper limit may vary based on the differences in the ABIs.
if the code were written in assembly, i'd agree. you've written it in pure C though, so the compiler worries about the ABI. if your ABI has different semantics for function pointers than normal function calls, it's a piece of crap. i dont think any ports of u-boot need worry about this.
agreed there.
The main reason for me doing this was to provide a "generic" mechanism that mimic how we boot kernels on PPC.
The other issue w/providing this on all arch's is that the number of params passed via regs may vary and I don't know what is for arm, avr32, blackfin, i386, m68k, microblaze, mips, nios, nios2, and sh.
and each variation will require a different prototype.
if someone can tell me what the number of args are for each arch we can see about providing this everywhere.
are you sure you actually need to worry about such things ? i'm pretty sure any relevant architecture says that the first X arguments go via registers and the rest go on the stack. let the compiler worry about the exact value for X. -mike

On Fri, 15 Feb 2008 02:08:23 -0500 Mike Frysinger vapier@gentoo.org wrote:
if someone can tell me what the number of args are for each arch we can see about providing this everywhere.
are you sure you actually need to worry about such things ? i'm pretty sure any relevant architecture says that the first X arguments go via registers and the rest go on the stack. let the compiler worry about the exact value for X.
I guess the real question is whether it's acceptable to pass arguments on the stack to such subprograms. If the answer is yes, why not simply use varargs?
If the answer is no: avr32 can pass up to 5 arguments through registers.
Haavard

On Friday 15 February 2008, Haavard Skinnemoen wrote:
Mike Frysinger vapier@gentoo.org wrote:
if someone can tell me what the number of args are for each arch we can see about providing this everywhere.
are you sure you actually need to worry about such things ? i'm pretty sure any relevant architecture says that the first X arguments go via registers and the rest go on the stack. let the compiler worry about the exact value for X.
I guess the real question is whether it's acceptable to pass arguments on the stack to such subprograms. If the answer is yes, why not simply use varargs?
if the goal is to keep things in registers, "call" and its description are way too vague. the description makes me think this is meant to be a "go" for functions.
If the answer is no: avr32 can pass up to 5 arguments through registers.
x86 does 0 while Blackfin does 3. -mike

On Feb 15, 2008, at 1:29 AM, Mike Frysinger wrote:
On Friday 15 February 2008, Haavard Skinnemoen wrote:
Mike Frysinger vapier@gentoo.org wrote:
if someone can tell me what the number of args are for each arch we can see about providing this everywhere.
are you sure you actually need to worry about such things ? i'm pretty sure any relevant architecture says that the first X arguments go via registers and the rest go on the stack. let the compiler worry about the exact value for X.
I guess the real question is whether it's acceptable to pass arguments on the stack to such subprograms. If the answer is yes, why not simply use varargs?
if the goal is to keep things in registers, "call" and its description are way too vague. the description makes me think this is meant to be a "go" for functions.
As per Wolfgang's desires the help is terse, the commit message was suppose to convey more details. But I can see where the confusion comes from. I'm open to better wording and will try to think of some myself.
If the answer is no: avr32 can pass up to 5 arguments through registers.
x86 does 0 while Blackfin does 3.
3 arch's down, 6 to go.
- k

On Fri, 15 Feb 2008 02:29:39 -0500 Mike Frysinger vapier@gentoo.org wrote:
x86 does 0 while Blackfin does 3.
x86 can do more (at least 3) if you use the regparm attribute. But you obviously need to keep both sides in sync.
Haavard

On Friday 15 February 2008, Haavard Skinnemoen wrote:
Mike Frysinger vapier@gentoo.org wrote:
x86 does 0 while Blackfin does 3.
x86 can do more (at least 3) if you use the regparm attribute. But you obviously need to keep both sides in sync.
i'm aware of all the neat tricks you can do with gcc, but we were talking about the ABI standard (which the gcc tricks violate) -mike

On Feb 15, 2008, at 1:21 AM, Haavard Skinnemoen wrote:
On Fri, 15 Feb 2008 02:08:23 -0500 Mike Frysinger vapier@gentoo.org wrote:
if someone can tell me what the number of args are for each arch we can see about providing this everywhere.
are you sure you actually need to worry about such things ? i'm pretty sure any relevant architecture says that the first X arguments go via registers and the rest go on the stack. let the compiler worry about the exact value for X.
I guess the real question is whether it's acceptable to pass arguments on the stack to such subprograms. If the answer is yes, why not simply use varargs?
for my purposes the answer is no.
If the answer is no: avr32 can pass up to 5 arguments through registers.
thanks
- k

In message 19411A28-BCCB-46D1-A80A-6C31657757D2@kernel.crashing.org you wrote:
I guess the real question is whether it's acceptable to pass arguments on the stack to such subprograms. If the answer is yes, why not simply use varargs?
for my purposes the answer is no.
Then you cannot use C code. Or you rely on the ABI, and then you can use "go" as well.
Best regards,
Wolfgang Denk

In message ECB2C6CF-0AB8-44AE-AD35-769B741B0528@kernel.crashing.org you wrote:
The main reason for me doing this was to provide a "generic" mechanism that mimic how we boot kernels on PPC.
May I ask why exactly this is needed at all? Kernels should be booted using the bootm command - if somethingis missing there, it should be added / fixed in this contexzt instead of adding another highly specialized command.
And *if* we add this, then please let's make it general enough so we can use it on all architectures without adding a lot of #ifdef mess.
The other issue w/providing this on all arch's is that the number of params passed via regs may vary and I don't know what is for arm, avr32, blackfin, i386, m68k, microblaze, mips, nios, nios2, and sh. and each variation will require a different prototype.
No, just change the design, then. Make it a varargs function and pass the number of registers as one argument.
Best regards,
Wolfgang Denk

On Friday 15 February 2008, Kumar Gala wrote:
The main reason for me doing this was to provide a "generic" mechanism that mimic how we boot kernels on PPC.
is that the only reason ? what format is the kernel that you're attempting to boot ? assuming it's an ELF ...
at the moment, the Blackfin code base maintained on blackfin.uclinux.org has hacked the "bootelf" command to assume it is always booting a kernel. this way we can load/boot the ELF image of our kernels in memory and have the $(bootargs) and such actually get passed properly (dont yell at me for this, the change was before my time, and i agree it's crap :p).
in other words, a common function for booting a linux ELF kernel image would be great. especially considering the fact we have a "bootvx" that takes an ELF image, sets up the bootargs, and then boots it properly. seems messed up that booting vxworks sees better support than booting linux ;) -mike

In message Pine.LNX.4.64.0802142341250.31987@blarg.am.freescale.net you wrote:
The call command tries to mimic a function call in that the 'arg's to the command are passed in registers according to the PPC ABI.
The prototype that call mimics is some variation of the following depending on how many arguments are passed to the command:
void func(void) void func(unsigned long r3) void func(unsigned long r3, unsigned long r4) ... void func(unsigned long r3, unsigned long r4, ... unsigned long r10)
The maximum number of 'arg's is 8. There are no arguments passed on a stack, no floating point or vector arguments.
Sorry, but this looks still broken to me.
Best regards,
Wolfgang Denk
participants (4)
-
Haavard Skinnemoen
-
Kumar Gala
-
Mike Frysinger
-
Wolfgang Denk