#include "vof.h" struct prom_args { uint32_t service; uint32_t nargs; uint32_t nret; uint32_t args[10]; }; typedef unsigned long prom_arg_t; #define ADDR(x) (uint32_t)(x) static int prom_handle(struct prom_args *pargs) { void *rtasbase; uint32_t rtassize = 0; phandle rtas; if (strcmp("call-method", (void *)(unsigned long)pargs->service)) { return -1; } if (strcmp("instantiate-rtas", (void *)(unsigned long)pargs->args[0])) { return -1; } rtas = ci_finddevice("/rtas"); /* rtas-size is set by QEMU depending of FWNMI support */ ci_getprop(rtas, "rtas-size", &rtassize, sizeof(rtassize)); if (rtassize < hv_rtas_size) { return -1; } rtasbase = (void *)(unsigned long) pargs->args[2]; memcpy(rtasbase, hv_rtas, hv_rtas_size); pargs->args[pargs->nargs] = 0; pargs->args[pargs->nargs + 1] = pargs->args[2]; return 0; } void prom_entry(uint32_t args) { if (prom_handle((void *)(unsigned long) args)) { ci_entry(args); } } static int call_ci(const char *service, int nargs, int nret, ...) { int i; struct prom_args args; va_list list; args.service = ADDR(service); args.nargs = nargs; args.nret = nret; va_start(list, nret); for (i = 0; i < nargs; i++) { args.args[i] = va_arg(list, prom_arg_t); } va_end(list); for (i = 0; i < nret; i++) { args.args[nargs + i] = 0; } if (ci_entry((uint32_t)(&args)) < 0) { return -1; } return (nret > 0) ? args.args[nargs] : 0; } void ci_panic(const char *str) { call_ci("exit", 0, 0); } phandle ci_finddevice(const char *path) { return call_ci("finddevice", 1, 1, path); } uint32_t ci_getprop(phandle ph, const char *propname, void *prop, int len) { return call_ci("getprop", 4, 1, ph, propname, prop, len); }