Files
openbios/libopenbios/client.c
Andreas Färber 28516584d1 CIF: Fix trace output for claim and release
A misplaced digit 8 made it look as if some signedness issue was present
somewhere between libopenbios/client.c:of_client_interface() and
arch/ppc/qemu/methods.c:ciface_claim(). This is not the case;
despite unsigned long -> ucell -> cell -> ucell conversions,
PUSH'ing 0x81234567 and POP'ing works as expected.

Fix the format string to avoid such confusion.
Add zero-padding while at it.

Signed-off-by: Andreas Färber <andreas.faerber@web.de>


git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@921 f158a5a8-5612-0410-a976-696ce0be7e32
2010-10-25 19:26:40 +00:00

336 lines
9.8 KiB
C

/*
* Creation Date: <2003/11/25 14:29:08 samuel>
* Time-stamp: <2004/03/27 01:13:53 samuel>
*
* <client.c>
*
* OpenFirmware client interface
*
* Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2
*
*/
#include "config.h"
#include "libopenbios/bindings.h"
#include "libopenbios/of.h"
/* Uncomment to enable debug printout of client interface calls */
//#define DEBUG_CIF
//#define DUMP_IO
/* OF client interface. r3 points to the argument array. On return,
* r3 should contain 0==true or -1==false. r4-r12,cr0,cr1 may
* be modified freely.
*
* -1 should only be returned if the control transfer to OF fails
* (it doesn't) or if the function is unimplemented.
*/
#define PROM_MAX_ARGS 10
typedef struct prom_args {
const char *service;
long nargs;
long nret;
unsigned long args[PROM_MAX_ARGS];
} prom_args_t;
#ifdef DEBUG_CIF
static void memdump(const char *mem, unsigned long size)
{
int i;
if (size == (unsigned long) -1)
return;
for (i = 0; i < size; i += 16) {
int j;
printk("0x%08lx ", (unsigned long)mem + i);
for (j = 0; j < 16 && i + j < size; j++)
printk(" %02x", *(unsigned char*)(mem + i + j));
for ( ; j < 16; j++)
printk(" __");
printk(" ");
for (j = 0; j < 16 && i + j < size; j++) {
unsigned char c = *(mem + i + j);
if (isprint(c))
printk("%c", c);
else
printk(".");
}
printk("\n");
}
}
static void dump_service(prom_args_t *pb)
{
int i;
if (strcmp(pb->service, "test") == 0) {
printk("test(\"%s\") = ", (char*)pb->args[0]);
} else if (strcmp(pb->service, "peer") == 0) {
printk("peer(0x%08lx) = ", pb->args[0]);
} else if (strcmp(pb->service, "child") == 0) {
printk("child(0x%08lx) = ", pb->args[0]);
} else if (strcmp(pb->service, "parent") == 0) {
printk("parent(0x%08lx) = ", pb->args[0]);
} else if (strcmp(pb->service, "instance-to-package") == 0) {
printk("instance-to-package(0x%08lx) = ", pb->args[0]);
} else if (strcmp(pb->service, "getproplen") == 0) {
printk("getproplen(0x%08lx, \"%s\") = ",
pb->args[0], (char*)pb->args[1]);
} else if (strcmp(pb->service, "getprop") == 0) {
printk("getprop(0x%08lx, \"%s\", 0x%08lx, %ld) = ",
pb->args[0], (char*)pb->args[1],
pb->args[2], pb->args[3]);
} else if (strcmp(pb->service, "nextprop") == 0) {
printk("nextprop(0x%08lx, \"%s\", 0x%08lx) = ",
pb->args[0], (char*)pb->args[1], pb->args[2]);
} else if (strcmp(pb->service, "setprop") == 0) {
printk("setprop(0x%08lx, \"%s\", 0x%08lx, %ld)\n",
pb->args[0], (char*)pb->args[1],
pb->args[2], pb->args[3]);
memdump((char*)pb->args[2], pb->args[3]);
printk(" = ");
} else if (strcmp(pb->service, "canon") == 0) {
printk("canon(\"%s\", 0x%08lx, %ld)\n",
(char*)pb->args[0], pb->args[1], pb->args[2]);
} else if (strcmp(pb->service, "finddevice") == 0) {
printk("finddevice(\"%s\") = ", (char*)pb->args[0]);
} else if (strcmp(pb->service, "instance-to-path") == 0) {
printk("instance-to-path(0x%08lx, 0x%08lx, %ld) = ",
pb->args[0], pb->args[1], pb->args[2]);
} else if (strcmp(pb->service, "package-to-path") == 0) {
printk("package-to-path(0x%08lx, 0x%08lx, %ld) = ",
pb->args[0], pb->args[1], pb->args[2]);
} else if (strcmp(pb->service, "open") == 0) {
printk("open(\"%s\") = ", (char*)pb->args[0]);
} else if (strcmp(pb->service, "close") == 0) {
printk("close(0x%08lx)\n", pb->args[0]);
} else if (strcmp(pb->service, "read") == 0) {
#ifdef DUMP_IO
printk("read(0x%08lx, 0x%08lx, %ld) = ",
pb->args[0], pb->args[1], pb->args[2]);
#endif
} else if (strcmp(pb->service, "write") == 0) {
#ifdef DUMP_IO
printk("write(0x%08lx, 0x%08lx, %ld)\n",
pb->args[0], pb->args[1], pb->args[2]);
memdump((char*)pb->args[1], pb->args[2]);
printk(" = ");
#endif
} else if (strcmp(pb->service, "seek") == 0) {
#ifdef DUMP_IO
printk("seek(0x%08lx, 0x%08lx, 0x%08lx) = ",
pb->args[0], pb->args[1], pb->args[2]);
#endif
} else if (strcmp(pb->service, "claim") == 0) {
printk("claim(0x%08lx, %ld, %ld) = ",
pb->args[0], pb->args[1], pb->args[2]);
} else if (strcmp(pb->service, "release") == 0) {
printk("release(0x%08lx, %ld)\n",
pb->args[0], pb->args[1]);
} else if (strcmp(pb->service, "boot") == 0) {
printk("boot \"%s\"\n", (char*)pb->args[0]);
} else if (strcmp(pb->service, "enter") == 0) {
printk("enter()\n");
} else if (strcmp(pb->service, "exit") == 0) {
printk("exit()\n");
} else if (strcmp(pb->service, "test-method") == 0) {
printk("test-method(0x%08lx, \"%s\") = ",
pb->args[0], (char*)pb->args[1]);
} else {
printk("of_client_interface: %s ", pb->service );
for( i = 0; i < pb->nargs; i++ )
printk("%lx ", pb->args[i] );
printk("\n");
}
}
static void dump_return(prom_args_t *pb)
{
int i;
if (strcmp(pb->service, "test") == 0) {
printk(" %ld\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "peer") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "child") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "parent") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "instance-to-package") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "getproplen") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "getprop") == 0) {
printk("%ld\n", pb->args[pb->nargs]);
if ((long)pb->args[pb->nargs] != -1)
memdump((char*)pb->args[2], MIN(pb->args[3], pb->args[pb->nargs]));
} else if (strcmp(pb->service, "nextprop") == 0) {
printk("%ld\n", pb->args[pb->nargs]);
memdump((char*)pb->args[2], pb->args[pb->nargs]);
} else if (strcmp(pb->service, "setprop") == 0) {
printk("%ld\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "canon") == 0) {
printk("%ld\n", pb->args[pb->nargs]);
memdump((char*)pb->args[1], pb->args[pb->nargs]);
} else if (strcmp(pb->service, "finddevice") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "instance-to-path") == 0) {
printk("%ld\n", pb->args[pb->nargs]);
memdump((char*)pb->args[1], pb->args[pb->nargs]);
} else if (strcmp(pb->service, "package-to-path") == 0) {
printk("%ld\n", pb->args[pb->nargs]);
memdump((char*)pb->args[1], pb->args[pb->nargs]);
} else if (strcmp(pb->service, "open") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "close") == 0) {
/* do nothing */
} else if (strcmp(pb->service, "read") == 0) {
#ifdef DUMP_IO
printk("%ld\n", pb->args[pb->nargs]);
memdump((char*)pb->args[1], pb->args[pb->nargs]);
#endif
} else if (strcmp(pb->service, "write") == 0) {
#ifdef DUMP_IO
printk("%ld\n", pb->args[pb->nargs]);
#endif
} else if (strcmp(pb->service, "seek") == 0) {
#ifdef DUMP_IO
printk("%ld\n", pb->args[pb->nargs]);
#endif
} else if (strcmp(pb->service, "claim") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else if (strcmp(pb->service, "release") == 0) {
/* do nothing */
} else if (strcmp(pb->service, "boot") == 0) {
/* do nothing */
} else if (strcmp(pb->service, "enter") == 0) {
/* do nothing */
} else if (strcmp(pb->service, "exit") == 0) {
/* do nothing */
} else if (strcmp(pb->service, "test-method") == 0) {
printk("0x%08lx\n", pb->args[pb->nargs]);
} else {
printk("of_client_interface return:");
for (i = 0; i < pb->nret; i++) {
printk(" %lx", pb->args[pb->nargs + i]);
}
printk("\n");
}
}
#endif
/* call-method, interpret */
static int
handle_calls( prom_args_t *pb )
{
int i, dstacksave = dstackcnt;
long val;
#ifdef DEBUG_CIF
printk("%s %s ([%ld] -- [%ld])\n", pb->service, (char *)pb->args[0],
pb->nargs, pb->nret);
#endif
for( i=pb->nargs-1; i>=0; i-- )
PUSH( pb->args[i] );
push_str( pb->service );
fword("client-call-iface");
/* Drop the return code from client-call-iface (status is handled by the
catch result which is the first parameter below) */
POP();
for( i=0; i<pb->nret; i++ ) {
val = POP();
pb->args[pb->nargs + i] = val;
/* don't pop args if an exception occured */
if( !i && val )
break;
}
#ifdef DEBUG_CIF
/* useful for debug but not necessarily an error */
if( i != pb->nret || dstackcnt != dstacksave ) {
printk("%s '%s': possible argument error (%ld--%ld) got %d\n",
pb->service, (char*)pb->args[0], pb->nargs-2, pb->nret, i );
}
printk("handle_calls return: ");
for (i = 0; i < pb->nret; i++) {
printk("%lx ", pb->args[pb->nargs + i]);
}
printk("\n");
#endif
dstackcnt = dstacksave;
return 0;
}
int
of_client_interface( int *params )
{
prom_args_t *pb = (prom_args_t*)params;
int val, i, dstacksave;
if( pb->nargs < 0 || pb->nret < 0 ||
pb->nargs + pb->nret > PROM_MAX_ARGS)
return -1;
#ifdef DEBUG_CIF
dump_service(pb);
#endif
/* call-method exceptions are special */
if( !strcmp("call-method", pb->service) || !strcmp("interpret", pb->service) )
return handle_calls( pb );
dstacksave = dstackcnt;
for( i=pb->nargs-1; i>=0; i-- )
PUSH( pb->args[i] );
push_str( pb->service );
fword("client-iface");
if( (val=POP()) ) {
dstackcnt = dstacksave;
if( val == -1 )
printk("Unimplemented service %s ([%ld] -- [%ld])\n",
pb->service, pb->nargs, pb->nret );
#ifdef DEBUG_CIF
else
printk("ERROR!\n");
#endif
return -1;
}
for( i=0; i<pb->nret ; i++ )
pb->args[pb->nargs + i] = POP();
if( dstackcnt != dstacksave ) {
#ifdef DEBUG_CIF
printk("service %s: possible argument error (%d %d)\n",
pb->service, i, dstackcnt - dstacksave );
#endif
/* Some clients request less parameters than the CIF method
returns, e.g. getprop with OpenSolaris. Hence we drop any
stack parameters after issuing a warning above */
dstackcnt = dstacksave;
}
#ifdef DEBUG_CIF
dump_return(pb);
#endif
return 0;
}