diff --git a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp index b365b9e23d..2979da7a96 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp @@ -654,7 +654,8 @@ arch_set_callback(void) // instead of maintaining it itself void *oldCallback = NULL; - if (of_call_method("set-callback", 1, 1, &callback, &oldCallback) == OF_FAILED) { + if (of_call_client_function("set-callback", 1, 1, &callback, &oldCallback) + == OF_FAILED) { puts("set-callback failed!"); return B_ERROR; } diff --git a/src/system/boot/platform/openfirmware/openfirmware.c b/src/system/boot/platform/openfirmware/openfirmware.c index 1f958131c3..44350f0355 100644 --- a/src/system/boot/platform/openfirmware/openfirmware.c +++ b/src/system/boot/platform/openfirmware/openfirmware.c @@ -27,7 +27,7 @@ of_init(int (*openFirmwareEntry)(void *)) int -of_call_method(const char *method, int numArgs, int numReturns, ...) +of_call_client_function(const char *method, int numArgs, int numReturns, ...) { struct { const char *name; @@ -83,7 +83,58 @@ of_interpret(const char *command, int numArgs, int numReturns, ...) // stack_result items." const char *command; void *args[13]; - } args = {"interpret", numArgs + 1, numReturns, command}; + } args = {"interpret", numArgs + 1, numReturns + 1, command}; + va_list list; + int i; + + // iterate over all arguments and copy them into the + // structure passed over to the OpenFirmware + + va_start(list, numReturns); + for (i = 0; i < numArgs; i++) { + // copy args + args.args[i] = (void *)va_arg(list, void *); + } + for (i = numArgs; i < numArgs + numReturns + 1; i++) { + // clear return values + args.args[i] = NULL; + } + + // args.args[numArgs] is the "catch-result" return value + if (gCallOpenFirmware(&args) == OF_FAILED || args.args[numArgs]) + return OF_FAILED; + + if (numReturns > 0) { + // copy return values over to the provided location + + for (i = numArgs + 1; i < numArgs + 1 + numReturns; i++) { + void **store = va_arg(list, void **); + if (store) + *store = args.args[i]; + } + } + va_end(list); + + return 0; +} + + +int +of_call_method(int handle, const char *method, int numArgs, int numReturns, ...) +{ + struct { + const char *name; + int num_args; + int num_returns; + // "IN: [string] method, ihandle, stack_arg1, ..., stack_argP + // OUT: catch-result, stack_result1, ..., stack_resultQ + // [...] + // An implementation shall allow at least six stack_arg and six + // stack_result items." + const char *method; + int handle; + void *args[13]; + } args = {"call-method", numArgs + 2, numReturns + 1, method, handle}; va_list list; int i; diff --git a/src/system/boot/platform/openfirmware/openfirmware.h b/src/system/boot/platform/openfirmware/openfirmware.h index 75fe63371c..9e75fc10e6 100644 --- a/src/system/boot/platform/openfirmware/openfirmware.h +++ b/src/system/boot/platform/openfirmware/openfirmware.h @@ -46,9 +46,12 @@ extern int of_peer(int node); extern int of_parent(int node); extern int of_instance_to_path(int instance, char *pathBuffer, int bufferSize); extern int of_instance_to_package(int instance); -extern int of_getprop(int package, const char *property, void *buffer, int bufferSize); -extern int of_setprop(int package, const char *property, const void *buffer, int bufferSize); -extern int of_nextprop(int package, const char *previousProperty, char *nextProperty); +extern int of_getprop(int package, const char *property, void *buffer, + int bufferSize); +extern int of_setprop(int package, const char *property, const void *buffer, + int bufferSize); +extern int of_nextprop(int package, const char *previousProperty, + char *nextProperty); extern int of_getproplen(int package, const char *property); extern int of_package_to_path(int package, char *pathBuffer, int bufferSize); @@ -64,8 +67,11 @@ extern int of_release(void *virtualAddress, int size); extern void *of_claim(void *virtualAddress, int size, int align); /* misc functions */ -extern int of_call_method(const char *method, int numArgs, int numReturns, ...); +extern int of_call_client_function(const char *method, int numArgs, + int numReturns, ...); extern int of_interpret(const char *command, int numArgs, int numReturns, ...); +extern int of_call_method(int handle, const char *method, int numArgs, + int numReturns, ...); extern int of_test(const char *service); extern int of_milliseconds(void); extern void of_exit(void);