xref: /qemu/pc-bios/vof/ci.c (revision b355f08a)
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