|
|
1.1 ! root 1: /* ! 2: * Creation Date: <2003/11/25 14:29:08 samuel> ! 3: * Time-stamp: <2004/03/27 01:13:53 samuel> ! 4: * ! 5: * <client.c> ! 6: * ! 7: * OpenFirmware client interface ! 8: * ! 9: * Copyright (C) 2003, 2004 Samuel Rydh ([email protected]) ! 10: * ! 11: * This program is free software; you can redistribute it and/or ! 12: * modify it under the terms of the GNU General Public License ! 13: * version 2 ! 14: * ! 15: */ ! 16: ! 17: #include "config.h" ! 18: #include "libopenbios/bindings.h" ! 19: #include "libopenbios/of.h" ! 20: ! 21: /* Uncomment to enable debug printout of client interface calls */ ! 22: //#define DEBUG_CIF ! 23: //#define DUMP_IO ! 24: ! 25: /* OF client interface. r3 points to the argument array. On return, ! 26: * r3 should contain 0==true or -1==false. r4-r12,cr0,cr1 may ! 27: * be modified freely. ! 28: * ! 29: * -1 should only be returned if the control transfer to OF fails ! 30: * (it doesn't) or if the function is unimplemented. ! 31: */ ! 32: ! 33: #define PROM_MAX_ARGS 10 ! 34: typedef struct prom_args { ! 35: prom_uarg_t service; ! 36: prom_arg_t nargs; ! 37: prom_arg_t nret; ! 38: prom_uarg_t args[PROM_MAX_ARGS]; ! 39: } __attribute__((packed)) prom_args_t; ! 40: ! 41: static inline const char * ! 42: arg2pointer(prom_uarg_t value) ! 43: { ! 44: return (char*)(uintptr_t)value; ! 45: } ! 46: ! 47: static inline const char * ! 48: get_service(prom_args_t *pb) ! 49: { ! 50: return arg2pointer(pb->service); ! 51: } ! 52: ! 53: #ifdef DEBUG_CIF ! 54: static void memdump(const char *mem, unsigned long size) ! 55: { ! 56: int i; ! 57: ! 58: if (size == (unsigned long) -1) ! 59: return; ! 60: ! 61: for (i = 0; i < size; i += 16) { ! 62: int j; ! 63: ! 64: printk("0x%08lx ", (unsigned long)mem + i); ! 65: ! 66: for (j = 0; j < 16 && i + j < size; j++) ! 67: printk(" %02x", *(unsigned char*)(mem + i + j)); ! 68: ! 69: for ( ; j < 16; j++) ! 70: printk(" __"); ! 71: ! 72: printk(" "); ! 73: ! 74: for (j = 0; j < 16 && i + j < size; j++) { ! 75: unsigned char c = *(mem + i + j); ! 76: if (isprint(c)) ! 77: printk("%c", c); ! 78: else ! 79: printk("."); ! 80: } ! 81: printk("\n"); ! 82: } ! 83: } ! 84: ! 85: static void dump_service(prom_args_t *pb) ! 86: { ! 87: int i; ! 88: const char *service = get_service(pb); ! 89: if (strcmp(service, "test") == 0) { ! 90: printk("test(\"%s\") = ", arg2pointer(pb->args[0])); ! 91: } else if (strcmp(service, "peer") == 0) { ! 92: printk("peer(0x" FMT_prom_uargx ") = ", pb->args[0]); ! 93: } else if (strcmp(service, "child") == 0) { ! 94: printk("child(0x" FMT_prom_uargx ") = ", pb->args[0]); ! 95: } else if (strcmp(service, "parent") == 0) { ! 96: printk("parent(0x" FMT_prom_uargx ") = ", pb->args[0]); ! 97: } else if (strcmp(service, "instance-to-package") == 0) { ! 98: printk("instance-to-package(0x" FMT_prom_uargx ") = ", pb->args[0]); ! 99: } else if (strcmp(service, "getproplen") == 0) { ! 100: printk("getproplen(0x" FMT_prom_uargx ", \"%s\") = ", ! 101: pb->args[0], arg2pointer(pb->args[1])); ! 102: } else if (strcmp(service, "getprop") == 0) { ! 103: printk("getprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", ! 104: pb->args[0], arg2pointer(pb->args[1]), ! 105: pb->args[2], pb->args[3]); ! 106: } else if (strcmp(service, "nextprop") == 0) { ! 107: printk("nextprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ") = ", ! 108: pb->args[0], arg2pointer(pb->args[1]), pb->args[2]); ! 109: } else if (strcmp(service, "setprop") == 0) { ! 110: printk("setprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", ! 111: pb->args[0], arg2pointer(pb->args[1]), ! 112: pb->args[2], pb->args[3]); ! 113: memdump(arg2pointer(pb->args[2]), pb->args[3]); ! 114: printk(" = "); ! 115: } else if (strcmp(service, "canon") == 0) { ! 116: printk("canon(\"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", ! 117: arg2pointer(pb->args[0]), pb->args[1], pb->args[2]); ! 118: } else if (strcmp(service, "finddevice") == 0) { ! 119: printk("finddevice(\"%s\") = ", arg2pointer(pb->args[0])); ! 120: } else if (strcmp(service, "instance-to-path") == 0) { ! 121: printk("instance-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", ! 122: pb->args[0], pb->args[1], pb->args[2]); ! 123: } else if (strcmp(service, "package-to-path") == 0) { ! 124: printk("package-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", ! 125: pb->args[0], pb->args[1], pb->args[2]); ! 126: } else if (strcmp(service, "open") == 0) { ! 127: printk("open(\"%s\") = ", arg2pointer(pb->args[0])); ! 128: } else if (strcmp(service, "close") == 0) { ! 129: printk("close(0x" FMT_prom_uargx ")\n", pb->args[0]); ! 130: } else if (strcmp(service, "read") == 0) { ! 131: #ifdef DUMP_IO ! 132: printk("read(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", ! 133: pb->args[0], pb->args[1], pb->args[2]); ! 134: #endif ! 135: } else if (strcmp(service, "write") == 0) { ! 136: #ifdef DUMP_IO ! 137: printk("write(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", ! 138: pb->args[0], pb->args[1], pb->args[2]); ! 139: memdump(arg2pointer(pb->args[1]), pb->args[2]); ! 140: printk(" = "); ! 141: #endif ! 142: } else if (strcmp(service, "seek") == 0) { ! 143: #ifdef DUMP_IO ! 144: printk("seek(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ") = ", ! 145: pb->args[0], pb->args[1], pb->args[2]); ! 146: #endif ! 147: } else if (strcmp(service, "claim") == 0) { ! 148: printk("claim(0x" FMT_prom_uargx ", " FMT_prom_arg ", " FMT_prom_arg ") = ", ! 149: pb->args[0], pb->args[1], pb->args[2]); ! 150: } else if (strcmp(service, "release") == 0) { ! 151: printk("release(0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", ! 152: pb->args[0], pb->args[1]); ! 153: } else if (strcmp(service, "boot") == 0) { ! 154: printk("boot \"%s\"\n", arg2pointer(pb->args[0])); ! 155: } else if (strcmp(service, "enter") == 0) { ! 156: printk("enter()\n"); ! 157: } else if (strcmp(service, "exit") == 0) { ! 158: printk("exit()\n"); ! 159: } else if (strcmp(service, "test-method") == 0) { ! 160: printk("test-method(0x" FMT_prom_uargx ", \"%s\") = ", ! 161: pb->args[0], arg2pointer(pb->args[1])); ! 162: } else { ! 163: printk("of_client_interface: %s", service); ! 164: for( i = 0; i < pb->nargs; i++ ) ! 165: printk(" " FMT_prom_uargx, pb->args[i]); ! 166: printk("\n"); ! 167: } ! 168: } ! 169: ! 170: static void dump_return(prom_args_t *pb) ! 171: { ! 172: int i; ! 173: const char *service = get_service(pb); ! 174: if (strcmp(service, "test") == 0) { ! 175: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 176: } else if (strcmp(service, "peer") == 0) { ! 177: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 178: } else if (strcmp(service, "child") == 0) { ! 179: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 180: } else if (strcmp(service, "parent") == 0) { ! 181: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 182: } else if (strcmp(service, "instance-to-package") == 0) { ! 183: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 184: } else if (strcmp(service, "getproplen") == 0) { ! 185: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 186: } else if (strcmp(service, "getprop") == 0) { ! 187: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 188: if ((prom_arg_t)pb->args[pb->nargs] != -1) ! 189: memdump(arg2pointer(pb->args[2]), MIN(pb->args[3], pb->args[pb->nargs])); ! 190: } else if (strcmp(service, "nextprop") == 0) { ! 191: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 192: memdump(arg2pointer(pb->args[2]), pb->args[pb->nargs]); ! 193: } else if (strcmp(service, "setprop") == 0) { ! 194: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 195: } else if (strcmp(service, "canon") == 0) { ! 196: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 197: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); ! 198: } else if (strcmp(service, "finddevice") == 0) { ! 199: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 200: } else if (strcmp(service, "instance-to-path") == 0) { ! 201: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 202: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); ! 203: } else if (strcmp(service, "package-to-path") == 0) { ! 204: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 205: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); ! 206: } else if (strcmp(service, "open") == 0) { ! 207: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 208: } else if (strcmp(service, "close") == 0) { ! 209: /* do nothing */ ! 210: } else if (strcmp(service, "read") == 0) { ! 211: #ifdef DUMP_IO ! 212: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 213: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); ! 214: #endif ! 215: } else if (strcmp(service, "write") == 0) { ! 216: #ifdef DUMP_IO ! 217: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 218: #endif ! 219: } else if (strcmp(service, "seek") == 0) { ! 220: #ifdef DUMP_IO ! 221: printk(FMT_prom_arg "\n", pb->args[pb->nargs]); ! 222: #endif ! 223: } else if (strcmp(service, "claim") == 0) { ! 224: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 225: } else if (strcmp(service, "release") == 0) { ! 226: /* do nothing */ ! 227: } else if (strcmp(service, "boot") == 0) { ! 228: /* do nothing */ ! 229: } else if (strcmp(service, "enter") == 0) { ! 230: /* do nothing */ ! 231: } else if (strcmp(service, "exit") == 0) { ! 232: /* do nothing */ ! 233: } else if (strcmp(service, "test-method") == 0) { ! 234: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); ! 235: } else { ! 236: printk("of_client_interface return:"); ! 237: for (i = 0; i < pb->nret; i++) { ! 238: printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]); ! 239: } ! 240: printk("\n"); ! 241: } ! 242: } ! 243: #endif ! 244: ! 245: /* call-method, interpret */ ! 246: static int ! 247: handle_calls( prom_args_t *pb ) ! 248: { ! 249: int i, dstacksave = dstackcnt; ! 250: prom_uarg_t val; ! 251: ! 252: #ifdef DEBUG_CIF ! 253: printk("%s %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n", ! 254: get_service(pb), arg2pointer(pb->args[0]), pb->nargs, pb->nret); ! 255: #endif ! 256: ! 257: for( i=pb->nargs-1; i>=0; i-- ) ! 258: PUSH( pb->args[i] ); ! 259: ! 260: push_str(get_service(pb)); ! 261: fword("client-call-iface"); ! 262: ! 263: /* Drop the return code from client-call-iface (status is handled by the ! 264: catch result which is the first parameter below) */ ! 265: POP(); ! 266: ! 267: for( i=0; i<pb->nret; i++ ) { ! 268: val = POP(); ! 269: pb->args[pb->nargs + i] = val; ! 270: ! 271: /* don't pop args if an exception occured */ ! 272: if( !i && val ) ! 273: break; ! 274: } ! 275: ! 276: #ifdef DEBUG_CIF ! 277: /* useful for debug but not necessarily an error */ ! 278: if (i != pb->nret || dstackcnt != dstacksave) { ! 279: printk("%s '%s': possible argument error (" FMT_prom_arg "--" FMT_prom_arg ") got %d\n", ! 280: get_service(pb), arg2pointer(pb->args[0]), ! 281: pb->nargs - 2, pb->nret, i); ! 282: } ! 283: ! 284: printk("handle_calls return:"); ! 285: for (i = 0; i < pb->nret; i++) { ! 286: printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]); ! 287: } ! 288: printk("\n"); ! 289: #endif ! 290: ! 291: dstackcnt = dstacksave; ! 292: return 0; ! 293: } ! 294: ! 295: int ! 296: of_client_interface( int *params ) ! 297: { ! 298: prom_args_t *pb = (prom_args_t*)params; ! 299: int val, i, dstacksave; ! 300: ! 301: if( pb->nargs < 0 || pb->nret < 0 || ! 302: pb->nargs + pb->nret > PROM_MAX_ARGS) ! 303: return -1; ! 304: ! 305: #ifdef DEBUG_CIF ! 306: dump_service(pb); ! 307: #endif ! 308: ! 309: /* call-method exceptions are special */ ! 310: if (!strcmp("call-method", get_service(pb)) || !strcmp("interpret", get_service(pb))) ! 311: return handle_calls( pb ); ! 312: ! 313: dstacksave = dstackcnt; ! 314: for( i=pb->nargs-1; i>=0; i-- ) ! 315: PUSH( pb->args[i] ); ! 316: ! 317: push_str(get_service(pb)); ! 318: fword("client-iface"); ! 319: ! 320: if( (val=POP()) ) { ! 321: dstackcnt = dstacksave; ! 322: if( val == -1 ) ! 323: printk("Unimplemented service %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n", ! 324: get_service(pb), pb->nargs, pb->nret ); ! 325: #ifdef DEBUG_CIF ! 326: else ! 327: printk("ERROR!\n"); ! 328: #endif ! 329: return -1; ! 330: } ! 331: ! 332: for( i=0; i<pb->nret ; i++ ) ! 333: pb->args[pb->nargs + i] = POP(); ! 334: ! 335: if( dstackcnt != dstacksave ) { ! 336: #ifdef DEBUG_CIF ! 337: printk("service %s: possible argument error (%d %d)\n", ! 338: get_service(pb), i, dstackcnt - dstacksave ); ! 339: #endif ! 340: /* Some clients request less parameters than the CIF method ! 341: returns, e.g. getprop with OpenSolaris. Hence we drop any ! 342: stack parameters after issuing a warning above */ ! 343: dstackcnt = dstacksave; ! 344: } ! 345: ! 346: #ifdef DEBUG_CIF ! 347: dump_return(pb); ! 348: #endif ! 349: return 0; ! 350: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.