1 #include "vof.h" 2 3 struct prom_args { 4 uint32_t service; 5 uint32_t nargs; 6 uint32_t nret; 7 uint32_t args[10]; 8 }; 9 10 typedef unsigned long prom_arg_t; 11 12 #define ADDR(x) (uint32_t)(x) 13 14 static int prom_handle(struct prom_args *pargs) 15 { 16 void *rtasbase; 17 uint32_t rtassize = 0; 18 phandle rtas; 19 20 if (strcmp("call-method", (void *)(unsigned long)pargs->service)) { 21 return -1; 22 } 23 24 if (strcmp("instantiate-rtas", (void *)(unsigned long)pargs->args[0])) { 25 return -1; 26 } 27 28 rtas = ci_finddevice("/rtas"); 29 /* rtas-size is set by QEMU depending of FWNMI support */ 30 ci_getprop(rtas, "rtas-size", &rtassize, sizeof(rtassize)); 31 if (rtassize < hv_rtas_size) { 32 return -1; 33 } 34 35 rtasbase = (void *)(unsigned long) pargs->args[2]; 36 37 memcpy(rtasbase, hv_rtas, hv_rtas_size); 38 pargs->args[pargs->nargs] = 0; 39 pargs->args[pargs->nargs + 1] = pargs->args[2]; 40 41 return 0; 42 } 43 44 void prom_entry(uint32_t args) 45 { 46 if (prom_handle((void *)(unsigned long) args)) { 47 ci_entry(args); 48 } 49 } 50 51 static int call_ci(const char *service, int nargs, int nret, ...) 52 { 53 int i; 54 struct prom_args args; 55 va_list list; 56 57 args.service = ADDR(service); 58 args.nargs = nargs; 59 args.nret = nret; 60 61 va_start(list, nret); 62 for (i = 0; i < nargs; i++) { 63 args.args[i] = va_arg(list, prom_arg_t); 64 } 65 va_end(list); 66 67 for (i = 0; i < nret; i++) { 68 args.args[nargs + i] = 0; 69 } 70 71 if (ci_entry((uint32_t)(&args)) < 0) { 72 return -1; 73 } 74 75 return (nret > 0) ? args.args[nargs] : 0; 76 } 77 78 void ci_panic(const char *str) 79 { 80 call_ci("exit", 0, 0); 81 } 82 83 phandle ci_finddevice(const char *path) 84 { 85 return call_ci("finddevice", 1, 1, path); 86 } 87 88 uint32_t ci_getprop(phandle ph, const char *propname, void *prop, int len) 89 { 90 return call_ci("getprop", 4, 1, ph, propname, prop, len); 91 } 92