vmt_subr.c revision 1.1.2.1 1 /* $NetBSD: vmt_subr.c,v 1.1.2.1 2020/12/14 14:38:09 thorpej Exp $ */
2 /* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */
3
4 /*
5 * Copyright (c) 2007 David Crawshaw <david (at) zentus.com>
6 * Copyright (c) 2008 David Gwynne <dlg (at) openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 /*
22 * Protocol reverse engineered by Ken Kato:
23 * https://sites.google.com/site/chitchatvmback/backdoor
24 */
25
26 #include <sys/param.h>
27 #include <sys/types.h>
28 #include <sys/callout.h>
29 #include <sys/device.h>
30 #include <sys/endian.h>
31 #include <sys/kernel.h>
32 #include <sys/kmem.h>
33 #include <sys/module.h>
34 #include <sys/proc.h>
35 #include <sys/reboot.h>
36 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 #include <sys/syslog.h>
39 #include <sys/systm.h>
40 #include <sys/timetc.h>
41
42 #include <net/if.h>
43 #include <netinet/in.h>
44
45 #include <dev/sysmon/sysmonvar.h>
46 #include <dev/sysmon/sysmon_taskq.h>
47 #include <dev/vmt/vmtreg.h>
48 #include <dev/vmt/vmtvar.h>
49
50 /* #define VMT_DEBUG */
51
52 static int vmt_sysctl_setup_root(device_t);
53 static int vmt_sysctl_setup_clock_sync(device_t, const struct sysctlnode *);
54 static int vmt_sysctl_update_clock_sync_period(SYSCTLFN_PROTO);
55
56 static void vm_cmd(struct vm_backdoor *);
57 static void vm_ins(struct vm_backdoor *);
58 static void vm_outs(struct vm_backdoor *);
59
60 /* Functions for communicating with the VM Host. */
61 static int vm_rpc_open(struct vm_rpc *, uint32_t);
62 static int vm_rpc_close(struct vm_rpc *);
63 static int vm_rpc_send(const struct vm_rpc *, const uint8_t *, uint32_t);
64 static int vm_rpc_send_str(const struct vm_rpc *, const uint8_t *);
65 static int vm_rpc_get_length(const struct vm_rpc *, uint32_t *, uint16_t *);
66 static int vm_rpc_get_data(const struct vm_rpc *, char *, uint32_t, uint16_t);
67 static int vm_rpc_send_rpci_tx_buf(struct vmt_softc *, const uint8_t *, uint32_t);
68 static int vm_rpc_send_rpci_tx(struct vmt_softc *, const char *, ...)
69 __printflike(2, 3);
70 static int vm_rpci_response_successful(struct vmt_softc *);
71
72 static void vmt_tclo_state_change_success(struct vmt_softc *, int, char);
73 static void vmt_do_reboot(struct vmt_softc *);
74 static void vmt_do_shutdown(struct vmt_softc *);
75
76 static void vmt_update_guest_info(struct vmt_softc *);
77 static void vmt_update_guest_uptime(struct vmt_softc *);
78 static void vmt_sync_guest_clock(struct vmt_softc *);
79
80 static void vmt_tick(void *);
81 static void vmt_tclo_tick(void *);
82 static void vmt_clock_sync_tick(void *);
83 static bool vmt_shutdown(device_t, int);
84 static void vmt_pswitch_event(void *);
85
86 extern char hostname[MAXHOSTNAMELEN];
87
88 static void
89 vmt_probe_cmd(struct vm_backdoor *frame, uint16_t cmd)
90 {
91 memset(frame, 0, sizeof(*frame));
92
93 (frame->eax).word = VM_MAGIC;
94 (frame->ebx).word = ~VM_MAGIC;
95 (frame->ecx).part.low = cmd;
96 (frame->ecx).part.high = 0xffff;
97 (frame->edx).part.low = VM_PORT_CMD;
98 (frame->edx).part.high = 0;
99
100 vm_cmd(frame);
101 }
102
103 bool
104 vmt_probe(void)
105 {
106 #if BYTE_ORDER == BIG_ENDIAN
107 /*
108 * XXX: doesn't support in big-endian.
109 * vmt has some code depends on little-endian.
110 */
111 return false;
112 #else
113 struct vm_backdoor frame;
114
115 vmt_probe_cmd(&frame, VM_CMD_GET_VERSION);
116 if (frame.eax.word == 0xffffffff ||
117 frame.ebx.word != VM_MAGIC)
118 return false;
119
120 vmt_probe_cmd(&frame, VM_CMD_GET_SPEED);
121 if (frame.eax.word == VM_MAGIC)
122 return false;
123
124 return true;
125 #endif
126 }
127
128 void
129 vmt_common_attach(struct vmt_softc *sc)
130 {
131 device_t self;
132 struct vm_backdoor frame;
133 int rv;
134
135 self = sc->sc_dev;
136 sc->sc_log = NULL;
137
138 /* check again */
139 vmt_probe_cmd(&frame, VM_CMD_GET_VERSION);
140 if (frame.eax.word == 0xffffffff ||
141 frame.ebx.word != VM_MAGIC) {
142 aprint_error_dev(self, "failed to get VMware version\n");
143 return;
144 }
145
146 /* show uuid */
147 {
148 struct uuid uuid;
149 uint32_t u;
150
151 vmt_probe_cmd(&frame, VM_CMD_GET_BIOS_UUID);
152 uuid.time_low = htobe32(frame.eax.word);
153 u = htobe32(frame.ebx.word);
154 uuid.time_mid = u >> 16;
155 uuid.time_hi_and_version = u;
156 u = htobe32(frame.ecx.word);
157 uuid.clock_seq_hi_and_reserved = u >> 24;
158 uuid.clock_seq_low = u >> 16;
159 uuid.node[0] = u >> 8;
160 uuid.node[1] = u;
161 u = htobe32(frame.edx.word);
162 uuid.node[2] = u >> 24;
163 uuid.node[3] = u >> 16;
164 uuid.node[4] = u >> 8;
165 uuid.node[5] = u;
166
167 uuid_snprintf(sc->sc_uuid, sizeof(sc->sc_uuid), &uuid);
168 aprint_verbose_dev(sc->sc_dev, "UUID: %s\n", sc->sc_uuid);
169 }
170
171 callout_init(&sc->sc_tick, 0);
172 callout_init(&sc->sc_tclo_tick, 0);
173 callout_init(&sc->sc_clock_sync_tick, 0);
174
175 sc->sc_clock_sync_period_seconds = VMT_CLOCK_SYNC_PERIOD_SECONDS;
176
177 rv = vmt_sysctl_setup_root(self);
178 if (rv != 0) {
179 aprint_error_dev(self, "failed to initialize sysctl "
180 "(err %d)\n", rv);
181 goto free;
182 }
183
184 sc->sc_rpc_buf = kmem_alloc(VMT_RPC_BUFLEN, KM_SLEEP);
185
186 if (vm_rpc_open(&sc->sc_tclo_rpc, VM_RPC_OPEN_TCLO) != 0) {
187 aprint_error_dev(self, "failed to open backdoor RPC channel (TCLO protocol)\n");
188 goto free;
189 }
190 sc->sc_tclo_rpc_open = true;
191
192 /* don't know if this is important at all yet */
193 if (vm_rpc_send_rpci_tx(sc, "tools.capability.hgfs_server toolbox 1") != 0) {
194 aprint_error_dev(self, "failed to set HGFS server capability\n");
195 goto free;
196 }
197
198 pmf_device_register1(self, NULL, NULL, vmt_shutdown);
199
200 sysmon_task_queue_init();
201
202 sc->sc_ev_power.ev_smpsw.smpsw_type = PSWITCH_TYPE_POWER;
203 sc->sc_ev_power.ev_smpsw.smpsw_name = device_xname(self);
204 sc->sc_ev_power.ev_code = PSWITCH_EVENT_PRESSED;
205 sysmon_pswitch_register(&sc->sc_ev_power.ev_smpsw);
206 sc->sc_ev_reset.ev_smpsw.smpsw_type = PSWITCH_TYPE_RESET;
207 sc->sc_ev_reset.ev_smpsw.smpsw_name = device_xname(self);
208 sc->sc_ev_reset.ev_code = PSWITCH_EVENT_PRESSED;
209 sysmon_pswitch_register(&sc->sc_ev_reset.ev_smpsw);
210 sc->sc_ev_sleep.ev_smpsw.smpsw_type = PSWITCH_TYPE_SLEEP;
211 sc->sc_ev_sleep.ev_smpsw.smpsw_name = device_xname(self);
212 sc->sc_ev_sleep.ev_code = PSWITCH_EVENT_RELEASED;
213 sysmon_pswitch_register(&sc->sc_ev_sleep.ev_smpsw);
214 sc->sc_smpsw_valid = true;
215
216 callout_setfunc(&sc->sc_tick, vmt_tick, sc);
217 callout_schedule(&sc->sc_tick, hz);
218
219 callout_setfunc(&sc->sc_tclo_tick, vmt_tclo_tick, sc);
220 callout_schedule(&sc->sc_tclo_tick, hz);
221 sc->sc_tclo_ping = 1;
222
223 callout_setfunc(&sc->sc_clock_sync_tick, vmt_clock_sync_tick, sc);
224 callout_schedule(&sc->sc_clock_sync_tick,
225 mstohz(sc->sc_clock_sync_period_seconds * 1000));
226
227 vmt_sync_guest_clock(sc);
228
229 return;
230
231 free:
232 if (sc->sc_rpc_buf)
233 kmem_free(sc->sc_rpc_buf, VMT_RPC_BUFLEN);
234 pmf_device_register(self, NULL, NULL);
235 if (sc->sc_log)
236 sysctl_teardown(&sc->sc_log);
237 }
238
239 int
240 vmt_common_detach(struct vmt_softc *sc)
241 {
242 if (sc->sc_tclo_rpc_open)
243 vm_rpc_close(&sc->sc_tclo_rpc);
244
245 if (sc->sc_smpsw_valid) {
246 sysmon_pswitch_unregister(&sc->sc_ev_sleep.ev_smpsw);
247 sysmon_pswitch_unregister(&sc->sc_ev_reset.ev_smpsw);
248 sysmon_pswitch_unregister(&sc->sc_ev_power.ev_smpsw);
249 }
250
251 callout_halt(&sc->sc_tick, NULL);
252 callout_destroy(&sc->sc_tick);
253
254 callout_halt(&sc->sc_tclo_tick, NULL);
255 callout_destroy(&sc->sc_tclo_tick);
256
257 callout_halt(&sc->sc_clock_sync_tick, NULL);
258 callout_destroy(&sc->sc_clock_sync_tick);
259
260 if (sc->sc_rpc_buf)
261 kmem_free(sc->sc_rpc_buf, VMT_RPC_BUFLEN);
262
263 if (sc->sc_log) {
264 sysctl_teardown(&sc->sc_log);
265 sc->sc_log = NULL;
266 }
267
268 return 0;
269 }
270
271 static int
272 vmt_sysctl_setup_root(device_t self)
273 {
274 const struct sysctlnode *machdep_node, *vmt_node;
275 struct vmt_softc *sc = device_private(self);
276 int rv;
277
278 rv = sysctl_createv(&sc->sc_log, 0, NULL, &machdep_node,
279 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
280 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
281 if (rv != 0)
282 goto fail;
283
284 rv = sysctl_createv(&sc->sc_log, 0, &machdep_node, &vmt_node,
285 0, CTLTYPE_NODE, device_xname(self), NULL,
286 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
287 if (rv != 0)
288 goto fail;
289
290 rv = sysctl_createv(&sc->sc_log, 0, &vmt_node, NULL,
291 CTLFLAG_READONLY, CTLTYPE_STRING, "uuid",
292 SYSCTL_DESCR("UUID of virtual machine"),
293 NULL, 0, sc->sc_uuid, 0,
294 CTL_CREATE, CTL_EOL);
295
296 rv = vmt_sysctl_setup_clock_sync(self, vmt_node);
297 if (rv != 0)
298 goto fail;
299
300 return 0;
301
302 fail:
303 sysctl_teardown(&sc->sc_log);
304 sc->sc_log = NULL;
305
306 return rv;
307 }
308
309 static int
310 vmt_sysctl_setup_clock_sync(device_t self, const struct sysctlnode *root_node)
311 {
312 const struct sysctlnode *node, *period_node;
313 struct vmt_softc *sc = device_private(self);
314 int rv;
315
316 rv = sysctl_createv(&sc->sc_log, 0, &root_node, &node,
317 0, CTLTYPE_NODE, "clock_sync", NULL,
318 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
319 if (rv != 0)
320 return rv;
321
322 rv = sysctl_createv(&sc->sc_log, 0, &node, &period_node,
323 CTLFLAG_READWRITE, CTLTYPE_INT, "period",
324 SYSCTL_DESCR("Period, in seconds, at which to update the "
325 "guest's clock"),
326 vmt_sysctl_update_clock_sync_period, 0, (void *)sc, 0,
327 CTL_CREATE, CTL_EOL);
328 return rv;
329 }
330
331 static int
332 vmt_sysctl_update_clock_sync_period(SYSCTLFN_ARGS)
333 {
334 int error, period;
335 struct sysctlnode node;
336 struct vmt_softc *sc;
337
338 node = *rnode;
339 sc = (struct vmt_softc *)node.sysctl_data;
340
341 period = sc->sc_clock_sync_period_seconds;
342 node.sysctl_data = .
343 error = sysctl_lookup(SYSCTLFN_CALL(&node));
344 if (error || newp == NULL)
345 return error;
346
347 if (sc->sc_clock_sync_period_seconds != period) {
348 callout_halt(&sc->sc_clock_sync_tick, NULL);
349 sc->sc_clock_sync_period_seconds = period;
350 if (sc->sc_clock_sync_period_seconds > 0)
351 callout_schedule(&sc->sc_clock_sync_tick,
352 mstohz(sc->sc_clock_sync_period_seconds * 1000));
353 }
354 return 0;
355 }
356
357 static void
358 vmt_clock_sync_tick(void *xarg)
359 {
360 struct vmt_softc *sc = xarg;
361
362 vmt_sync_guest_clock(sc);
363
364 callout_schedule(&sc->sc_clock_sync_tick,
365 mstohz(sc->sc_clock_sync_period_seconds * 1000));
366 }
367
368 static void
369 vmt_update_guest_uptime(struct vmt_softc *sc)
370 {
371 /* host wants uptime in hundredths of a second */
372 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %" PRId64 "00",
373 VM_GUEST_INFO_UPTIME, time_uptime) != 0) {
374 device_printf(sc->sc_dev, "unable to set guest uptime\n");
375 sc->sc_rpc_error = 1;
376 }
377 }
378
379 static void
380 vmt_update_guest_info(struct vmt_softc *sc)
381 {
382 if (strncmp(sc->sc_hostname, hostname, sizeof(sc->sc_hostname)) != 0) {
383 strlcpy(sc->sc_hostname, hostname, sizeof(sc->sc_hostname));
384 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %s",
385 VM_GUEST_INFO_DNS_NAME, sc->sc_hostname) != 0) {
386 device_printf(sc->sc_dev, "unable to set hostname\n");
387 sc->sc_rpc_error = 1;
388 }
389 }
390
391 /*
392 * we're supposed to pass the full network address information back here,
393 * but that involves xdr (sunrpc) data encoding, which seems a bit unreasonable.
394 */
395
396 if (sc->sc_set_guest_os == 0) {
397 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %s %s %s",
398 VM_GUEST_INFO_OS_NAME_FULL, ostype, osrelease, machine_arch) != 0) {
399 device_printf(sc->sc_dev, "unable to set full guest OS\n");
400 sc->sc_rpc_error = 1;
401 }
402
403 /*
404 * host doesn't like it if we send an OS name it doesn't recognise,
405 * so use "other" for i386 and "other-64" for amd64
406 */
407 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %s",
408 VM_GUEST_INFO_OS_NAME, VM_OS_NAME) != 0) {
409 device_printf(sc->sc_dev, "unable to set guest OS\n");
410 sc->sc_rpc_error = 1;
411 }
412
413 sc->sc_set_guest_os = 1;
414 }
415 }
416
417 static void
418 vmt_sync_guest_clock(struct vmt_softc *sc)
419 {
420 struct vm_backdoor frame;
421 struct timespec ts;
422
423 memset(&frame, 0, sizeof(frame));
424 frame.eax.word = VM_MAGIC;
425 frame.ecx.part.low = VM_CMD_GET_TIME_FULL;
426 frame.edx.part.low = VM_PORT_CMD;
427 vm_cmd(&frame);
428
429 if (frame.eax.word != 0xffffffff) {
430 ts.tv_sec = ((uint64_t)frame.esi.word << 32) | frame.edx.word;
431 ts.tv_nsec = frame.ebx.word * 1000;
432 tc_setclock(&ts);
433 }
434 }
435
436 static void
437 vmt_tick(void *xarg)
438 {
439 struct vmt_softc *sc = xarg;
440
441 vmt_update_guest_info(sc);
442 vmt_update_guest_uptime(sc);
443
444 callout_schedule(&sc->sc_tick, hz * 15);
445 }
446
447 static void
448 vmt_tclo_state_change_success(struct vmt_softc *sc, int success, char state)
449 {
450 if (vm_rpc_send_rpci_tx(sc, "tools.os.statechange.status %d %d",
451 success, state) != 0) {
452 device_printf(sc->sc_dev, "unable to send state change result\n");
453 sc->sc_rpc_error = 1;
454 }
455 }
456
457 static void
458 vmt_do_shutdown(struct vmt_softc *sc)
459 {
460 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_HALT);
461 vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK);
462
463 device_printf(sc->sc_dev, "host requested shutdown\n");
464 sysmon_task_queue_sched(0, vmt_pswitch_event, &sc->sc_ev_power);
465 }
466
467 static void
468 vmt_do_reboot(struct vmt_softc *sc)
469 {
470 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_REBOOT);
471 vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK);
472
473 device_printf(sc->sc_dev, "host requested reboot\n");
474 sysmon_task_queue_sched(0, vmt_pswitch_event, &sc->sc_ev_reset);
475 }
476
477 static void
478 vmt_do_resume(struct vmt_softc *sc)
479 {
480 device_printf(sc->sc_dev, "guest resuming from suspended state\n");
481
482 vmt_sync_guest_clock(sc);
483
484 /* force guest info update */
485 sc->sc_hostname[0] = '\0';
486 sc->sc_set_guest_os = 0;
487 vmt_update_guest_info(sc);
488
489 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_RESUME);
490 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
491 device_printf(sc->sc_dev, "error sending resume response\n");
492 sc->sc_rpc_error = 1;
493 }
494
495 sysmon_task_queue_sched(0, vmt_pswitch_event, &sc->sc_ev_sleep);
496 }
497
498 static bool
499 vmt_shutdown(device_t self, int flags)
500 {
501 struct vmt_softc *sc = device_private(self);
502
503 if (vm_rpc_send_rpci_tx(sc, "tools.capability.hgfs_server toolbox 0") != 0) {
504 device_printf(sc->sc_dev, "failed to disable hgfs server capability\n");
505 }
506
507 if (vm_rpc_send(&sc->sc_tclo_rpc, NULL, 0) != 0) {
508 device_printf(sc->sc_dev, "failed to send shutdown ping\n");
509 }
510
511 vm_rpc_close(&sc->sc_tclo_rpc);
512
513 return true;
514 }
515
516 static void
517 vmt_pswitch_event(void *xarg)
518 {
519 struct vmt_event *ev = xarg;
520
521 sysmon_pswitch_event(&ev->ev_smpsw, ev->ev_code);
522 }
523
524 static void
525 vmt_tclo_tick(void *xarg)
526 {
527 struct vmt_softc *sc = xarg;
528 u_int32_t rlen;
529 u_int16_t ack;
530
531 /* reopen tclo channel if it's currently closed */
532 if (sc->sc_tclo_rpc.channel == 0 &&
533 sc->sc_tclo_rpc.cookie1 == 0 &&
534 sc->sc_tclo_rpc.cookie2 == 0) {
535 if (vm_rpc_open(&sc->sc_tclo_rpc, VM_RPC_OPEN_TCLO) != 0) {
536 device_printf(sc->sc_dev, "unable to reopen TCLO channel\n");
537 callout_schedule(&sc->sc_tclo_tick, hz * 15);
538 return;
539 }
540
541 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_RESET_REPLY) != 0) {
542 device_printf(sc->sc_dev, "failed to send reset reply\n");
543 sc->sc_rpc_error = 1;
544 goto out;
545 } else {
546 sc->sc_rpc_error = 0;
547 }
548 }
549
550 if (sc->sc_tclo_ping) {
551 if (vm_rpc_send(&sc->sc_tclo_rpc, NULL, 0) != 0) {
552 device_printf(sc->sc_dev, "failed to send TCLO outgoing ping\n");
553 sc->sc_rpc_error = 1;
554 goto out;
555 }
556 }
557
558 if (vm_rpc_get_length(&sc->sc_tclo_rpc, &rlen, &ack) != 0) {
559 device_printf(sc->sc_dev, "failed to get length of incoming TCLO data\n");
560 sc->sc_rpc_error = 1;
561 goto out;
562 }
563
564 if (rlen == 0) {
565 sc->sc_tclo_ping = 1;
566 goto out;
567 }
568
569 if (rlen >= VMT_RPC_BUFLEN) {
570 rlen = VMT_RPC_BUFLEN - 1;
571 }
572 if (vm_rpc_get_data(&sc->sc_tclo_rpc, sc->sc_rpc_buf, rlen, ack) != 0) {
573 device_printf(sc->sc_dev, "failed to get incoming TCLO data\n");
574 sc->sc_rpc_error = 1;
575 goto out;
576 }
577 sc->sc_tclo_ping = 0;
578
579 #ifdef VMT_DEBUG
580 printf("vmware: received message '%s'\n", sc->sc_rpc_buf);
581 #endif
582
583 if (strcmp(sc->sc_rpc_buf, "reset") == 0) {
584
585 if (sc->sc_rpc_error != 0) {
586 device_printf(sc->sc_dev, "resetting rpc\n");
587 vm_rpc_close(&sc->sc_tclo_rpc);
588 /* reopen and send the reset reply next time around */
589 goto out;
590 }
591
592 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_RESET_REPLY) != 0) {
593 device_printf(sc->sc_dev, "failed to send reset reply\n");
594 sc->sc_rpc_error = 1;
595 }
596
597 } else if (strcmp(sc->sc_rpc_buf, "ping") == 0) {
598
599 vmt_update_guest_info(sc);
600 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
601 device_printf(sc->sc_dev, "error sending ping response\n");
602 sc->sc_rpc_error = 1;
603 }
604
605 } else if (strcmp(sc->sc_rpc_buf, "OS_Halt") == 0) {
606 vmt_do_shutdown(sc);
607 } else if (strcmp(sc->sc_rpc_buf, "OS_Reboot") == 0) {
608 vmt_do_reboot(sc);
609 } else if (strcmp(sc->sc_rpc_buf, "OS_PowerOn") == 0) {
610 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_POWERON);
611 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
612 device_printf(sc->sc_dev, "error sending poweron response\n");
613 sc->sc_rpc_error = 1;
614 }
615 } else if (strcmp(sc->sc_rpc_buf, "OS_Suspend") == 0) {
616 log(LOG_KERN | LOG_NOTICE, "VMware guest entering suspended state\n");
617
618 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_SUSPEND);
619 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
620 device_printf(sc->sc_dev, "error sending suspend response\n");
621 sc->sc_rpc_error = 1;
622 }
623 } else if (strcmp(sc->sc_rpc_buf, "OS_Resume") == 0) {
624 vmt_do_resume(sc);
625 } else if (strcmp(sc->sc_rpc_buf, "Capabilities_Register") == 0) {
626
627 /* don't know if this is important at all */
628 if (vm_rpc_send_rpci_tx(sc, "vmx.capability.unified_loop toolbox") != 0) {
629 device_printf(sc->sc_dev, "unable to set unified loop\n");
630 sc->sc_rpc_error = 1;
631 }
632 if (vm_rpci_response_successful(sc) == 0) {
633 device_printf(sc->sc_dev, "host rejected unified loop setting\n");
634 }
635
636 /* the trailing space is apparently important here */
637 if (vm_rpc_send_rpci_tx(sc, "tools.capability.statechange ") != 0) {
638 device_printf(sc->sc_dev, "unable to send statechange capability\n");
639 sc->sc_rpc_error = 1;
640 }
641 if (vm_rpci_response_successful(sc) == 0) {
642 device_printf(sc->sc_dev, "host rejected statechange capability\n");
643 }
644
645 if (vm_rpc_send_rpci_tx(sc, "tools.set.version %u", VM_VERSION_UNMANAGED) != 0) {
646 device_printf(sc->sc_dev, "unable to set tools version\n");
647 sc->sc_rpc_error = 1;
648 }
649
650 vmt_update_guest_uptime(sc);
651
652 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
653 device_printf(sc->sc_dev, "error sending capabilities_register response\n");
654 sc->sc_rpc_error = 1;
655 }
656 } else if (strcmp(sc->sc_rpc_buf, "Set_Option broadcastIP 1") == 0) {
657 struct ifaddr *iface_addr = NULL;
658 struct ifnet *iface;
659 struct sockaddr_in *guest_ip;
660 int s;
661 struct psref psref;
662
663 /* find first available ipv4 address */
664 guest_ip = NULL;
665 s = pserialize_read_enter();
666 IFNET_READER_FOREACH(iface) {
667
668 /* skip loopback */
669 if (strncmp(iface->if_xname, "lo", 2) == 0 &&
670 iface->if_xname[2] >= '0' && iface->if_xname[2] <= '9') {
671 continue;
672 }
673
674 IFADDR_READER_FOREACH(iface_addr, iface) {
675 if (iface_addr->ifa_addr->sa_family != AF_INET) {
676 continue;
677 }
678
679 guest_ip = satosin(iface_addr->ifa_addr);
680 ifa_acquire(iface_addr, &psref);
681 goto got;
682 }
683 }
684 got:
685 pserialize_read_exit(s);
686
687 if (guest_ip != NULL) {
688 if (vm_rpc_send_rpci_tx(sc, "info-set guestinfo.ip %s",
689 inet_ntoa(guest_ip->sin_addr)) != 0) {
690 device_printf(sc->sc_dev, "unable to send guest IP address\n");
691 sc->sc_rpc_error = 1;
692 }
693 ifa_release(iface_addr, &psref);
694
695 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
696 device_printf(sc->sc_dev, "error sending broadcastIP response\n");
697 sc->sc_rpc_error = 1;
698 }
699 } else {
700 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_ERROR_IP_ADDR) != 0) {
701 device_printf(sc->sc_dev,
702 "error sending broadcastIP error response\n");
703 sc->sc_rpc_error = 1;
704 }
705 }
706 } else {
707 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_ERROR) != 0) {
708 device_printf(sc->sc_dev, "error sending unknown command reply\n");
709 sc->sc_rpc_error = 1;
710 }
711 }
712
713 out:
714 callout_schedule(&sc->sc_tclo_tick, sc->sc_tclo_ping ? hz : 1);
715 }
716
717 static void
718 vm_cmd(struct vm_backdoor *frame)
719 {
720 BACKDOOR_OP(BACKDOOR_OP_CMD, frame);
721 }
722
723 static void
724 vm_ins(struct vm_backdoor *frame)
725 {
726 BACKDOOR_OP(BACKDOOR_OP_IN, frame);
727 }
728
729 static void
730 vm_outs(struct vm_backdoor *frame)
731 {
732 BACKDOOR_OP(BACKDOOR_OP_OUT, frame);
733 }
734
735 static int
736 vm_rpc_open(struct vm_rpc *rpc, uint32_t proto)
737 {
738 struct vm_backdoor frame;
739
740 memset(&frame, 0, sizeof(frame));
741 frame.eax.word = VM_MAGIC;
742 frame.ebx.word = proto | VM_RPC_FLAG_COOKIE;
743 frame.ecx.part.low = VM_CMD_RPC;
744 frame.ecx.part.high = VM_RPC_OPEN;
745 frame.edx.part.low = VM_PORT_CMD;
746 frame.edx.part.high = 0;
747
748 vm_cmd(&frame);
749
750 if (frame.ecx.part.high != 1 || frame.edx.part.low != 0) {
751 /* open-vm-tools retries without VM_RPC_FLAG_COOKIE here.. */
752 printf("vmware: open failed, eax=%08x, ecx=%08x, edx=%08x\n",
753 frame.eax.word, frame.ecx.word, frame.edx.word);
754 return EIO;
755 }
756
757 rpc->channel = frame.edx.part.high;
758 rpc->cookie1 = frame.esi.word;
759 rpc->cookie2 = frame.edi.word;
760
761 return 0;
762 }
763
764 static int
765 vm_rpc_close(struct vm_rpc *rpc)
766 {
767 struct vm_backdoor frame;
768
769 memset(&frame, 0, sizeof(frame));
770 frame.eax.word = VM_MAGIC;
771 frame.ebx.word = 0;
772 frame.ecx.part.low = VM_CMD_RPC;
773 frame.ecx.part.high = VM_RPC_CLOSE;
774 frame.edx.part.low = VM_PORT_CMD;
775 frame.edx.part.high = rpc->channel;
776 frame.edi.word = rpc->cookie2;
777 frame.esi.word = rpc->cookie1;
778
779 vm_cmd(&frame);
780
781 if (frame.ecx.part.high == 0 || frame.ecx.part.low != 0) {
782 printf("vmware: close failed, eax=%08x, ecx=%08x\n",
783 frame.eax.word, frame.ecx.word);
784 return EIO;
785 }
786
787 rpc->channel = 0;
788 rpc->cookie1 = 0;
789 rpc->cookie2 = 0;
790
791 return 0;
792 }
793
794 static int
795 vm_rpc_send(const struct vm_rpc *rpc, const uint8_t *buf, uint32_t length)
796 {
797 struct vm_backdoor frame;
798
799 /* Send the length of the command. */
800 memset(&frame, 0, sizeof(frame));
801 frame.eax.word = VM_MAGIC;
802 frame.ebx.word = length;
803 frame.ecx.part.low = VM_CMD_RPC;
804 frame.ecx.part.high = VM_RPC_SET_LENGTH;
805 frame.edx.part.low = VM_PORT_CMD;
806 frame.edx.part.high = rpc->channel;
807 frame.esi.word = rpc->cookie1;
808 frame.edi.word = rpc->cookie2;
809
810 vm_cmd(&frame);
811
812 if ((frame.ecx.part.high & VM_RPC_REPLY_SUCCESS) == 0) {
813 printf("vmware: sending length failed, eax=%08x, ecx=%08x\n",
814 frame.eax.word, frame.ecx.word);
815 return EIO;
816 }
817
818 if (length == 0)
819 return 0; /* Only need to poke once if command is null. */
820
821 /* Send the command using enhanced RPC. */
822 memset(&frame, 0, sizeof(frame));
823 frame.eax.word = VM_MAGIC;
824 frame.ebx.word = VM_RPC_ENH_DATA;
825 frame.ecx.word = length;
826 frame.edx.part.low = VM_PORT_RPC;
827 frame.edx.part.high = rpc->channel;
828 frame.ebp.word = rpc->cookie1;
829 frame.edi.word = rpc->cookie2;
830 #if defined(__amd64__) || defined(__aarch64__)
831 frame.esi.quad = (uint64_t)buf;
832 #else
833 frame.esi.word = (uint32_t)buf;
834 #endif
835
836 vm_outs(&frame);
837
838 if (frame.ebx.word != VM_RPC_ENH_DATA) {
839 /* open-vm-tools retries on VM_RPC_REPLY_CHECKPOINT */
840 printf("vmware: send failed, ebx=%08x\n", frame.ebx.word);
841 return EIO;
842 }
843
844 return 0;
845 }
846
847 static int
848 vm_rpc_send_str(const struct vm_rpc *rpc, const uint8_t *str)
849 {
850 return vm_rpc_send(rpc, str, strlen(str));
851 }
852
853 static int
854 vm_rpc_get_data(const struct vm_rpc *rpc, char *data, uint32_t length,
855 uint16_t dataid)
856 {
857 struct vm_backdoor frame;
858
859 /* Get data using enhanced RPC. */
860 memset(&frame, 0, sizeof(frame));
861 frame.eax.word = VM_MAGIC;
862 frame.ebx.word = VM_RPC_ENH_DATA;
863 frame.ecx.word = length;
864 frame.edx.part.low = VM_PORT_RPC;
865 frame.edx.part.high = rpc->channel;
866 frame.esi.word = rpc->cookie1;
867 #if defined(__amd64__) || defined(__aarch64__)
868 frame.edi.quad = (uint64_t)data;
869 #else
870 frame.edi.word = (uint32_t)data;
871 #endif
872 frame.ebp.word = rpc->cookie2;
873
874 vm_ins(&frame);
875
876 /* NUL-terminate the data */
877 data[length] = '\0';
878
879 if (frame.ebx.word != VM_RPC_ENH_DATA) {
880 printf("vmware: get data failed, ebx=%08x\n",
881 frame.ebx.word);
882 return EIO;
883 }
884
885 /* Acknowledge data received. */
886 memset(&frame, 0, sizeof(frame));
887 frame.eax.word = VM_MAGIC;
888 frame.ebx.word = dataid;
889 frame.ecx.part.low = VM_CMD_RPC;
890 frame.ecx.part.high = VM_RPC_GET_END;
891 frame.edx.part.low = VM_PORT_CMD;
892 frame.edx.part.high = rpc->channel;
893 frame.esi.word = rpc->cookie1;
894 frame.edi.word = rpc->cookie2;
895
896 vm_cmd(&frame);
897
898 if (frame.ecx.part.high == 0) {
899 printf("vmware: ack data failed, eax=%08x, ecx=%08x\n",
900 frame.eax.word, frame.ecx.word);
901 return EIO;
902 }
903
904 return 0;
905 }
906
907 static int
908 vm_rpc_get_length(const struct vm_rpc *rpc, uint32_t *length, uint16_t *dataid)
909 {
910 struct vm_backdoor frame;
911
912 memset(&frame, 0, sizeof(frame));
913 frame.eax.word = VM_MAGIC;
914 frame.ebx.word = 0;
915 frame.ecx.part.low = VM_CMD_RPC;
916 frame.ecx.part.high = VM_RPC_GET_LENGTH;
917 frame.edx.part.low = VM_PORT_CMD;
918 frame.edx.part.high = rpc->channel;
919 frame.esi.word = rpc->cookie1;
920 frame.edi.word = rpc->cookie2;
921
922 vm_cmd(&frame);
923
924 if ((frame.ecx.part.high & VM_RPC_REPLY_SUCCESS) == 0) {
925 printf("vmware: get length failed, eax=%08x, ecx=%08x\n",
926 frame.eax.word, frame.ecx.word);
927 return EIO;
928 }
929 if ((frame.ecx.part.high & VM_RPC_REPLY_DORECV) == 0) {
930 *length = 0;
931 *dataid = 0;
932 } else {
933 *length = frame.ebx.word;
934 *dataid = frame.edx.part.high;
935 }
936
937 return 0;
938 }
939
940 static int
941 vm_rpci_response_successful(struct vmt_softc *sc)
942 {
943 return (sc->sc_rpc_buf[0] == '1' && sc->sc_rpc_buf[1] == ' ');
944 }
945
946 static int
947 vm_rpc_send_rpci_tx_buf(struct vmt_softc *sc, const uint8_t *buf, uint32_t length)
948 {
949 struct vm_rpc rpci;
950 u_int32_t rlen;
951 u_int16_t ack;
952 int result = 0;
953
954 if (vm_rpc_open(&rpci, VM_RPC_OPEN_RPCI) != 0) {
955 device_printf(sc->sc_dev, "rpci channel open failed\n");
956 return EIO;
957 }
958
959 if (vm_rpc_send(&rpci, sc->sc_rpc_buf, length) != 0) {
960 device_printf(sc->sc_dev, "unable to send rpci command\n");
961 result = EIO;
962 goto out;
963 }
964
965 if (vm_rpc_get_length(&rpci, &rlen, &ack) != 0) {
966 device_printf(sc->sc_dev, "failed to get length of rpci response data\n");
967 result = EIO;
968 goto out;
969 }
970
971 if (rlen > 0) {
972 if (rlen >= VMT_RPC_BUFLEN) {
973 rlen = VMT_RPC_BUFLEN - 1;
974 }
975
976 if (vm_rpc_get_data(&rpci, sc->sc_rpc_buf, rlen, ack) != 0) {
977 device_printf(sc->sc_dev, "failed to get rpci response data\n");
978 result = EIO;
979 goto out;
980 }
981 }
982
983 out:
984 if (vm_rpc_close(&rpci) != 0) {
985 device_printf(sc->sc_dev, "unable to close rpci channel\n");
986 }
987
988 return result;
989 }
990
991 static int
992 vm_rpc_send_rpci_tx(struct vmt_softc *sc, const char *fmt, ...)
993 {
994 va_list args;
995 int len;
996
997 va_start(args, fmt);
998 len = vsnprintf(sc->sc_rpc_buf, VMT_RPC_BUFLEN, fmt, args);
999 va_end(args);
1000
1001 if (len >= VMT_RPC_BUFLEN) {
1002 device_printf(sc->sc_dev, "rpci command didn't fit in buffer\n");
1003 return EIO;
1004 }
1005
1006 return vm_rpc_send_rpci_tx_buf(sc, sc->sc_rpc_buf, len);
1007 }
1008
1009 #if 0
1010 struct vm_backdoor frame;
1011
1012 memset(&frame, 0, sizeof(frame));
1013
1014 frame.eax.word = VM_MAGIC;
1015 frame.ecx.part.low = VM_CMD_GET_VERSION;
1016 frame.edx.part.low = VM_PORT_CMD;
1017
1018 printf("\n");
1019 printf("eax 0x%08x\n", frame.eax.word);
1020 printf("ebx 0x%08x\n", frame.ebx.word);
1021 printf("ecx 0x%08x\n", frame.ecx.word);
1022 printf("edx 0x%08x\n", frame.edx.word);
1023 printf("ebp 0x%08x\n", frame.ebp.word);
1024 printf("edi 0x%08x\n", frame.edi.word);
1025 printf("esi 0x%08x\n", frame.esi.word);
1026
1027 vm_cmd(&frame);
1028
1029 printf("-\n");
1030 printf("eax 0x%08x\n", frame.eax.word);
1031 printf("ebx 0x%08x\n", frame.ebx.word);
1032 printf("ecx 0x%08x\n", frame.ecx.word);
1033 printf("edx 0x%08x\n", frame.edx.word);
1034 printf("ebp 0x%08x\n", frame.ebp.word);
1035 printf("edi 0x%08x\n", frame.edi.word);
1036 printf("esi 0x%08x\n", frame.esi.word);
1037 #endif
1038
1039 /*
1040 * Notes on tracing backdoor activity in vmware-guestd:
1041 *
1042 * - Find the addresses of the inl / rep insb / rep outsb
1043 * instructions used to perform backdoor operations.
1044 * One way to do this is to disassemble vmware-guestd:
1045 *
1046 * $ objdump -S /emul/freebsd/sbin/vmware-guestd > vmware-guestd.S
1047 *
1048 * and search for '<tab>in ' in the resulting file. The rep insb and
1049 * rep outsb code is directly below that.
1050 *
1051 * - Run vmware-guestd under gdb, setting up breakpoints as follows:
1052 * (the addresses shown here are the ones from VMware-server-1.0.10-203137,
1053 * the last version that actually works in FreeBSD emulation on OpenBSD)
1054 *
1055 * break *0x805497b (address of 'in' instruction)
1056 * commands 1
1057 * silent
1058 * echo INOUT\n
1059 * print/x $ecx
1060 * print/x $ebx
1061 * print/x $edx
1062 * continue
1063 * end
1064 * break *0x805497c (address of instruction after 'in')
1065 * commands 2
1066 * silent
1067 * echo ===\n
1068 * print/x $ecx
1069 * print/x $ebx
1070 * print/x $edx
1071 * echo \n
1072 * continue
1073 * end
1074 * break *0x80549b7 (address of instruction before 'rep insb')
1075 * commands 3
1076 * silent
1077 * set variable $inaddr = $edi
1078 * set variable $incount = $ecx
1079 * continue
1080 * end
1081 * break *0x80549ba (address of instruction after 'rep insb')
1082 * commands 4
1083 * silent
1084 * echo IN\n
1085 * print $incount
1086 * x/s $inaddr
1087 * echo \n
1088 * continue
1089 * end
1090 * break *0x80549fb (address of instruction before 'rep outsb')
1091 * commands 5
1092 * silent
1093 * echo OUT\n
1094 * print $ecx
1095 * x/s $esi
1096 * echo \n
1097 * continue
1098 * end
1099 *
1100 * This will produce a log of the backdoor operations, including the
1101 * data sent and received and the relevant register values. You can then
1102 * match the register values to the various constants in this file.
1103 */
1104