1 /* $OpenBSD: vmt.c,v 1.19 2020/06/24 22:03:40 cheloha Exp $ */ 2 3 /* 4 * Copyright (c) 2007 David Crawshaw <david@zentus.com> 5 * Copyright (c) 2008 David Gwynne <dlg@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #if !defined(__i386__) && !defined(__amd64__) 21 #error vmt(4) is only supported on i386 and amd64 22 #endif 23 24 /* 25 * Protocol reverse engineered by Ken Kato: 26 * https://sites.google.com/site/chitchatvmback/backdoor 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/kernel.h> 32 #include <sys/malloc.h> 33 #include <sys/timeout.h> 34 #include <sys/signalvar.h> 35 #include <sys/syslog.h> 36 #include <sys/proc.h> 37 #include <sys/socket.h> 38 #include <sys/ioctl.h> 39 #include <sys/mount.h> 40 #include <sys/task.h> 41 #include <sys/sensors.h> 42 43 #include <net/if.h> 44 #include <net/if_var.h> 45 #include <netinet/in.h> 46 47 #include <dev/pv/pvvar.h> 48 49 /* "The" magic number, always occupies the EAX register. */ 50 #define VM_MAGIC 0x564D5868 51 52 /* Port numbers, passed on EDX.LOW . */ 53 #define VM_PORT_CMD 0x5658 54 #define VM_PORT_RPC 0x5659 55 56 /* Commands, passed on ECX.LOW. */ 57 #define VM_CMD_GET_SPEED 0x01 58 #define VM_CMD_APM 0x02 59 #define VM_CMD_GET_MOUSEPOS 0x04 60 #define VM_CMD_SET_MOUSEPOS 0x05 61 #define VM_CMD_GET_CLIPBOARD_LEN 0x06 62 #define VM_CMD_GET_CLIPBOARD 0x07 63 #define VM_CMD_SET_CLIPBOARD_LEN 0x08 64 #define VM_CMD_SET_CLIPBOARD 0x09 65 #define VM_CMD_GET_VERSION 0x0a 66 #define VM_VERSION_UNMANAGED 0x7fffffff 67 #define VM_CMD_GET_DEVINFO 0x0b 68 #define VM_CMD_DEV_ADDREMOVE 0x0c 69 #define VM_CMD_GET_GUI_OPTIONS 0x0d 70 #define VM_CMD_SET_GUI_OPTIONS 0x0e 71 #define VM_CMD_GET_SCREEN_SIZE 0x0f 72 #define VM_CMD_GET_HWVER 0x11 73 #define VM_CMD_POPUP_OSNOTFOUND 0x12 74 #define VM_CMD_GET_BIOS_UUID 0x13 75 #define VM_CMD_GET_MEM_SIZE 0x14 76 /*#define VM_CMD_GET_TIME 0x17 */ /* deprecated */ 77 #define VM_CMD_RPC 0x1e 78 #define VM_CMD_GET_TIME_FULL 0x2e 79 80 /* RPC sub-commands, passed on ECX.HIGH. */ 81 #define VM_RPC_OPEN 0x00 82 #define VM_RPC_SET_LENGTH 0x01 83 #define VM_RPC_SET_DATA 0x02 84 #define VM_RPC_GET_LENGTH 0x03 85 #define VM_RPC_GET_DATA 0x04 86 #define VM_RPC_GET_END 0x05 87 #define VM_RPC_CLOSE 0x06 88 89 /* RPC magic numbers, passed on EBX. */ 90 #define VM_RPC_OPEN_RPCI 0x49435052UL /* with VM_RPC_OPEN. */ 91 #define VM_RPC_OPEN_TCLO 0x4F4C4354UL /* with VP_RPC_OPEN. */ 92 #define VM_RPC_ENH_DATA 0x00010000UL /* with enhanced RPC data calls. */ 93 94 #define VM_RPC_FLAG_COOKIE 0x80000000UL 95 96 /* RPC reply flags */ 97 #define VM_RPC_REPLY_SUCCESS 0x0001 98 #define VM_RPC_REPLY_DORECV 0x0002 /* incoming message available */ 99 #define VM_RPC_REPLY_CLOSED 0x0004 /* RPC channel is closed */ 100 #define VM_RPC_REPLY_UNSENT 0x0008 /* incoming message was removed? */ 101 #define VM_RPC_REPLY_CHECKPOINT 0x0010 /* checkpoint occurred -> retry */ 102 #define VM_RPC_REPLY_POWEROFF 0x0020 /* underlying device is powering off */ 103 #define VM_RPC_REPLY_TIMEOUT 0x0040 104 #define VM_RPC_REPLY_HB 0x0080 /* high-bandwidth tx/rx available */ 105 106 /* VM state change IDs */ 107 #define VM_STATE_CHANGE_HALT 1 108 #define VM_STATE_CHANGE_REBOOT 2 109 #define VM_STATE_CHANGE_POWERON 3 110 #define VM_STATE_CHANGE_RESUME 4 111 #define VM_STATE_CHANGE_SUSPEND 5 112 113 /* VM guest info keys */ 114 #define VM_GUEST_INFO_DNS_NAME 1 115 #define VM_GUEST_INFO_IP_ADDRESS 2 116 #define VM_GUEST_INFO_DISK_FREE_SPACE 3 117 #define VM_GUEST_INFO_BUILD_NUMBER 4 118 #define VM_GUEST_INFO_OS_NAME_FULL 5 119 #define VM_GUEST_INFO_OS_NAME 6 120 #define VM_GUEST_INFO_UPTIME 7 121 #define VM_GUEST_INFO_MEMORY 8 122 #define VM_GUEST_INFO_IP_ADDRESS_V2 9 123 124 /* RPC responses */ 125 #define VM_RPC_REPLY_OK "OK " 126 #define VM_RPC_RESET_REPLY "OK ATR toolbox" 127 #define VM_RPC_REPLY_ERROR "ERROR Unknown command" 128 #define VM_RPC_REPLY_ERROR_IP_ADDR "ERROR Unable to find guest IP address" 129 130 /* VM backup error codes */ 131 #define VM_BACKUP_SUCCESS 0 132 #define VM_BACKUP_SYNC_ERROR 3 133 #define VM_BACKUP_REMOTE_ABORT 4 134 135 #define VM_BACKUP_TIMEOUT 30 /* seconds */ 136 137 /* A register. */ 138 union vm_reg { 139 struct { 140 uint16_t low; 141 uint16_t high; 142 } part; 143 uint32_t word; 144 #ifdef __amd64__ 145 struct { 146 uint32_t low; 147 uint32_t high; 148 } words; 149 uint64_t quad; 150 #endif 151 } __packed; 152 153 /* A register frame. */ 154 struct vm_backdoor { 155 union vm_reg eax; 156 union vm_reg ebx; 157 union vm_reg ecx; 158 union vm_reg edx; 159 union vm_reg esi; 160 union vm_reg edi; 161 union vm_reg ebp; 162 } __packed; 163 164 /* RPC context. */ 165 struct vm_rpc { 166 uint16_t channel; 167 uint32_t cookie1; 168 uint32_t cookie2; 169 }; 170 171 struct vmt_softc { 172 struct device sc_dev; 173 174 struct vm_rpc sc_tclo_rpc; 175 char *sc_rpc_buf; 176 int sc_rpc_error; 177 int sc_tclo_ping; 178 int sc_set_guest_os; 179 int sc_quiesce; 180 struct task sc_quiesce_task; 181 #define VMT_RPC_BUFLEN 4096 182 183 struct timeout sc_tick; 184 struct timeout sc_tclo_tick; 185 struct ksensordev sc_sensordev; 186 struct ksensor sc_sensor; 187 188 char sc_hostname[MAXHOSTNAMELEN]; 189 }; 190 191 #ifdef VMT_DEBUG 192 #define DPRINTF(_arg...) printf(_arg) 193 #else 194 #define DPRINTF(_arg...) do {} while(0) 195 #endif 196 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 197 198 void vm_cmd(struct vm_backdoor *); 199 void vm_ins(struct vm_backdoor *); 200 void vm_outs(struct vm_backdoor *); 201 202 /* Functions for communicating with the VM Host. */ 203 int vm_rpc_open(struct vm_rpc *, uint32_t); 204 int vm_rpc_close(struct vm_rpc *); 205 int vm_rpc_send(const struct vm_rpc *, const uint8_t *, uint32_t); 206 int vm_rpc_send_str(const struct vm_rpc *, const uint8_t *); 207 int vm_rpc_get_length(const struct vm_rpc *, uint32_t *, uint16_t *); 208 int vm_rpc_get_data(const struct vm_rpc *, char *, uint32_t, uint16_t); 209 int vm_rpc_send_rpci_tx_buf(struct vmt_softc *, const uint8_t *, uint32_t); 210 int vm_rpc_send_rpci_tx(struct vmt_softc *, const char *, ...) 211 __attribute__((__format__(__kprintf__,2,3))); 212 int vm_rpci_response_successful(struct vmt_softc *); 213 214 int vmt_kvop(void *, int, char *, char *, size_t); 215 216 void vmt_probe_cmd(struct vm_backdoor *, uint16_t); 217 void vmt_tclo_state_change_success(struct vmt_softc *, int, char); 218 void vmt_do_reboot(struct vmt_softc *); 219 void vmt_do_shutdown(struct vmt_softc *); 220 void vmt_shutdown(void *); 221 222 void vmt_clear_guest_info(struct vmt_softc *); 223 void vmt_update_guest_info(struct vmt_softc *); 224 void vmt_update_guest_uptime(struct vmt_softc *); 225 226 void vmt_tick_hook(struct device *self); 227 void vmt_tick(void *); 228 void vmt_resume(void); 229 230 int vmt_match(struct device *, void *, void *); 231 void vmt_attach(struct device *, struct device *, void *); 232 int vmt_activate(struct device *, int); 233 234 void vmt_tclo_tick(void *); 235 int vmt_tclo_process(struct vmt_softc *, const char *); 236 void vmt_tclo_reset(struct vmt_softc *); 237 void vmt_tclo_ping(struct vmt_softc *); 238 void vmt_tclo_halt(struct vmt_softc *); 239 void vmt_tclo_reboot(struct vmt_softc *); 240 void vmt_tclo_poweron(struct vmt_softc *); 241 void vmt_tclo_suspend(struct vmt_softc *); 242 void vmt_tclo_resume(struct vmt_softc *); 243 void vmt_tclo_capreg(struct vmt_softc *); 244 void vmt_tclo_broadcastip(struct vmt_softc *); 245 246 void vmt_set_backup_status(struct vmt_softc *, const char *, int, 247 const char *); 248 void vmt_quiesce_task(void *); 249 void vmt_quiesce_done_task(void *); 250 void vmt_tclo_abortbackup(struct vmt_softc *); 251 void vmt_tclo_startbackup(struct vmt_softc *); 252 void vmt_tclo_backupdone(struct vmt_softc *); 253 254 int vmt_probe(void); 255 256 struct vmt_tclo_rpc { 257 const char *name; 258 void (*cb)(struct vmt_softc *); 259 } vmt_tclo_rpc[] = { 260 /* Keep sorted by name (case-sensitive) */ 261 { "Capabilities_Register", vmt_tclo_capreg }, 262 { "OS_Halt", vmt_tclo_halt }, 263 { "OS_PowerOn", vmt_tclo_poweron }, 264 { "OS_Reboot", vmt_tclo_reboot }, 265 { "OS_Resume", vmt_tclo_resume }, 266 { "OS_Suspend", vmt_tclo_suspend }, 267 { "Set_Option broadcastIP 1", vmt_tclo_broadcastip }, 268 { "ping", vmt_tclo_ping }, 269 { "reset", vmt_tclo_reset }, 270 { "vmbackup.abort", vmt_tclo_abortbackup }, 271 { "vmbackup.snapshotDone", vmt_tclo_backupdone }, 272 { "vmbackup.start 1", vmt_tclo_startbackup }, 273 { NULL }, 274 #if 0 275 /* Various unsupported commands */ 276 { "Set_Option autohide 0" }, 277 { "Set_Option copypaste 1" }, 278 { "Set_Option enableDnD 1" }, 279 { "Set_Option enableMessageBusTunnel 0" }, 280 { "Set_Option linkRootHgfsShare 0" }, 281 { "Set_Option mapRootHgfsShare 0" }, 282 { "Set_Option synctime 1" }, 283 { "Set_Option synctime.period 0" }, 284 { "Set_Option time.synchronize.tools.enable 1" }, 285 { "Set_Option time.synchronize.tools.percentCorrection 0" }, 286 { "Set_Option time.synchronize.tools.slewCorrection 1" }, 287 { "Set_Option time.synchronize.tools.startup 1" }, 288 { "Set_Option toolScripts.afterPowerOn 1" }, 289 { "Set_Option toolScripts.afterResume 1" }, 290 { "Set_Option toolScripts.beforePowerOff 1" }, 291 { "Set_Option toolScripts.beforeSuspend 1" }, 292 { "Time_Synchronize 0" }, 293 { "Vix_1_Relayed_Command \"38cdcae40e075d66\"" }, 294 #endif 295 }; 296 297 struct cfattach vmt_ca = { 298 sizeof(struct vmt_softc), 299 vmt_match, 300 vmt_attach, 301 NULL, 302 vmt_activate 303 }; 304 305 struct cfdriver vmt_cd = { 306 NULL, 307 "vmt", 308 DV_DULL 309 }; 310 311 extern char hostname[MAXHOSTNAMELEN]; 312 313 void 314 vmt_probe_cmd(struct vm_backdoor *frame, uint16_t cmd) 315 { 316 bzero(frame, sizeof(*frame)); 317 318 (frame->eax).word = VM_MAGIC; 319 (frame->ebx).word = ~VM_MAGIC; 320 (frame->ecx).part.low = cmd; 321 (frame->ecx).part.high = 0xffff; 322 (frame->edx).part.low = VM_PORT_CMD; 323 (frame->edx).part.high = 0; 324 325 vm_cmd(frame); 326 } 327 328 int 329 vmt_probe(void) 330 { 331 struct vm_backdoor frame; 332 333 vmt_probe_cmd(&frame, VM_CMD_GET_VERSION); 334 if (frame.eax.word == 0xffffffff || 335 frame.ebx.word != VM_MAGIC) 336 return (0); 337 338 vmt_probe_cmd(&frame, VM_CMD_GET_SPEED); 339 if (frame.eax.word == VM_MAGIC) 340 return (0); 341 342 return (1); 343 } 344 345 int 346 vmt_match(struct device *parent, void *match, void *aux) 347 { 348 struct pv_attach_args *pva = aux; 349 struct pvbus_hv *hv = &pva->pva_hv[PVBUS_VMWARE]; 350 351 if (hv->hv_base == 0) 352 return (0); 353 if (!vmt_probe()) 354 return (0); 355 356 return (1); 357 } 358 359 void 360 vmt_attach(struct device *parent, struct device *self, void *aux) 361 { 362 struct vmt_softc *sc = (struct vmt_softc *)self; 363 struct pv_attach_args *pva = aux; 364 struct pvbus_hv *hv = &pva->pva_hv[PVBUS_VMWARE]; 365 366 printf("\n"); 367 sc->sc_rpc_buf = malloc(VMT_RPC_BUFLEN, M_DEVBUF, M_NOWAIT); 368 if (sc->sc_rpc_buf == NULL) { 369 printf("%s: unable to allocate buffer for RPC\n", 370 DEVNAME(sc)); 371 return; 372 } 373 374 if (vm_rpc_open(&sc->sc_tclo_rpc, VM_RPC_OPEN_TCLO) != 0) { 375 printf("%s: failed to open backdoor RPC channel " 376 "(TCLO protocol)\n", DEVNAME(sc)); 377 goto free; 378 } 379 380 /* don't know if this is important at all yet */ 381 if (vm_rpc_send_rpci_tx(sc, 382 "tools.capability.hgfs_server toolbox 1") != 0) { 383 printf(": failed to set HGFS server capability\n"); 384 goto free; 385 } 386 387 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 388 sizeof(sc->sc_sensordev.xname)); 389 390 sc->sc_sensor.type = SENSOR_TIMEDELTA; 391 sc->sc_sensor.status = SENSOR_S_UNKNOWN; 392 393 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); 394 sensordev_install(&sc->sc_sensordev); 395 396 config_mountroot(self, vmt_tick_hook); 397 398 timeout_set(&sc->sc_tclo_tick, vmt_tclo_tick, sc); 399 timeout_add_sec(&sc->sc_tclo_tick, 1); 400 sc->sc_tclo_ping = 1; 401 402 /* pvbus(4) key/value interface */ 403 hv->hv_kvop = vmt_kvop; 404 hv->hv_arg = sc; 405 406 return; 407 408 free: 409 free(sc->sc_rpc_buf, M_DEVBUF, VMT_RPC_BUFLEN); 410 } 411 412 int 413 vmt_kvop(void *arg, int op, char *key, char *value, size_t valuelen) 414 { 415 struct vmt_softc *sc = arg; 416 char *buf = NULL, *ptr; 417 size_t bufsz; 418 int error = 0; 419 420 bufsz = VMT_RPC_BUFLEN; 421 buf = malloc(bufsz, M_TEMP|M_ZERO, M_WAITOK); 422 423 switch (op) { 424 case PVBUS_KVWRITE: 425 if ((size_t)snprintf(buf, bufsz, "info-set %s %s", 426 key, value) >= bufsz) { 427 DPRINTF("%s: write command too long", DEVNAME(sc)); 428 error = EINVAL; 429 goto done; 430 } 431 break; 432 case PVBUS_KVREAD: 433 if ((size_t)snprintf(buf, bufsz, "info-get %s", 434 key) >= bufsz) { 435 DPRINTF("%s: read command too long", DEVNAME(sc)); 436 error = EINVAL; 437 goto done; 438 } 439 break; 440 default: 441 error = EOPNOTSUPP; 442 goto done; 443 } 444 445 if (vm_rpc_send_rpci_tx(sc, "%s", buf) != 0) { 446 DPRINTF("%s: error sending command: %s\n", DEVNAME(sc), buf); 447 sc->sc_rpc_error = 1; 448 error = EIO; 449 goto done; 450 } 451 452 if (vm_rpci_response_successful(sc) == 0) { 453 DPRINTF("%s: host rejected command: %s\n", DEVNAME(sc), buf); 454 error = EINVAL; 455 goto done; 456 } 457 458 /* skip response that was tested in vm_rpci_response_successful() */ 459 ptr = sc->sc_rpc_buf + 2; 460 461 /* might truncat, copy anyway but return error */ 462 if (strlcpy(value, ptr, valuelen) >= valuelen) 463 error = ENOMEM; 464 465 done: 466 free(buf, M_TEMP, bufsz); 467 return (error); 468 } 469 470 void 471 vmt_resume(void) 472 { 473 struct vm_backdoor frame; 474 extern void rdrand(void *); 475 476 bzero(&frame, sizeof(frame)); 477 frame.eax.word = VM_MAGIC; 478 frame.ecx.part.low = VM_CMD_GET_TIME_FULL; 479 frame.edx.part.low = VM_PORT_CMD; 480 vm_cmd(&frame); 481 482 rdrand(NULL); 483 enqueue_randomness(frame.eax.word); 484 enqueue_randomness(frame.esi.word); 485 enqueue_randomness(frame.edx.word); 486 enqueue_randomness(frame.ebx.word); 487 resume_randomness(NULL, 0); 488 } 489 490 int 491 vmt_activate(struct device *self, int act) 492 { 493 int rv = 0; 494 495 switch (act) { 496 case DVACT_POWERDOWN: 497 vmt_shutdown(self); 498 break; 499 case DVACT_RESUME: 500 vmt_resume(); 501 break; 502 } 503 return (rv); 504 } 505 506 507 void 508 vmt_update_guest_uptime(struct vmt_softc *sc) 509 { 510 /* host wants uptime in hundredths of a second */ 511 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %lld00", 512 VM_GUEST_INFO_UPTIME, (long long)getuptime()) != 0) { 513 DPRINTF("%s: unable to set guest uptime", DEVNAME(sc)); 514 sc->sc_rpc_error = 1; 515 } 516 } 517 518 void 519 vmt_clear_guest_info(struct vmt_softc *sc) 520 { 521 sc->sc_hostname[0] = '\0'; 522 sc->sc_set_guest_os = 0; 523 } 524 525 void 526 vmt_update_guest_info(struct vmt_softc *sc) 527 { 528 if (strncmp(sc->sc_hostname, hostname, sizeof(sc->sc_hostname)) != 0) { 529 strlcpy(sc->sc_hostname, hostname, sizeof(sc->sc_hostname)); 530 531 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %s", 532 VM_GUEST_INFO_DNS_NAME, sc->sc_hostname) != 0) { 533 DPRINTF("%s: unable to set hostname", DEVNAME(sc)); 534 sc->sc_rpc_error = 1; 535 } 536 } 537 538 /* 539 * We're supposed to pass the full network address information back 540 * here, but that involves xdr (sunrpc) data encoding, which seems a 541 * bit unreasonable. 542 */ 543 544 if (sc->sc_set_guest_os == 0) { 545 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %s %s %s", 546 VM_GUEST_INFO_OS_NAME_FULL, 547 ostype, osrelease, osversion) != 0) { 548 DPRINTF("%s: unable to set full guest OS", DEVNAME(sc)); 549 sc->sc_rpc_error = 1; 550 } 551 552 /* 553 * Host doesn't like it if we send an OS name it doesn't 554 * recognise, so use the closest match, which happens 555 * to be FreeBSD. 556 */ 557 558 if (vm_rpc_send_rpci_tx(sc, "SetGuestInfo %d %s", 559 VM_GUEST_INFO_OS_NAME, "FreeBSD") != 0) { 560 DPRINTF("%s: unable to set guest OS", DEVNAME(sc)); 561 sc->sc_rpc_error = 1; 562 } 563 564 sc->sc_set_guest_os = 1; 565 } 566 } 567 568 void 569 vmt_tick_hook(struct device *self) 570 { 571 struct vmt_softc *sc = (struct vmt_softc *)self; 572 573 timeout_set(&sc->sc_tick, vmt_tick, sc); 574 vmt_tick(sc); 575 } 576 577 void 578 vmt_tick(void *xarg) 579 { 580 struct vmt_softc *sc = xarg; 581 struct vm_backdoor frame; 582 struct timeval *guest = &sc->sc_sensor.tv; 583 struct timeval host, diff; 584 585 microtime(guest); 586 587 bzero(&frame, sizeof(frame)); 588 frame.eax.word = VM_MAGIC; 589 frame.ecx.part.low = VM_CMD_GET_TIME_FULL; 590 frame.edx.part.low = VM_PORT_CMD; 591 vm_cmd(&frame); 592 593 if (frame.eax.word != 0xffffffff) { 594 host.tv_sec = ((uint64_t)frame.esi.word << 32) | frame.edx.word; 595 host.tv_usec = frame.ebx.word; 596 597 timersub(guest, &host, &diff); 598 599 sc->sc_sensor.value = (u_int64_t)diff.tv_sec * 1000000000LL + 600 (u_int64_t)diff.tv_usec * 1000LL; 601 sc->sc_sensor.status = SENSOR_S_OK; 602 } else { 603 sc->sc_sensor.status = SENSOR_S_UNKNOWN; 604 } 605 606 vmt_update_guest_info(sc); 607 vmt_update_guest_uptime(sc); 608 609 timeout_add_sec(&sc->sc_tick, 15); 610 } 611 612 void 613 vmt_tclo_state_change_success(struct vmt_softc *sc, int success, char state) 614 { 615 if (vm_rpc_send_rpci_tx(sc, "tools.os.statechange.status %d %d", 616 success, state) != 0) { 617 DPRINTF("%s: unable to send state change result\n", 618 DEVNAME(sc)); 619 sc->sc_rpc_error = 1; 620 } 621 } 622 623 void 624 vmt_do_shutdown(struct vmt_softc *sc) 625 { 626 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_HALT); 627 vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK); 628 pvbus_shutdown(&sc->sc_dev); 629 } 630 631 void 632 vmt_do_reboot(struct vmt_softc *sc) 633 { 634 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_REBOOT); 635 vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK); 636 pvbus_reboot(&sc->sc_dev); 637 } 638 639 void 640 vmt_shutdown(void *arg) 641 { 642 struct vmt_softc *sc = arg; 643 644 if (vm_rpc_send_rpci_tx(sc, 645 "tools.capability.hgfs_server toolbox 0") != 0) { 646 DPRINTF("%s: failed to disable hgfs server capability\n", 647 DEVNAME(sc)); 648 } 649 650 if (vm_rpc_send(&sc->sc_tclo_rpc, NULL, 0) != 0) { 651 DPRINTF("%s: failed to send shutdown ping\n", DEVNAME(sc)); 652 } 653 654 vm_rpc_close(&sc->sc_tclo_rpc); 655 } 656 657 void 658 vmt_tclo_reset(struct vmt_softc *sc) 659 { 660 if (sc->sc_rpc_error != 0) { 661 DPRINTF("%s: resetting rpc\n", DEVNAME(sc)); 662 vm_rpc_close(&sc->sc_tclo_rpc); 663 664 /* reopen and send the reset reply next time around */ 665 sc->sc_rpc_error = 1; 666 return; 667 } 668 669 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_RESET_REPLY) != 0) { 670 DPRINTF("%s: failed to send reset reply\n", DEVNAME(sc)); 671 sc->sc_rpc_error = 1; 672 } 673 } 674 675 void 676 vmt_tclo_ping(struct vmt_softc *sc) 677 { 678 vmt_update_guest_info(sc); 679 680 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) { 681 DPRINTF("%s: error sending ping response\n", DEVNAME(sc)); 682 sc->sc_rpc_error = 1; 683 } 684 } 685 686 void 687 vmt_tclo_halt(struct vmt_softc *sc) 688 { 689 vmt_do_shutdown(sc); 690 } 691 692 void 693 vmt_tclo_reboot(struct vmt_softc *sc) 694 { 695 vmt_do_reboot(sc); 696 } 697 698 void 699 vmt_tclo_poweron(struct vmt_softc *sc) 700 { 701 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_POWERON); 702 703 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) { 704 DPRINTF("%s: error sending poweron response\n", DEVNAME(sc)); 705 sc->sc_rpc_error = 1; 706 } 707 } 708 709 void 710 vmt_tclo_suspend(struct vmt_softc *sc) 711 { 712 log(LOG_KERN | LOG_NOTICE, 713 "VMware guest entering suspended state\n"); 714 715 suspend_randomness(); 716 717 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_SUSPEND); 718 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) { 719 DPRINTF("%s: error sending suspend response\n", DEVNAME(sc)); 720 sc->sc_rpc_error = 1; 721 } 722 } 723 724 void 725 vmt_tclo_resume(struct vmt_softc *sc) 726 { 727 log(LOG_KERN | LOG_NOTICE, 728 "VMware guest resuming from suspended state\n"); 729 730 /* force guest info update */ 731 vmt_clear_guest_info(sc); 732 vmt_update_guest_info(sc); 733 vmt_resume(); 734 735 vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_RESUME); 736 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) { 737 DPRINTF("%s: error sending resume response\n", DEVNAME(sc)); 738 sc->sc_rpc_error = 1; 739 } 740 } 741 742 void 743 vmt_tclo_capreg(struct vmt_softc *sc) 744 { 745 /* don't know if this is important at all */ 746 if (vm_rpc_send_rpci_tx(sc, 747 "vmx.capability.unified_loop toolbox") != 0) { 748 DPRINTF("%s: unable to set unified loop\n", DEVNAME(sc)); 749 sc->sc_rpc_error = 1; 750 } 751 752 if (vm_rpci_response_successful(sc) == 0) { 753 DPRINTF("%s: host rejected unified loop setting\n", 754 DEVNAME(sc)); 755 } 756 757 /* the trailing space is apparently important here */ 758 if (vm_rpc_send_rpci_tx(sc, 759 "tools.capability.statechange ") != 0) { 760 DPRINTF("%s: unable to send statechange capability\n", 761 DEVNAME(sc)); 762 sc->sc_rpc_error = 1; 763 } 764 765 if (vm_rpci_response_successful(sc) == 0) { 766 DPRINTF("%s: host rejected statechange capability\n", 767 DEVNAME(sc)); 768 } 769 770 if (vm_rpc_send_rpci_tx(sc, "tools.set.version %u", 771 VM_VERSION_UNMANAGED) != 0) { 772 DPRINTF("%s: unable to set tools version\n", 773 DEVNAME(sc)); 774 sc->sc_rpc_error = 1; 775 } 776 777 vmt_clear_guest_info(sc); 778 vmt_update_guest_uptime(sc); 779 780 if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) { 781 DPRINTF("%s: error sending capabilities_register" 782 " response\n", DEVNAME(sc)); 783 sc->sc_rpc_error = 1; 784 } 785 } 786 787 void 788 vmt_tclo_broadcastip(struct vmt_softc *sc) 789 { 790 struct ifnet *iface; 791 struct sockaddr_in *guest_ip; 792 793 /* find first available ipv4 address */ 794 guest_ip = NULL; 795 TAILQ_FOREACH(iface, &ifnet, if_list) { 796 struct ifaddr *iface_addr; 797 798 /* skip loopback */ 799 if (strncmp(iface->if_xname, "lo", 2) == 0 && 800 iface->if_xname[2] >= '0' && 801 iface->if_xname[2] <= '9') { 802 continue; 803 } 804 805 TAILQ_FOREACH(iface_addr, &iface->if_addrlist, 806 ifa_list) { 807 if (iface_addr->ifa_addr->sa_family != AF_INET) 808 continue; 809 810 guest_ip = satosin(iface_addr->ifa_addr); 811 break; 812 } 813 } 814 815 if (guest_ip != NULL) { 816 char ip[INET_ADDRSTRLEN]; 817 818 inet_ntop(AF_INET, &guest_ip->sin_addr, ip, sizeof(ip)); 819 if (vm_rpc_send_rpci_tx(sc, "info-set guestinfo.ip %s", 820 ip) != 0) { 821 DPRINTF("%s: unable to send guest IP address\n", 822 DEVNAME(sc)); 823 sc->sc_rpc_error = 1; 824 } 825 826 if (vm_rpc_send_str(&sc->sc_tclo_rpc, 827 VM_RPC_REPLY_OK) != 0) { 828 DPRINTF("%s: error sending broadcastIP" 829 " response\n", DEVNAME(sc)); 830 sc->sc_rpc_error = 1; 831 } 832 } else { 833 if (vm_rpc_send_str(&sc->sc_tclo_rpc, 834 VM_RPC_REPLY_ERROR_IP_ADDR) != 0) { 835 DPRINTF("%s: error sending broadcastIP" 836 " error response\n", DEVNAME(sc)); 837 sc->sc_rpc_error = 1; 838 } 839 } 840 } 841 842 void 843 vmt_set_backup_status(struct vmt_softc *sc, const char *state, int code, 844 const char *desc) 845 { 846 if (vm_rpc_send_rpci_tx(sc, "vmbackup.eventSet %s %d %s", 847 state, code, desc) != 0) { 848 DPRINTF("%s: setting backup status failed\n", DEVNAME(sc)); 849 } 850 } 851 852 void 853 vmt_quiesce_task(void *data) 854 { 855 struct vmt_softc *sc = data; 856 int err; 857 858 DPRINTF("%s: quiescing filesystems for backup\n", DEVNAME(sc)); 859 err = vfs_stall(curproc, 1); 860 if (err != 0) { 861 printf("%s: unable to quiesce filesystems\n", DEVNAME(sc)); 862 vfs_stall(curproc, 0); 863 864 vmt_set_backup_status(sc, "req.aborted", VM_BACKUP_SYNC_ERROR, 865 "vfs_stall failed"); 866 vmt_set_backup_status(sc, "req.done", VM_BACKUP_SUCCESS, ""); 867 sc->sc_quiesce = 0; 868 return; 869 } 870 871 DPRINTF("%s: filesystems quiesced\n", DEVNAME(sc)); 872 vmt_set_backup_status(sc, "prov.snapshotCommit", VM_BACKUP_SUCCESS, ""); 873 } 874 875 void 876 vmt_quiesce_done_task(void *data) 877 { 878 struct vmt_softc *sc = data; 879 880 vfs_stall(curproc, 0); 881 882 if (sc->sc_quiesce == -1) 883 vmt_set_backup_status(sc, "req.aborted", VM_BACKUP_REMOTE_ABORT, 884 ""); 885 886 vmt_set_backup_status(sc, "req.done", VM_BACKUP_SUCCESS, ""); 887 sc->sc_quiesce = 0; 888 } 889 890 void 891 vmt_tclo_abortbackup(struct vmt_softc *sc) 892 { 893 const char *reply = VM_RPC_REPLY_OK; 894 895 if (sc->sc_quiesce > 0) { 896 DPRINTF("%s: aborting backup\n", DEVNAME(sc)); 897 sc->sc_quiesce = -1; 898 task_set(&sc->sc_quiesce_task, vmt_quiesce_done_task, sc); 899 task_add(systq, &sc->sc_quiesce_task); 900 } else { 901 DPRINTF("%s: can't abort, no backup in progress\n", 902 DEVNAME(sc)); 903 reply = VM_RPC_REPLY_ERROR; 904 } 905 906 if (vm_rpc_send_str(&sc->sc_tclo_rpc, reply) != 0) { 907 DPRINTF("%s: error sending vmbackup.abort reply\n", 908 DEVNAME(sc)); 909 sc->sc_rpc_error = 1; 910 } 911 } 912 913 void 914 vmt_tclo_startbackup(struct vmt_softc *sc) 915 { 916 const char *reply = VM_RPC_REPLY_OK; 917 918 if (sc->sc_quiesce == 0) { 919 DPRINTF("%s: starting quiesce\n", DEVNAME(sc)); 920 vmt_set_backup_status(sc, "reset", VM_BACKUP_SUCCESS, ""); 921 922 task_set(&sc->sc_quiesce_task, vmt_quiesce_task, sc); 923 task_add(systq, &sc->sc_quiesce_task); 924 sc->sc_quiesce = 1; 925 } else { 926 DPRINTF("%s: can't start backup, already in progress\n", 927 DEVNAME(sc)); 928 reply = VM_RPC_REPLY_ERROR; 929 } 930 931 if (vm_rpc_send_str(&sc->sc_tclo_rpc, reply) != 0) { 932 DPRINTF("%s: error sending vmbackup.start reply\n", 933 DEVNAME(sc)); 934 sc->sc_rpc_error = 1; 935 } 936 } 937 938 void 939 vmt_tclo_backupdone(struct vmt_softc *sc) 940 { 941 const char *reply = VM_RPC_REPLY_OK; 942 if (sc->sc_quiesce > 0) { 943 DPRINTF("%s: backup complete\n", DEVNAME(sc)); 944 task_set(&sc->sc_quiesce_task, vmt_quiesce_done_task, sc); 945 task_add(systq, &sc->sc_quiesce_task); 946 } else { 947 DPRINTF("%s: got backup complete, but not doing a backup\n", 948 DEVNAME(sc)); 949 reply = VM_RPC_REPLY_ERROR; 950 } 951 952 if (vm_rpc_send_str(&sc->sc_tclo_rpc, reply) != 0) { 953 DPRINTF("%s: error sending vmbackup.snapshotDone reply\n", 954 DEVNAME(sc)); 955 sc->sc_rpc_error = 1; 956 } 957 } 958 959 int 960 vmt_tclo_process(struct vmt_softc *sc, const char *name) 961 { 962 int i; 963 964 /* Search for rpc command and call handler */ 965 for (i = 0; vmt_tclo_rpc[i].name != NULL; i++) { 966 if (strcmp(vmt_tclo_rpc[i].name, sc->sc_rpc_buf) == 0) { 967 vmt_tclo_rpc[i].cb(sc); 968 return (0); 969 } 970 } 971 972 DPRINTF("%s: unknown command: \"%s\"\n", DEVNAME(sc), name); 973 974 return (-1); 975 } 976 977 void 978 vmt_tclo_tick(void *xarg) 979 { 980 struct vmt_softc *sc = xarg; 981 u_int32_t rlen; 982 u_int16_t ack; 983 int delay; 984 985 /* By default, poll every second for new messages */ 986 delay = 1; 987 988 if (sc->sc_quiesce > 0) { 989 /* abort quiesce if it's taking too long */ 990 if (sc->sc_quiesce++ == VM_BACKUP_TIMEOUT) { 991 printf("%s: aborting quiesce\n", DEVNAME(sc)); 992 sc->sc_quiesce = -1; 993 task_set(&sc->sc_quiesce_task, vmt_quiesce_done_task, 994 sc); 995 task_add(systq, &sc->sc_quiesce_task); 996 } else 997 vmt_set_backup_status(sc, "req.keepAlive", 998 VM_BACKUP_SUCCESS, ""); 999 } 1000 1001 /* reopen tclo channel if it's currently closed */ 1002 if (sc->sc_tclo_rpc.channel == 0 && 1003 sc->sc_tclo_rpc.cookie1 == 0 && 1004 sc->sc_tclo_rpc.cookie2 == 0) { 1005 if (vm_rpc_open(&sc->sc_tclo_rpc, VM_RPC_OPEN_TCLO) != 0) { 1006 DPRINTF("%s: unable to reopen TCLO channel\n", 1007 DEVNAME(sc)); 1008 delay = 15; 1009 goto out; 1010 } 1011 1012 if (vm_rpc_send_str(&sc->sc_tclo_rpc, 1013 VM_RPC_RESET_REPLY) != 0) { 1014 DPRINTF("%s: failed to send reset reply\n", 1015 DEVNAME(sc)); 1016 sc->sc_rpc_error = 1; 1017 goto out; 1018 } else { 1019 sc->sc_rpc_error = 0; 1020 } 1021 } 1022 1023 if (sc->sc_tclo_ping) { 1024 if (vm_rpc_send(&sc->sc_tclo_rpc, NULL, 0) != 0) { 1025 DPRINTF("%s: failed to send TCLO outgoing ping\n", 1026 DEVNAME(sc)); 1027 sc->sc_rpc_error = 1; 1028 goto out; 1029 } 1030 } 1031 1032 if (vm_rpc_get_length(&sc->sc_tclo_rpc, &rlen, &ack) != 0) { 1033 DPRINTF("%s: failed to get length of incoming TCLO data\n", 1034 DEVNAME(sc)); 1035 sc->sc_rpc_error = 1; 1036 goto out; 1037 } 1038 1039 if (rlen == 0) { 1040 sc->sc_tclo_ping = 1; 1041 goto out; 1042 } 1043 1044 if (rlen >= VMT_RPC_BUFLEN) { 1045 rlen = VMT_RPC_BUFLEN - 1; 1046 } 1047 if (vm_rpc_get_data(&sc->sc_tclo_rpc, sc->sc_rpc_buf, rlen, ack) != 0) { 1048 DPRINTF("%s: failed to get incoming TCLO data\n", DEVNAME(sc)); 1049 sc->sc_rpc_error = 1; 1050 goto out; 1051 } 1052 sc->sc_tclo_ping = 0; 1053 1054 /* The VM host can queue multiple messages; continue without delay */ 1055 delay = 0; 1056 1057 if (vmt_tclo_process(sc, sc->sc_rpc_buf) != 0) { 1058 if (vm_rpc_send_str(&sc->sc_tclo_rpc, 1059 VM_RPC_REPLY_ERROR) != 0) { 1060 DPRINTF("%s: error sending unknown command reply\n", 1061 DEVNAME(sc)); 1062 sc->sc_rpc_error = 1; 1063 } 1064 } 1065 1066 if (sc->sc_rpc_error == 1) { 1067 /* On error, give time to recover and wait a second */ 1068 delay = 1; 1069 } 1070 1071 out: 1072 timeout_add_sec(&sc->sc_tclo_tick, delay); 1073 } 1074 1075 #define BACKDOOR_OP_I386(op, frame) \ 1076 __asm__ volatile ( \ 1077 "pushal;" \ 1078 "pushl %%eax;" \ 1079 "movl 0x18(%%eax), %%ebp;" \ 1080 "movl 0x14(%%eax), %%edi;" \ 1081 "movl 0x10(%%eax), %%esi;" \ 1082 "movl 0x0c(%%eax), %%edx;" \ 1083 "movl 0x08(%%eax), %%ecx;" \ 1084 "movl 0x04(%%eax), %%ebx;" \ 1085 "movl 0x00(%%eax), %%eax;" \ 1086 op \ 1087 "xchgl %%eax, 0x00(%%esp);" \ 1088 "movl %%ebp, 0x18(%%eax);" \ 1089 "movl %%edi, 0x14(%%eax);" \ 1090 "movl %%esi, 0x10(%%eax);" \ 1091 "movl %%edx, 0x0c(%%eax);" \ 1092 "movl %%ecx, 0x08(%%eax);" \ 1093 "movl %%ebx, 0x04(%%eax);" \ 1094 "popl 0x00(%%eax);" \ 1095 "popal;" \ 1096 ::"a"(frame) \ 1097 ) 1098 1099 #define BACKDOOR_OP_AMD64(op, frame) \ 1100 __asm__ volatile ( \ 1101 "pushq %%rbp; \n\t" \ 1102 "pushq %%rax; \n\t" \ 1103 "movq 0x30(%%rax), %%rbp; \n\t" \ 1104 "movq 0x28(%%rax), %%rdi; \n\t" \ 1105 "movq 0x20(%%rax), %%rsi; \n\t" \ 1106 "movq 0x18(%%rax), %%rdx; \n\t" \ 1107 "movq 0x10(%%rax), %%rcx; \n\t" \ 1108 "movq 0x08(%%rax), %%rbx; \n\t" \ 1109 "movq 0x00(%%rax), %%rax; \n\t" \ 1110 op "\n\t" \ 1111 "xchgq %%rax, 0x00(%%rsp); \n\t" \ 1112 "movq %%rbp, 0x30(%%rax); \n\t" \ 1113 "movq %%rdi, 0x28(%%rax); \n\t" \ 1114 "movq %%rsi, 0x20(%%rax); \n\t" \ 1115 "movq %%rdx, 0x18(%%rax); \n\t" \ 1116 "movq %%rcx, 0x10(%%rax); \n\t" \ 1117 "movq %%rbx, 0x08(%%rax); \n\t" \ 1118 "popq 0x00(%%rax); \n\t" \ 1119 "popq %%rbp; \n\t" \ 1120 : /* No outputs. */ : "a" (frame) \ 1121 /* No pushal on amd64 so warn gcc about the clobbered registers. */ \ 1122 : "rbx", "rcx", "rdx", "rdi", "rsi", "cc", "memory" \ 1123 ) 1124 1125 1126 #ifdef __i386__ 1127 #define BACKDOOR_OP(op, frame) BACKDOOR_OP_I386(op, frame) 1128 #else 1129 #define BACKDOOR_OP(op, frame) BACKDOOR_OP_AMD64(op, frame) 1130 #endif 1131 1132 void 1133 vm_cmd(struct vm_backdoor *frame) 1134 { 1135 BACKDOOR_OP("inl %%dx, %%eax;", frame); 1136 } 1137 1138 void 1139 vm_ins(struct vm_backdoor *frame) 1140 { 1141 BACKDOOR_OP("cld;\n\trep insb;", frame); 1142 } 1143 1144 void 1145 vm_outs(struct vm_backdoor *frame) 1146 { 1147 BACKDOOR_OP("cld;\n\trep outsb;", frame); 1148 } 1149 1150 int 1151 vm_rpc_open(struct vm_rpc *rpc, uint32_t proto) 1152 { 1153 struct vm_backdoor frame; 1154 1155 bzero(&frame, sizeof(frame)); 1156 frame.eax.word = VM_MAGIC; 1157 frame.ebx.word = proto | VM_RPC_FLAG_COOKIE; 1158 frame.ecx.part.low = VM_CMD_RPC; 1159 frame.ecx.part.high = VM_RPC_OPEN; 1160 frame.edx.part.low = VM_PORT_CMD; 1161 frame.edx.part.high = 0; 1162 1163 vm_cmd(&frame); 1164 1165 if (frame.ecx.part.high != 1 || frame.edx.part.low != 0) { 1166 /* open-vm-tools retries without VM_RPC_FLAG_COOKIE here.. */ 1167 DPRINTF("vmware: open failed, eax=%08x, ecx=%08x, edx=%08x\n", 1168 frame.eax.word, frame.ecx.word, frame.edx.word); 1169 return EIO; 1170 } 1171 1172 rpc->channel = frame.edx.part.high; 1173 rpc->cookie1 = frame.esi.word; 1174 rpc->cookie2 = frame.edi.word; 1175 1176 return 0; 1177 } 1178 1179 int 1180 vm_rpc_close(struct vm_rpc *rpc) 1181 { 1182 struct vm_backdoor frame; 1183 1184 bzero(&frame, sizeof(frame)); 1185 frame.eax.word = VM_MAGIC; 1186 frame.ebx.word = 0; 1187 frame.ecx.part.low = VM_CMD_RPC; 1188 frame.ecx.part.high = VM_RPC_CLOSE; 1189 frame.edx.part.low = VM_PORT_CMD; 1190 frame.edx.part.high = rpc->channel; 1191 frame.edi.word = rpc->cookie2; 1192 frame.esi.word = rpc->cookie1; 1193 1194 vm_cmd(&frame); 1195 1196 if (frame.ecx.part.high == 0 || frame.ecx.part.low != 0) { 1197 DPRINTF("vmware: close failed, eax=%08x, ecx=%08x\n", 1198 frame.eax.word, frame.ecx.word); 1199 return EIO; 1200 } 1201 1202 rpc->channel = 0; 1203 rpc->cookie1 = 0; 1204 rpc->cookie2 = 0; 1205 1206 return 0; 1207 } 1208 1209 int 1210 vm_rpc_send(const struct vm_rpc *rpc, const uint8_t *buf, uint32_t length) 1211 { 1212 struct vm_backdoor frame; 1213 1214 /* Send the length of the command. */ 1215 bzero(&frame, sizeof(frame)); 1216 frame.eax.word = VM_MAGIC; 1217 frame.ebx.word = length; 1218 frame.ecx.part.low = VM_CMD_RPC; 1219 frame.ecx.part.high = VM_RPC_SET_LENGTH; 1220 frame.edx.part.low = VM_PORT_CMD; 1221 frame.edx.part.high = rpc->channel; 1222 frame.esi.word = rpc->cookie1; 1223 frame.edi.word = rpc->cookie2; 1224 1225 vm_cmd(&frame); 1226 1227 if ((frame.ecx.part.high & VM_RPC_REPLY_SUCCESS) == 0) { 1228 DPRINTF("vmware: sending length failed, eax=%08x, ecx=%08x\n", 1229 frame.eax.word, frame.ecx.word); 1230 return EIO; 1231 } 1232 1233 if (length == 0) 1234 return 0; /* Only need to poke once if command is null. */ 1235 1236 /* Send the command using enhanced RPC. */ 1237 bzero(&frame, sizeof(frame)); 1238 frame.eax.word = VM_MAGIC; 1239 frame.ebx.word = VM_RPC_ENH_DATA; 1240 frame.ecx.word = length; 1241 frame.edx.part.low = VM_PORT_RPC; 1242 frame.edx.part.high = rpc->channel; 1243 frame.ebp.word = rpc->cookie1; 1244 frame.edi.word = rpc->cookie2; 1245 #ifdef __amd64__ 1246 frame.esi.quad = (uint64_t)buf; 1247 #else 1248 frame.esi.word = (uint32_t)buf; 1249 #endif 1250 1251 vm_outs(&frame); 1252 1253 if (frame.ebx.word != VM_RPC_ENH_DATA) { 1254 /* open-vm-tools retries on VM_RPC_REPLY_CHECKPOINT */ 1255 DPRINTF("vmware: send failed, ebx=%08x\n", frame.ebx.word); 1256 return EIO; 1257 } 1258 1259 return 0; 1260 } 1261 1262 int 1263 vm_rpc_send_str(const struct vm_rpc *rpc, const uint8_t *str) 1264 { 1265 return vm_rpc_send(rpc, str, strlen(str)); 1266 } 1267 1268 int 1269 vm_rpc_get_data(const struct vm_rpc *rpc, char *data, uint32_t length, 1270 uint16_t dataid) 1271 { 1272 struct vm_backdoor frame; 1273 1274 /* Get data using enhanced RPC. */ 1275 bzero(&frame, sizeof(frame)); 1276 frame.eax.word = VM_MAGIC; 1277 frame.ebx.word = VM_RPC_ENH_DATA; 1278 frame.ecx.word = length; 1279 frame.edx.part.low = VM_PORT_RPC; 1280 frame.edx.part.high = rpc->channel; 1281 frame.esi.word = rpc->cookie1; 1282 #ifdef __amd64__ 1283 frame.edi.quad = (uint64_t)data; 1284 #else 1285 frame.edi.word = (uint32_t)data; 1286 #endif 1287 frame.ebp.word = rpc->cookie2; 1288 1289 vm_ins(&frame); 1290 1291 /* NUL-terminate the data */ 1292 data[length] = '\0'; 1293 1294 if (frame.ebx.word != VM_RPC_ENH_DATA) { 1295 DPRINTF("vmware: get data failed, ebx=%08x\n", 1296 frame.ebx.word); 1297 return EIO; 1298 } 1299 1300 /* Acknowledge data received. */ 1301 bzero(&frame, sizeof(frame)); 1302 frame.eax.word = VM_MAGIC; 1303 frame.ebx.word = dataid; 1304 frame.ecx.part.low = VM_CMD_RPC; 1305 frame.ecx.part.high = VM_RPC_GET_END; 1306 frame.edx.part.low = VM_PORT_CMD; 1307 frame.edx.part.high = rpc->channel; 1308 frame.esi.word = rpc->cookie1; 1309 frame.edi.word = rpc->cookie2; 1310 1311 vm_cmd(&frame); 1312 1313 if (frame.ecx.part.high == 0) { 1314 DPRINTF("vmware: ack data failed, eax=%08x, ecx=%08x\n", 1315 frame.eax.word, frame.ecx.word); 1316 return EIO; 1317 } 1318 1319 return 0; 1320 } 1321 1322 int 1323 vm_rpc_get_length(const struct vm_rpc *rpc, uint32_t *length, uint16_t *dataid) 1324 { 1325 struct vm_backdoor frame; 1326 1327 bzero(&frame, sizeof(frame)); 1328 frame.eax.word = VM_MAGIC; 1329 frame.ebx.word = 0; 1330 frame.ecx.part.low = VM_CMD_RPC; 1331 frame.ecx.part.high = VM_RPC_GET_LENGTH; 1332 frame.edx.part.low = VM_PORT_CMD; 1333 frame.edx.part.high = rpc->channel; 1334 frame.esi.word = rpc->cookie1; 1335 frame.edi.word = rpc->cookie2; 1336 1337 vm_cmd(&frame); 1338 1339 if ((frame.ecx.part.high & VM_RPC_REPLY_SUCCESS) == 0) { 1340 DPRINTF("vmware: get length failed, eax=%08x, ecx=%08x\n", 1341 frame.eax.word, frame.ecx.word); 1342 return EIO; 1343 } 1344 if ((frame.ecx.part.high & VM_RPC_REPLY_DORECV) == 0) { 1345 *length = 0; 1346 *dataid = 0; 1347 } else { 1348 *length = frame.ebx.word; 1349 *dataid = frame.edx.part.high; 1350 } 1351 1352 return 0; 1353 } 1354 1355 int 1356 vm_rpci_response_successful(struct vmt_softc *sc) 1357 { 1358 return (sc->sc_rpc_buf[0] == '1' && sc->sc_rpc_buf[1] == ' '); 1359 } 1360 1361 int 1362 vm_rpc_send_rpci_tx_buf(struct vmt_softc *sc, const uint8_t *buf, 1363 uint32_t length) 1364 { 1365 struct vm_rpc rpci; 1366 u_int32_t rlen; 1367 u_int16_t ack; 1368 int result = 0; 1369 1370 if (vm_rpc_open(&rpci, VM_RPC_OPEN_RPCI) != 0) { 1371 DPRINTF("%s: rpci channel open failed\n", DEVNAME(sc)); 1372 return EIO; 1373 } 1374 1375 if (vm_rpc_send(&rpci, sc->sc_rpc_buf, length) != 0) { 1376 DPRINTF("%s: unable to send rpci command\n", DEVNAME(sc)); 1377 result = EIO; 1378 goto out; 1379 } 1380 1381 if (vm_rpc_get_length(&rpci, &rlen, &ack) != 0) { 1382 DPRINTF("%s: failed to get length of rpci response data\n", 1383 DEVNAME(sc)); 1384 result = EIO; 1385 goto out; 1386 } 1387 1388 if (rlen > 0) { 1389 if (rlen >= VMT_RPC_BUFLEN) { 1390 rlen = VMT_RPC_BUFLEN - 1; 1391 } 1392 1393 if (vm_rpc_get_data(&rpci, sc->sc_rpc_buf, rlen, ack) != 0) { 1394 DPRINTF("%s: failed to get rpci response data\n", 1395 DEVNAME(sc)); 1396 result = EIO; 1397 goto out; 1398 } 1399 } 1400 1401 out: 1402 if (vm_rpc_close(&rpci) != 0) { 1403 DPRINTF("%s: unable to close rpci channel\n", DEVNAME(sc)); 1404 } 1405 1406 return result; 1407 } 1408 1409 int 1410 vm_rpc_send_rpci_tx(struct vmt_softc *sc, const char *fmt, ...) 1411 { 1412 va_list args; 1413 int len; 1414 1415 va_start(args, fmt); 1416 len = vsnprintf(sc->sc_rpc_buf, VMT_RPC_BUFLEN, fmt, args); 1417 va_end(args); 1418 1419 if (len >= VMT_RPC_BUFLEN) { 1420 DPRINTF("%s: rpci command didn't fit in buffer\n", DEVNAME(sc)); 1421 return EIO; 1422 } 1423 1424 return vm_rpc_send_rpci_tx_buf(sc, sc->sc_rpc_buf, len); 1425 } 1426 1427 #if 0 1428 struct vm_backdoor frame; 1429 1430 bzero(&frame, sizeof(frame)); 1431 1432 frame.eax.word = VM_MAGIC; 1433 frame.ecx.part.low = VM_CMD_GET_VERSION; 1434 frame.edx.part.low = VM_PORT_CMD; 1435 1436 printf("\n"); 1437 printf("eax 0x%08x\n", frame.eax.word); 1438 printf("ebx 0x%08x\n", frame.ebx.word); 1439 printf("ecx 0x%08x\n", frame.ecx.word); 1440 printf("edx 0x%08x\n", frame.edx.word); 1441 printf("ebp 0x%08x\n", frame.ebp.word); 1442 printf("edi 0x%08x\n", frame.edi.word); 1443 printf("esi 0x%08x\n", frame.esi.word); 1444 1445 vm_cmd(&frame); 1446 1447 printf("-\n"); 1448 printf("eax 0x%08x\n", frame.eax.word); 1449 printf("ebx 0x%08x\n", frame.ebx.word); 1450 printf("ecx 0x%08x\n", frame.ecx.word); 1451 printf("edx 0x%08x\n", frame.edx.word); 1452 printf("ebp 0x%08x\n", frame.ebp.word); 1453 printf("edi 0x%08x\n", frame.edi.word); 1454 printf("esi 0x%08x\n", frame.esi.word); 1455 #endif 1456 1457 /* 1458 * Notes on tracing backdoor activity in vmware-guestd: 1459 * 1460 * - Find the addresses of the inl / rep insb / rep outsb 1461 * instructions used to perform backdoor operations. 1462 * One way to do this is to disassemble vmware-guestd: 1463 * 1464 * $ objdump -S /emul/freebsd/sbin/vmware-guestd > vmware-guestd.S 1465 * 1466 * and search for '<tab>in ' in the resulting file. The rep insb and 1467 * rep outsb code is directly below that. 1468 * 1469 * - Run vmware-guestd under gdb, setting up breakpoints as follows: 1470 * (the addresses shown here are the ones from VMware-server-1.0.10-203137, 1471 * the last version that actually works in FreeBSD emulation on OpenBSD) 1472 * 1473 * break *0x805497b (address of 'in' instruction) 1474 * commands 1 1475 * silent 1476 * echo INOUT\n 1477 * print/x $ecx 1478 * print/x $ebx 1479 * print/x $edx 1480 * continue 1481 * end 1482 * break *0x805497c (address of instruction after 'in') 1483 * commands 2 1484 * silent 1485 * echo ===\n 1486 * print/x $ecx 1487 * print/x $ebx 1488 * print/x $edx 1489 * echo \n 1490 * continue 1491 * end 1492 * break *0x80549b7 (address of instruction before 'rep insb') 1493 * commands 3 1494 * silent 1495 * set variable $inaddr = $edi 1496 * set variable $incount = $ecx 1497 * continue 1498 * end 1499 * break *0x80549ba (address of instruction after 'rep insb') 1500 * commands 4 1501 * silent 1502 * echo IN\n 1503 * print $incount 1504 * x/s $inaddr 1505 * echo \n 1506 * continue 1507 * end 1508 * break *0x80549fb (address of instruction before 'rep outsb') 1509 * commands 5 1510 * silent 1511 * echo OUT\n 1512 * print $ecx 1513 * x/s $esi 1514 * echo \n 1515 * continue 1516 * end 1517 * 1518 * This will produce a log of the backdoor operations, including the 1519 * data sent and received and the relevant register values. You can then 1520 * match the register values to the various constants in this file. 1521 */ 1522