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