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