1 /* 2 * Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <platform/openfirmware/openfirmware.h> 7 8 #include <stdarg.h> 9 10 11 // OpenFirmware entry function 12 static int (*gCallOpenFirmware)(void *) = 0; 13 int gChosen; 14 15 16 status_t 17 of_init(int (*openFirmwareEntry)(void *)) 18 { 19 gCallOpenFirmware = openFirmwareEntry; 20 21 gChosen = of_finddevice("/chosen"); 22 if (gChosen == OF_FAILED) 23 return B_ERROR; 24 25 return B_OK; 26 } 27 28 29 int 30 of_call_client_function(const char *method, int numArgs, int numReturns, ...) 31 { 32 struct { 33 const char *name; 34 int num_args; 35 int num_returns; 36 void *args[10]; 37 } args = {method, numArgs, numReturns}; 38 va_list list; 39 int i; 40 41 // iterate over all arguments and copy them into the 42 // structure passed over to the OpenFirmware 43 44 va_start(list, numReturns); 45 for (i = 0; i < numArgs; i++) { 46 // copy args 47 args.args[i] = (void *)va_arg(list, void *); 48 } 49 for (i = numArgs; i < numArgs + numReturns; i++) { 50 // clear return values 51 args.args[i] = NULL; 52 } 53 54 if (gCallOpenFirmware(&args) == OF_FAILED) 55 return OF_FAILED; 56 57 if (numReturns > 0) { 58 // copy return values over to the provided location 59 60 for (i = numArgs; i < numArgs + numReturns; i++) { 61 void **store = va_arg(list, void **); 62 if (store) 63 *store = args.args[i]; 64 } 65 } 66 va_end(list); 67 68 return 0; 69 } 70 71 72 int 73 of_interpret(const char *command, int numArgs, int numReturns, ...) 74 { 75 struct { 76 const char *name; 77 int num_args; 78 int num_returns; 79 // "IN: [string] cmd, stack_arg1, ..., stack_argP 80 // OUT: catch-result, stack_result1, ..., stack_resultQ 81 // [...] 82 // An implementation shall allow at least six stack_arg and six 83 // stack_result items." 84 const char *command; 85 void *args[13]; 86 } args = {"interpret", numArgs + 1, numReturns + 1, command}; 87 va_list list; 88 int i; 89 90 // iterate over all arguments and copy them into the 91 // structure passed over to the OpenFirmware 92 93 va_start(list, numReturns); 94 for (i = 0; i < numArgs; i++) { 95 // copy args 96 args.args[i] = (void *)va_arg(list, void *); 97 } 98 for (i = numArgs; i < numArgs + numReturns + 1; i++) { 99 // clear return values 100 args.args[i] = NULL; 101 } 102 103 // args.args[numArgs] is the "catch-result" return value 104 if (gCallOpenFirmware(&args) == OF_FAILED || args.args[numArgs]) 105 return OF_FAILED; 106 107 if (numReturns > 0) { 108 // copy return values over to the provided location 109 110 for (i = numArgs + 1; i < numArgs + 1 + numReturns; i++) { 111 void **store = va_arg(list, void **); 112 if (store) 113 *store = args.args[i]; 114 } 115 } 116 va_end(list); 117 118 return 0; 119 } 120 121 122 int 123 of_call_method(int handle, const char *method, int numArgs, int numReturns, ...) 124 { 125 struct { 126 const char *name; 127 int num_args; 128 int num_returns; 129 // "IN: [string] method, ihandle, stack_arg1, ..., stack_argP 130 // OUT: catch-result, stack_result1, ..., stack_resultQ 131 // [...] 132 // An implementation shall allow at least six stack_arg and six 133 // stack_result items." 134 const char *method; 135 int handle; 136 void *args[13]; 137 } args = {"call-method", numArgs + 2, numReturns + 1, method, handle}; 138 va_list list; 139 int i; 140 141 // iterate over all arguments and copy them into the 142 // structure passed over to the OpenFirmware 143 144 va_start(list, numReturns); 145 for (i = 0; i < numArgs; i++) { 146 // copy args 147 args.args[i] = (void *)va_arg(list, void *); 148 } 149 for (i = numArgs; i < numArgs + numReturns + 1; i++) { 150 // clear return values 151 args.args[i] = NULL; 152 } 153 154 // args.args[numArgs] is the "catch-result" return value 155 if (gCallOpenFirmware(&args) == OF_FAILED || args.args[numArgs]) 156 return OF_FAILED; 157 158 if (numReturns > 0) { 159 // copy return values over to the provided location 160 161 for (i = numArgs + 1; i < numArgs + 1 + numReturns; i++) { 162 void **store = va_arg(list, void **); 163 if (store) 164 *store = args.args[i]; 165 } 166 } 167 va_end(list); 168 169 return 0; 170 } 171 172 173 int 174 of_finddevice(const char *device) 175 { 176 struct { 177 const char *name; 178 int num_args; 179 int num_returns; 180 const char *device; 181 int handle; 182 } args = {"finddevice", 1, 1, device, 0}; 183 184 if (gCallOpenFirmware(&args) == OF_FAILED) 185 return OF_FAILED; 186 187 return args.handle; 188 } 189 190 191 /** Returns the first child of the given node 192 */ 193 194 int 195 of_child(int node) 196 { 197 struct { 198 const char *name; 199 int num_args; 200 int num_returns; 201 int node; 202 int child; 203 } args = {"child", 1, 1, node, 0}; 204 205 if (gCallOpenFirmware(&args) == OF_FAILED) 206 return OF_FAILED; 207 208 return args.child; 209 } 210 211 212 /** Returns the next sibling of the given node 213 */ 214 215 int 216 of_peer(int node) 217 { 218 struct { 219 const char *name; 220 int num_args; 221 int num_returns; 222 int node; 223 int next_sibling; 224 } args = {"peer", 1, 1, node, 0}; 225 226 if (gCallOpenFirmware(&args) == OF_FAILED) 227 return OF_FAILED; 228 229 return args.next_sibling; 230 } 231 232 233 /** Returns the parent of the given node 234 */ 235 236 int 237 of_parent(int node) 238 { 239 struct { 240 const char *name; 241 int num_args; 242 int num_returns; 243 int node; 244 int parent; 245 } args = {"parent", 1, 1, node, 0}; 246 247 if (gCallOpenFirmware(&args) == OF_FAILED) 248 return OF_FAILED; 249 250 return args.parent; 251 } 252 253 254 int 255 of_instance_to_path(int instance, char *pathBuffer, int bufferSize) 256 { 257 struct { 258 const char *name; 259 int num_args; 260 int num_returns; 261 int instance; 262 char *path_buffer; 263 int buffer_size; 264 int size; 265 } args = {"instance-to-path", 3, 1, instance, pathBuffer, bufferSize, 0}; 266 267 if (gCallOpenFirmware(&args) == OF_FAILED) 268 return OF_FAILED; 269 270 return args.size; 271 } 272 273 274 int 275 of_instance_to_package(int instance) 276 { 277 struct { 278 const char *name; 279 int num_args; 280 int num_returns; 281 int instance; 282 int package; 283 } args = {"instance-to-package", 1, 1, instance, 0}; 284 285 if (gCallOpenFirmware(&args) == OF_FAILED) 286 return OF_FAILED; 287 288 return args.package; 289 } 290 291 292 int 293 of_getprop(int package, const char *property, void *buffer, int bufferSize) 294 { 295 struct { 296 const char *name; 297 int num_args; 298 int num_returns; 299 int package; 300 const char *property; 301 void *buffer; 302 int buffer_size; 303 int size; 304 } args = {"getprop", 4, 1, package, property, buffer, bufferSize, 0}; 305 306 if (gCallOpenFirmware(&args) == OF_FAILED) 307 return OF_FAILED; 308 309 return args.size; 310 } 311 312 313 int 314 of_setprop(int package, const char *property, const void *buffer, int bufferSize) 315 { 316 struct { 317 const char *name; 318 int num_args; 319 int num_returns; 320 int package; 321 const char *property; 322 const void *buffer; 323 int buffer_size; 324 int size; 325 } args = {"setprop", 4, 1, package, property, buffer, bufferSize, 0}; 326 327 if (gCallOpenFirmware(&args) == OF_FAILED) 328 return OF_FAILED; 329 330 return args.size; 331 } 332 333 334 int 335 of_getproplen(int package, const char *property) 336 { 337 struct { 338 const char *name; 339 int num_args; 340 int num_returns; 341 int package; 342 const char *property; 343 int size; 344 } args = {"getproplen", 2, 1, package, property, 0}; 345 346 if (gCallOpenFirmware(&args) == OF_FAILED) 347 return OF_FAILED; 348 349 return args.size; 350 } 351 352 353 int 354 of_nextprop(int package, const char *previousProperty, char *nextProperty) 355 { 356 struct { 357 const char *name; 358 int num_args; 359 int num_returns; 360 int package; 361 const char *previous_property; 362 char *next_property; 363 int flag; 364 } args = {"nextprop", 3, 1, package, previousProperty, nextProperty, 0}; 365 366 if (gCallOpenFirmware(&args) == OF_FAILED) 367 return OF_FAILED; 368 369 return args.flag; 370 } 371 372 373 int 374 of_package_to_path(int package, char *pathBuffer, int bufferSize) 375 { 376 struct { 377 const char *name; 378 int num_args; 379 int num_returns; 380 int package; 381 char *path_buffer; 382 int buffer_size; 383 int size; 384 } args = {"package-to-path", 3, 1, package, pathBuffer, bufferSize, 0}; 385 386 if (gCallOpenFirmware(&args) == OF_FAILED) 387 return OF_FAILED; 388 389 return args.size; 390 } 391 392 393 // I/O functions 394 395 396 int 397 of_open(const char *nodeName) 398 { 399 struct { 400 const char *name; 401 int num_args; 402 int num_returns; 403 const char *node_name; 404 int handle; 405 } args = {"open", 1, 1, nodeName, 0}; 406 407 if (gCallOpenFirmware(&args) == OF_FAILED || args.handle == 0) 408 return OF_FAILED; 409 410 return args.handle; 411 } 412 413 414 void 415 of_close(int handle) 416 { 417 struct { 418 const char *name; 419 int num_args; 420 int num_returns; 421 int handle; 422 } args = {"close", 1, 0, handle}; 423 424 gCallOpenFirmware(&args); 425 } 426 427 428 int 429 of_read(int handle, void *buffer, int bufferSize) 430 { 431 struct { 432 const char *name; 433 int num_args; 434 int num_returns; 435 int handle; 436 void *buffer; 437 int buffer_size; 438 int size; 439 } args = {"read", 3, 1, handle, buffer, bufferSize, 0}; 440 441 if (gCallOpenFirmware(&args) == OF_FAILED) 442 return OF_FAILED; 443 444 return args.size; 445 } 446 447 448 int 449 of_write(int handle, const void *buffer, int bufferSize) 450 { 451 struct { 452 const char *name; 453 int num_args; 454 int num_returns; 455 int handle; 456 const void *buffer; 457 int buffer_size; 458 int size; 459 } args = {"write", 3, 1, handle, buffer, bufferSize, 0}; 460 461 if (gCallOpenFirmware(&args) == OF_FAILED) 462 return OF_FAILED; 463 464 return args.size; 465 } 466 467 468 int 469 of_seek(int handle, long long pos) 470 { 471 struct { 472 const char *name; 473 int num_args; 474 int num_returns; 475 int handle; 476 int64 pos; 477 int status; 478 } args = {"seek", 3, 1, handle, pos, 0}; 479 480 if (gCallOpenFirmware(&args) == OF_FAILED) 481 return OF_FAILED; 482 483 return args.status; 484 } 485 486 487 // memory functions 488 489 490 int 491 of_release(void *virtualAddress, int size) 492 { 493 struct { 494 const char *name; 495 int num_args; 496 int num_returns; 497 void *virtualAddress; 498 int size; 499 } args = {"release", 2, 0, virtualAddress, size}; 500 501 return gCallOpenFirmware(&args); 502 } 503 504 505 void * 506 of_claim(void *virtualAddress, int size, int align) 507 { 508 struct { 509 const char *name; 510 int num_args; 511 int num_returns; 512 void *virtualAddress; 513 int size; 514 int align; 515 void *address; 516 } args = {"claim", 3, 1, virtualAddress, size, align}; 517 518 if (gCallOpenFirmware(&args) == OF_FAILED) 519 return NULL; 520 521 return args.address; 522 } 523 524 525 // misc functions 526 527 528 /** tests if the given service is missing 529 */ 530 531 int 532 of_test(const char *service) 533 { 534 struct { 535 const char *name; 536 int num_args; 537 int num_returns; 538 const char *service; 539 int missing; 540 } args = {"test", 1, 1, service, 0}; 541 542 if (gCallOpenFirmware(&args) == OF_FAILED) 543 return OF_FAILED; 544 545 return args.missing; 546 } 547 548 549 /** Returns the millisecond counter 550 */ 551 552 int 553 of_milliseconds(void) 554 { 555 struct { 556 const char *name; 557 int num_args; 558 int num_returns; 559 int milliseconds; 560 } args = {"milliseconds", 0, 1, 0}; 561 562 if (gCallOpenFirmware(&args) == OF_FAILED) 563 return OF_FAILED; 564 565 return args.milliseconds; 566 } 567 568 569 void 570 of_exit(void) 571 { 572 struct { 573 const char *name; 574 int num_args; 575 int num_returns; 576 } args = {"exit", 0, 0}; 577 578 gCallOpenFirmware(&args); 579 } 580 581