1*06d2afa6SDavid du Colombier #include "all.h"
2*06d2afa6SDavid du Colombier #include <fcall.h>
3*06d2afa6SDavid du Colombier #include <thread.h>
4*06d2afa6SDavid du Colombier #include <9p.h> /* for emalloc9p */
5*06d2afa6SDavid du Colombier
6*06d2afa6SDavid du Colombier enum
7*06d2afa6SDavid du Colombier {
8*06d2afa6SDavid du Colombier /* high bits of u.cx */
9*06d2afa6SDavid du Colombier CmdOpen = 0x00,
10*06d2afa6SDavid du Colombier CmdSendsize = 0x01,
11*06d2afa6SDavid du Colombier CmdSenddata = 0x02,
12*06d2afa6SDavid du Colombier CmdRecvsize = 0x03,
13*06d2afa6SDavid du Colombier CmdRecvdata = 0x04,
14*06d2afa6SDavid du Colombier CmdRecvstatus = 0x05,
15*06d2afa6SDavid du Colombier CmdClose = 0x06,
16*06d2afa6SDavid du Colombier
17*06d2afa6SDavid du Colombier StatSuccess = 0x0001, /* request succeeded */
18*06d2afa6SDavid du Colombier StatHavedata = 0x0002, /* vmware has message available */
19*06d2afa6SDavid du Colombier StatClosed = 0x0004, /* channel got closed */
20*06d2afa6SDavid du Colombier StatUnsent = 0x0008, /* vmware removed message before it got delivered */
21*06d2afa6SDavid du Colombier StatChkpt = 0x0010, /* checkpoint occurred */
22*06d2afa6SDavid du Colombier StatPoweroff = 0x0020, /* underlying device is powering off */
23*06d2afa6SDavid du Colombier };
24*06d2afa6SDavid du Colombier
25*06d2afa6SDavid du Colombier
26*06d2afa6SDavid du Colombier Msgchan*
openmsg(ulong proto)27*06d2afa6SDavid du Colombier openmsg(ulong proto)
28*06d2afa6SDavid du Colombier {
29*06d2afa6SDavid du Colombier Msgchan *c;
30*06d2afa6SDavid du Colombier Ureg u;
31*06d2afa6SDavid du Colombier
32*06d2afa6SDavid du Colombier memset(&u, 0, sizeof u);
33*06d2afa6SDavid du Colombier u.cx = (CmdOpen<<16) | BackMessage;
34*06d2afa6SDavid du Colombier u.bx = proto;
35*06d2afa6SDavid du Colombier
36*06d2afa6SDavid du Colombier backdoor(&u, 0);
37*06d2afa6SDavid du Colombier
38*06d2afa6SDavid du Colombier fprint(2, "msgopen %.8lux\n", u.cx);
39*06d2afa6SDavid du Colombier if(!(u.cx & (StatSuccess<<16))){
40*06d2afa6SDavid du Colombier fprint(2, "message %.8lux\n", u.cx);
41*06d2afa6SDavid du Colombier werrstr("unable to open message channel (%.8lux)", u.cx);
42*06d2afa6SDavid du Colombier return nil;
43*06d2afa6SDavid du Colombier }
44*06d2afa6SDavid du Colombier
45*06d2afa6SDavid du Colombier c = emalloc9p(sizeof(*c));
46*06d2afa6SDavid du Colombier c->id = u.dx>>16;
47*06d2afa6SDavid du Colombier return c;
48*06d2afa6SDavid du Colombier }
49*06d2afa6SDavid du Colombier
50*06d2afa6SDavid du Colombier enum
51*06d2afa6SDavid du Colombier {
52*06d2afa6SDavid du Colombier Ok = 0,
53*06d2afa6SDavid du Colombier ErrBad = -1,
54*06d2afa6SDavid du Colombier ErrChkpt = -2,
55*06d2afa6SDavid du Colombier };
56*06d2afa6SDavid du Colombier
57*06d2afa6SDavid du Colombier static int
sendpiece(Msgchan * c,int ty,ulong a)58*06d2afa6SDavid du Colombier sendpiece(Msgchan *c, int ty, ulong a)
59*06d2afa6SDavid du Colombier {
60*06d2afa6SDavid du Colombier Ureg u;
61*06d2afa6SDavid du Colombier
62*06d2afa6SDavid du Colombier memset(&u, 0, sizeof u);
63*06d2afa6SDavid du Colombier u.cx = (ty<<16) | BackMessage;
64*06d2afa6SDavid du Colombier u.dx = c->id<<16;
65*06d2afa6SDavid du Colombier u.bx = a;
66*06d2afa6SDavid du Colombier
67*06d2afa6SDavid du Colombier backdoor(&u, 0);
68*06d2afa6SDavid du Colombier
69*06d2afa6SDavid du Colombier if(!(u.cx & (StatSuccess<<16))){
70*06d2afa6SDavid du Colombier fprint(2, "cmd %x failed\n", ty);
71*06d2afa6SDavid du Colombier if(u.cx & (StatChkpt<<16))
72*06d2afa6SDavid du Colombier return ErrChkpt;
73*06d2afa6SDavid du Colombier return ErrBad;
74*06d2afa6SDavid du Colombier }
75*06d2afa6SDavid du Colombier return 0;
76*06d2afa6SDavid du Colombier }
77*06d2afa6SDavid du Colombier
78*06d2afa6SDavid du Colombier int
sendmsg(Msgchan * c,void * a,int n)79*06d2afa6SDavid du Colombier sendmsg(Msgchan *c, void *a, int n)
80*06d2afa6SDavid du Colombier {
81*06d2afa6SDavid du Colombier int i, m, e, left;
82*06d2afa6SDavid du Colombier uchar *p;
83*06d2afa6SDavid du Colombier ulong v;
84*06d2afa6SDavid du Colombier
85*06d2afa6SDavid du Colombier Again:
86*06d2afa6SDavid du Colombier v = n;
87*06d2afa6SDavid du Colombier if(sendpiece(c, CmdSendsize, v) < 0)
88*06d2afa6SDavid du Colombier return -1;
89*06d2afa6SDavid du Colombier
90*06d2afa6SDavid du Colombier p = a;
91*06d2afa6SDavid du Colombier left = n;
92*06d2afa6SDavid du Colombier while(left > 0){
93*06d2afa6SDavid du Colombier m = left;
94*06d2afa6SDavid du Colombier if(m > 4)
95*06d2afa6SDavid du Colombier m = 4;
96*06d2afa6SDavid du Colombier v = 0;
97*06d2afa6SDavid du Colombier for(i=0; i<m; i++)
98*06d2afa6SDavid du Colombier v |= *p++ << (8*i);
99*06d2afa6SDavid du Colombier if((e=sendpiece(c, CmdSenddata, v)) < 0){
100*06d2afa6SDavid du Colombier if(e == -2)
101*06d2afa6SDavid du Colombier goto Again;
102*06d2afa6SDavid du Colombier return -1;
103*06d2afa6SDavid du Colombier }
104*06d2afa6SDavid du Colombier left -= m;
105*06d2afa6SDavid du Colombier }
106*06d2afa6SDavid du Colombier return 0;
107*06d2afa6SDavid du Colombier }
108*06d2afa6SDavid du Colombier
109*06d2afa6SDavid du Colombier static int
recvpiece(Msgchan * c,int ty,ulong * stat,ulong * a)110*06d2afa6SDavid du Colombier recvpiece(Msgchan *c, int ty, ulong *stat, ulong *a)
111*06d2afa6SDavid du Colombier {
112*06d2afa6SDavid du Colombier Ureg u;
113*06d2afa6SDavid du Colombier
114*06d2afa6SDavid du Colombier fprint(2, "recvpiece %d %d\n", c->id, ty);
115*06d2afa6SDavid du Colombier memset(&u, 0, sizeof u);
116*06d2afa6SDavid du Colombier u.cx = (ty<<16) | BackMessage;
117*06d2afa6SDavid du Colombier u.bx = StatSuccess;
118*06d2afa6SDavid du Colombier u.dx = c->id<<16;
119*06d2afa6SDavid du Colombier
120*06d2afa6SDavid du Colombier backdoor(&u, 0);
121*06d2afa6SDavid du Colombier
122*06d2afa6SDavid du Colombier if(!(u.cx & (StatSuccess<<16))){
123*06d2afa6SDavid du Colombier fprint(2, "no success %lux\n", u.cx);
124*06d2afa6SDavid du Colombier if(u.cx & (StatChkpt<<16))
125*06d2afa6SDavid du Colombier return ErrChkpt;
126*06d2afa6SDavid du Colombier return ErrBad;
127*06d2afa6SDavid du Colombier }
128*06d2afa6SDavid du Colombier *stat = u.cx;
129*06d2afa6SDavid du Colombier if(ty == CmdRecvsize && !(u.cx&(StatHavedata<<16))){
130*06d2afa6SDavid du Colombier fprint(2, "poll got no data\n");
131*06d2afa6SDavid du Colombier return 0;
132*06d2afa6SDavid du Colombier }
133*06d2afa6SDavid du Colombier
134*06d2afa6SDavid du Colombier if(ty != CmdRecvstatus && (u.dx>>16) != ty-2){
135*06d2afa6SDavid du Colombier fprint(2, "got wrong answer! %lux\n", u.dx);
136*06d2afa6SDavid du Colombier werrstr("protocol error");
137*06d2afa6SDavid du Colombier return ErrBad;
138*06d2afa6SDavid du Colombier }
139*06d2afa6SDavid du Colombier *a = u.bx;
140*06d2afa6SDavid du Colombier fprint(2, "got %lux\n", *a);
141*06d2afa6SDavid du Colombier return 0;
142*06d2afa6SDavid du Colombier }
143*06d2afa6SDavid du Colombier
144*06d2afa6SDavid du Colombier static void
signalerror(Msgchan * c,int ty)145*06d2afa6SDavid du Colombier signalerror(Msgchan *c, int ty)
146*06d2afa6SDavid du Colombier {
147*06d2afa6SDavid du Colombier Ureg u;
148*06d2afa6SDavid du Colombier
149*06d2afa6SDavid du Colombier memset(&u, 0, sizeof u);
150*06d2afa6SDavid du Colombier u.cx = (ty<<16) | BackMessage;
151*06d2afa6SDavid du Colombier u.dx = c->id<<16;
152*06d2afa6SDavid du Colombier u.bx = 0;
153*06d2afa6SDavid du Colombier backdoor(&u, 0);
154*06d2afa6SDavid du Colombier }
155*06d2afa6SDavid du Colombier
156*06d2afa6SDavid du Colombier int
recvmsg(Msgchan * c,void ** pp)157*06d2afa6SDavid du Colombier recvmsg(Msgchan *c, void **pp)
158*06d2afa6SDavid du Colombier {
159*06d2afa6SDavid du Colombier int left;
160*06d2afa6SDavid du Colombier ulong v, stat, tot;
161*06d2afa6SDavid du Colombier uchar *p;
162*06d2afa6SDavid du Colombier
163*06d2afa6SDavid du Colombier Top:
164*06d2afa6SDavid du Colombier if(recvpiece(c, CmdRecvsize, &stat, &tot) < 0)
165*06d2afa6SDavid du Colombier return -1;
166*06d2afa6SDavid du Colombier
167*06d2afa6SDavid du Colombier if(!(stat & (StatHavedata<<16)))
168*06d2afa6SDavid du Colombier return 0;
169*06d2afa6SDavid du Colombier
170*06d2afa6SDavid du Colombier free(c->a);
171*06d2afa6SDavid du Colombier c->a = emalloc9p(tot+5);
172*06d2afa6SDavid du Colombier c->na = tot;
173*06d2afa6SDavid du Colombier p = c->a; /* NUL terminate for callers */
174*06d2afa6SDavid du Colombier
175*06d2afa6SDavid du Colombier left = tot;
176*06d2afa6SDavid du Colombier while(left > 0){
177*06d2afa6SDavid du Colombier switch(recvpiece(c, CmdRecvdata, &stat, &v)){
178*06d2afa6SDavid du Colombier case ErrChkpt:
179*06d2afa6SDavid du Colombier goto Top;
180*06d2afa6SDavid du Colombier case ErrBad:
181*06d2afa6SDavid du Colombier signalerror(c, CmdRecvdata);
182*06d2afa6SDavid du Colombier return -1;
183*06d2afa6SDavid du Colombier }
184*06d2afa6SDavid du Colombier *(uint*)p = v;
185*06d2afa6SDavid du Colombier p += 4;
186*06d2afa6SDavid du Colombier left -= 4;
187*06d2afa6SDavid du Colombier }
188*06d2afa6SDavid du Colombier ((char*)c->a)[tot] = '\0';
189*06d2afa6SDavid du Colombier
190*06d2afa6SDavid du Colombier switch(recvpiece(c, CmdRecvstatus, &stat, &v)){
191*06d2afa6SDavid du Colombier case ErrChkpt:
192*06d2afa6SDavid du Colombier goto Top;
193*06d2afa6SDavid du Colombier case ErrBad:
194*06d2afa6SDavid du Colombier /* BUG: signal receipt of error */
195*06d2afa6SDavid du Colombier signalerror(c, CmdRecvstatus);
196*06d2afa6SDavid du Colombier return -1;
197*06d2afa6SDavid du Colombier }
198*06d2afa6SDavid du Colombier
199*06d2afa6SDavid du Colombier *pp = c->a;
200*06d2afa6SDavid du Colombier return tot;
201*06d2afa6SDavid du Colombier }
202*06d2afa6SDavid du Colombier
203*06d2afa6SDavid du Colombier int
closemsg(Msgchan * c)204*06d2afa6SDavid du Colombier closemsg(Msgchan *c)
205*06d2afa6SDavid du Colombier {
206*06d2afa6SDavid du Colombier Ureg u;
207*06d2afa6SDavid du Colombier
208*06d2afa6SDavid du Colombier memset(&u, 0, sizeof u);
209*06d2afa6SDavid du Colombier
210*06d2afa6SDavid du Colombier u.cx = (CmdClose<<16) | BackMessage;
211*06d2afa6SDavid du Colombier u.dx = c->id;
212*06d2afa6SDavid du Colombier
213*06d2afa6SDavid du Colombier backdoor(&u, 0);
214*06d2afa6SDavid du Colombier
215*06d2afa6SDavid du Colombier if(!(u.cx & (StatSuccess<<16))){
216*06d2afa6SDavid du Colombier werrstr("unable to close message channel");
217*06d2afa6SDavid du Colombier return -1;
218*06d2afa6SDavid du Colombier }
219*06d2afa6SDavid du Colombier
220*06d2afa6SDavid du Colombier free(c->a);
221*06d2afa6SDavid du Colombier c->a = nil;
222*06d2afa6SDavid du Colombier free(c);
223*06d2afa6SDavid du Colombier return 0;
224*06d2afa6SDavid du Colombier }
225