Home | History | Annotate | Line # | Download | only in vmt
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 = &period;
    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