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
prom_handle(struct prom_args * pargs)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
prom_entry(uint32_t args)44 void prom_entry(uint32_t args)
45 {
46 if (prom_handle((void *)(unsigned long) args)) {
47 ci_entry(args);
48 }
49 }
50
call_ci(const char * service,int nargs,int nret,...)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
ci_panic(const char * str)78 void ci_panic(const char *str)
79 {
80 call_ci("exit", 0, 0);
81 }
82
ci_finddevice(const char * path)83 phandle ci_finddevice(const char *path)
84 {
85 return call_ci("finddevice", 1, 1, path);
86 }
87
ci_getprop(phandle ph,const char * propname,void * prop,int len)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