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