1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <dlfcn.h> 6#include <inttypes.h> 7#include <stdarg.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11#include <unistd.h> 12 13#include <ddk/debug.h> 14#include <ddk/device.h> 15#include <ddk/driver.h> 16#include <ddk/binding.h> 17 18#include <zircon/dlfcn.h> 19#include <zircon/process.h> 20#include <zircon/processargs.h> 21#include <zircon/syscalls.h> 22#include <zircon/syscalls/log.h> 23 24#include <fuchsia/io/c/fidl.h> 25#include <lib/fdio/util.h> 26#include <lib/fdio/remoteio.h> 27#include <lib/fidl/coding.h> 28#include <zxcpp/new.h> 29 30#include "devcoordinator.h" 31#include "devhost.h" 32#include "devhost-main.h" 33#include "log.h" 34 35uint32_t log_flags = LOG_ERROR | LOG_INFO; 36 37struct proxy_iostate { 38 zx_device_t* dev; 39 port_handler_t ph; 40}; 41static void proxy_ios_create(zx_device_t* dev, zx_handle_t h); 42static void proxy_ios_destroy(zx_device_t* dev); 43 44#define proxy_ios_from_ph(ph) containerof(ph, proxy_iostate_t, ph) 45 46#define ios_from_ph(ph) containerof(ph, devhost_iostate_t, ph) 47 48static zx_status_t dh_handle_dc_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt); 49 50static port_t dh_port; 51 52typedef struct devhost_iostate iostate_t; 53 54static iostate_t root_ios = []() { 55 iostate_t ios; 56 ios.ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 57 ios.ph.func = dh_handle_dc_rpc; 58 return ios; 59}(); 60 61static fbl::DoublyLinkedList<zx_driver*> dh_drivers; 62 63static const char* mkdevpath(zx_device_t* dev, char* path, size_t max) { 64 if (dev == nullptr) { 65 return ""; 66 } 67 if (max < 1) { 68 return "<invalid>"; 69 } 70 char* end = path + max; 71 char sep = 0; 72 73 while (dev) { 74 *(--end) = sep; 75 76 size_t len = strlen(dev->name); 77 if (len > (size_t)(end - path)) { 78 break; 79 } 80 end -= len; 81 memcpy(end, dev->name, len); 82 sep = '/'; 83 dev = dev->parent; 84 } 85 return end; 86} 87 88static uint32_t logflagval(char* flag) { 89 if (!strcmp(flag, "error")) { 90 return DDK_LOG_ERROR; 91 } 92 if (!strcmp(flag, "warn")) { 93 return DDK_LOG_WARN; 94 } 95 if (!strcmp(flag, "info")) { 96 return DDK_LOG_INFO; 97 } 98 if (!strcmp(flag, "trace")) { 99 return DDK_LOG_TRACE; 100 } 101 if (!strcmp(flag, "spew")) { 102 return DDK_LOG_SPEW; 103 } 104 if (!strcmp(flag, "debug1")) { 105 return DDK_LOG_DEBUG1; 106 } 107 if (!strcmp(flag, "debug2")) { 108 return DDK_LOG_DEBUG2; 109 } 110 if (!strcmp(flag, "debug3")) { 111 return DDK_LOG_DEBUG3; 112 } 113 if (!strcmp(flag, "debug4")) { 114 return DDK_LOG_DEBUG4; 115 } 116 return static_cast<uint32_t>(strtoul(flag, nullptr, 0)); 117} 118 119static void logflag(char* flag, uint32_t* flags) { 120 if (*flag == '+') { 121 *flags |= logflagval(flag + 1); 122 } else if (*flag == '-') { 123 *flags &= ~logflagval(flag + 1); 124 } 125} 126 127static zx_status_t dh_find_driver(const char* libname, zx_handle_t vmo, zx_driver_t** out) { 128 // check for already-loaded driver first 129 for (auto& drv : dh_drivers) { 130 if (!strcmp(libname, drv.libname)) { 131 *out = &drv; 132 zx_handle_close(vmo); 133 return drv.status; 134 } 135 } 136 137 size_t len = strlen(libname) + 1; 138 auto drv = static_cast<zx_driver_t*>(calloc(1, sizeof(zx_driver_t) + len)); 139 if (drv == nullptr) { 140 zx_handle_close(vmo); 141 return ZX_ERR_NO_MEMORY; 142 } 143 new (drv) zx_driver_t; 144 memcpy((void*) (drv + 1), libname, len); 145 drv->libname = (const char*) (drv + 1); 146 dh_drivers.push_back(drv); 147 *out = drv; 148 149 void* dl = dlopen_vmo(vmo, RTLD_NOW); 150 if (dl == nullptr) { 151 log(ERROR, "devhost: cannot load '%s': %s\n", libname, dlerror()); 152 drv->status = ZX_ERR_IO; 153 goto done; 154 } 155 156 const zircon_driver_note_t* dn; 157 dn = static_cast<const zircon_driver_note_t*>(dlsym(dl, "__zircon_driver_note__")); 158 if (dn == nullptr) { 159 log(ERROR, "devhost: driver '%s' missing __zircon_driver_note__ symbol\n", libname); 160 drv->status = ZX_ERR_IO; 161 goto done; 162 } 163 zx_driver_rec_t* dr; 164 dr = static_cast<zx_driver_rec_t*>(dlsym(dl, "__zircon_driver_rec__")); 165 if (dr == nullptr) { 166 log(ERROR, "devhost: driver '%s' missing __zircon_driver_rec__ symbol\n", libname); 167 drv->status = ZX_ERR_IO; 168 goto done; 169 } 170 if (!dr->ops) { 171 log(ERROR, "devhost: driver '%s' has nullptr ops\n", libname); 172 drv->status = ZX_ERR_INVALID_ARGS; 173 goto done; 174 } 175 if (dr->ops->version != DRIVER_OPS_VERSION) { 176 log(ERROR, "devhost: driver '%s' has bad driver ops version %" PRIx64 177 ", expecting %" PRIx64 "\n", libname, 178 dr->ops->version, DRIVER_OPS_VERSION); 179 drv->status = ZX_ERR_INVALID_ARGS; 180 goto done; 181 } 182 183 drv->driver_rec = dr; 184 drv->name = dn->payload.name; 185 drv->ops = dr->ops; 186 dr->driver = drv; 187 188 // check for dprintf log level flags 189 char tmp[128]; 190 snprintf(tmp, sizeof(tmp), "driver.%s.log", drv->name); 191 char* log; 192 log = getenv(tmp); 193 if (log) { 194 while (log) { 195 char* sep = strchr(log, ','); 196 if (sep) { 197 *sep = 0; 198 logflag(log, &dr->log_flags); 199 *sep = ','; 200 log = sep + 1; 201 } else { 202 logflag(log, &dr->log_flags); 203 break; 204 } 205 } 206 log(INFO, "devhost: driver '%s': log flags set to: 0x%x\n", drv->name, dr->log_flags); 207 } 208 209 if (drv->ops->init) { 210 drv->status = drv->ops->init(&drv->ctx); 211 if (drv->status < 0) { 212 log(ERROR, "devhost: driver '%s' failed in init: %d\n", 213 libname, drv->status); 214 } 215 } else { 216 drv->status = ZX_OK; 217 } 218 219done: 220 zx_handle_close(vmo); 221 return drv->status; 222} 223 224static void dh_send_status(zx_handle_t h, zx_status_t status) { 225 dc_msg_t reply = {}; 226 reply.txid = 0; 227 reply.op = dc_msg_t::Op::kStatus; 228 reply.status = status; 229 zx_channel_write(h, 0, &reply, sizeof(reply), nullptr, 0); 230} 231 232static zx_status_t dh_null_reply(fidl_txn_t* reply, const fidl_msg_t* msg) { 233 return ZX_OK; 234} 235 236static fidl_txn_t dh_null_txn = { 237 .reply = dh_null_reply, 238}; 239 240static zx_status_t dh_handle_rpc_read(zx_handle_t h, iostate_t* ios) { 241 dc_msg_t msg; 242 zx_handle_t hin[3]; 243 uint32_t msize = sizeof(msg); 244 uint32_t hcount = 3; 245 246 zx_status_t r; 247 if ((r = zx_channel_read(h, 0, &msg, hin, msize, 248 hcount, &msize, &hcount)) < 0) { 249 return r; 250 } 251 252 char buffer[512]; 253 const char* path = mkdevpath(ios->dev, buffer, sizeof(buffer)); 254 255 if (msize >= sizeof(fidl_message_header_t) && 256 static_cast<uint32_t>(msg.op) == fuchsia_io_DirectoryOpenOrdinal) { 257 log(RPC_RIO, "devhost[%s] FIDL OPEN\n", path); 258 259 fidl_msg_t fidl_msg = { 260 .bytes = &msg, 261 .handles = hin, 262 .num_bytes = msize, 263 .num_handles = hcount, 264 }; 265 266 if ((r = devhost_fidl_handler(&fidl_msg, &dh_null_txn, ios)) != ZX_OK) { 267 log(ERROR, "devhost: OPEN failed: %d\n", r); 268 return r; 269 } 270 271 return ZX_OK; 272 } 273 274 const void* data; 275 const char* name; 276 const char* args; 277 if ((r = dc_msg_unpack(&msg, msize, &data, &name, &args)) < 0) { 278 goto fail; 279 } 280 switch (msg.op) { 281 case dc_msg_t::Op::kCreateDeviceStub: { 282 log(RPC_IN, "devhost[%s] create device stub drv='%s'\n", path, name); 283 if (hcount != 1) { 284 r = ZX_ERR_INVALID_ARGS; 285 goto fail; 286 } 287 iostate_t* newios = static_cast<iostate_t*>(calloc(1, sizeof(iostate_t))); 288 if (newios == nullptr) { 289 r = ZX_ERR_NO_MEMORY; 290 break; 291 } 292 new (newios) iostate_t; 293 294 //TODO: dev->ops and other lifecycle bits 295 // no name means a dummy proxy device 296 if ((newios->dev = static_cast<zx_device_t*>(calloc(1, sizeof(zx_device_t)))) == nullptr) { 297 free(newios); 298 r = ZX_ERR_NO_MEMORY; 299 break; 300 } 301 new (newios->dev) zx_device_t; 302 zx_device_t* dev = newios->dev; 303 strcpy(dev->name, "proxy"); 304 dev->protocol_id = msg.protocol_id; 305 dev->ops = &device_default_ops; 306 dev->rpc = hin[0]; 307 dev->refcount = 1; 308 list_initialize(&dev->children); 309 310 newios->ph.handle = hin[0]; 311 newios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 312 newios->ph.func = dh_handle_dc_rpc; 313 if ((r = port_wait(&dh_port, &newios->ph)) < 0) { 314 free(newios->dev); 315 free(newios); 316 break; 317 } 318 log(RPC_IN, "devhost[%s] created '%s' ios=%p\n", path, name, newios); 319 return ZX_OK; 320 } 321 322 case dc_msg_t::Op::kCreateDevice: { 323 // This does not operate under the devhost api lock, 324 // since the newly created device is not visible to 325 // any API surface until a driver is bound to it. 326 // (which can only happen via another message on this thread) 327 log(RPC_IN, "devhost[%s] create device drv='%s' args='%s'\n", path, name, args); 328 329 // hin: rpc, vmo, optional-rsrc 330 if (hcount == 2) { 331 hin[2] = ZX_HANDLE_INVALID; 332 } else if (hcount != 3) { 333 r = ZX_ERR_INVALID_ARGS; 334 break; 335 } 336 iostate_t* newios = static_cast<iostate_t*>(calloc(1, sizeof(iostate_t))); 337 if (newios == nullptr) { 338 r = ZX_ERR_NO_MEMORY; 339 break; 340 } 341 new (newios) iostate_t; 342 343 // named driver -- ask it to create the device 344 zx_driver_t* drv; 345 if ((r = dh_find_driver(name, hin[1], &drv)) < 0) { 346 free(newios); 347 log(ERROR, "devhost[%s] driver load failed: %d\n", path, r); 348 break; 349 } 350 if (drv->ops->create) { 351 // magic cookie for device create handshake 352 zx_device_t parent = {}; 353 char dummy_name[sizeof(parent.name)] = "device_create dummy"; 354 memcpy(&parent.name, &dummy_name, sizeof(parent.name)); 355 356 creation_context_t ctx = { 357 .parent = &parent, 358 .child = nullptr, 359 .rpc = hin[0], 360 }; 361 devhost_set_creation_context(&ctx); 362 r = drv->ops->create(drv->ctx, &parent, "proxy", args, hin[2]); 363 devhost_set_creation_context(nullptr); 364 365 if (r < 0) { 366 log(ERROR, "devhost[%s] driver create() failed: %d\n", path, r); 367 break; 368 } 369 if ((newios->dev = ctx.child) == nullptr) { 370 log(ERROR, "devhost[%s] driver create() failed to create a device!", path); 371 r = ZX_ERR_BAD_STATE; 372 break; 373 } 374 } else { 375 log(ERROR, "devhost[%s] driver create() not supported\n", path); 376 r = ZX_ERR_NOT_SUPPORTED; 377 break; 378 } 379 //TODO: inform devcoord 380 381 newios->ph.handle = hin[0]; 382 newios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 383 newios->ph.func = dh_handle_dc_rpc; 384 if ((r = port_wait(&dh_port, &newios->ph)) < 0) { 385 free(newios); 386 break; 387 } 388 log(RPC_IN, "devhost[%s] created '%s' ios=%p\n", path, name, newios); 389 return ZX_OK; 390 } 391 392 case dc_msg_t::Op::kBindDriver: 393 if (hcount != 1) { 394 r = ZX_ERR_INVALID_ARGS; 395 break; 396 } 397 //TODO: api lock integration 398 log(RPC_IN, "devhost[%s] bind driver '%s'\n", path, name); 399 zx_driver_t* drv; 400 if (ios->dev->flags & DEV_FLAG_DEAD) { 401 log(ERROR, "devhost[%s] bind to removed device disallowed\n", path); 402 r = ZX_ERR_IO_NOT_PRESENT; 403 } else if ((r = dh_find_driver(name, hin[0], &drv)) < 0) { 404 log(ERROR, "devhost[%s] driver load failed: %d\n", path, r); 405 } else { 406 if (drv->ops->bind) { 407 creation_context_t ctx = { 408 .parent = ios->dev, 409 .child = nullptr, 410 .rpc = ZX_HANDLE_INVALID, 411 }; 412 devhost_set_creation_context(&ctx); 413 r = drv->ops->bind(drv->ctx, ios->dev); 414 devhost_set_creation_context(nullptr); 415 416 if ((r == ZX_OK) && (ctx.child == nullptr)) { 417 printf("devhost: WARNING: driver '%s' did not add device in bind()\n", name); 418 } 419 if (r < 0) { 420 log(ERROR, "devhost[%s] bind driver '%s' failed: %d\n", path, name, r); 421 } 422 } else { 423 if (!drv->ops->create) { 424 log(ERROR, "devhost[%s] neither create nor bind are implemented: '%s'\n", 425 path, name); 426 } 427 r = ZX_ERR_NOT_SUPPORTED; 428 } 429 } 430 dh_send_status(h, r); 431 return ZX_OK; 432 433 case dc_msg_t::Op::kConnectProxy: 434 if (hcount != 1) { 435 r = ZX_ERR_INVALID_ARGS; 436 break; 437 } 438 log(RPC_SDW, "devhost[%s] connect proxy rpc\n", path); 439 ios->dev->ops->rxrpc(ios->dev->ctx, ZX_HANDLE_INVALID); 440 proxy_ios_create(ios->dev, hin[0]); 441 return ZX_OK; 442 443 case dc_msg_t::Op::kSuspend: { 444 if (hcount != 0) { 445 r = ZX_ERR_INVALID_ARGS; 446 break; 447 } 448 // call suspend on the device this devhost is rooted on 449 zx_device_t* device = ios->dev; 450 while (device->parent != nullptr) { 451 device = device->parent; 452 } 453 DM_LOCK(); 454 r = devhost_device_suspend(device, msg.value); 455 DM_UNLOCK(); 456 dh_send_status(h, r); 457 return ZX_OK; 458 } 459 460 case dc_msg_t::Op::kRemoveDevice: 461 if (hcount != 0) { 462 r = ZX_ERR_INVALID_ARGS; 463 break; 464 } 465 device_remove(ios->dev); 466 return ZX_OK; 467 468 default: 469 log(ERROR, "devhost[%s] invalid rpc op %08x\n", path, static_cast<uint32_t>(msg.op)); 470 r = ZX_ERR_NOT_SUPPORTED; 471 } 472 473fail: 474 while (hcount > 0) { 475 zx_handle_close(hin[--hcount]); 476 } 477 return r; 478} 479 480// handles devcoordinator rpc 481static zx_status_t dh_handle_dc_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt) { 482 iostate_t* ios = ios_from_ph(ph); 483 484 if (evt != 0) { 485 // we send an event to request the destruction 486 // of an iostate, to ensure that's the *last* 487 // packet about the iostate that we get 488 free(ios); 489 return ZX_ERR_STOP; 490 } 491 if (ios->dead) { 492 // ports does not let us cancel packets that are 493 // already in the queue, so the dead flag enables us 494 // to ignore them 495 return ZX_ERR_STOP; 496 } 497 if (signals & ZX_CHANNEL_READABLE) { 498 zx_status_t r = dh_handle_rpc_read(ph->handle, ios); 499 if (r != ZX_OK) { 500 log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%d. fatal.\n", ios, r); 501 exit(0); 502 } 503 return r; 504 } 505 if (signals & ZX_CHANNEL_PEER_CLOSED) { 506 log(ERROR, "devhost: devmgr disconnected! fatal. (ios=%p)\n", ios); 507 exit(0); 508 } 509 log(ERROR, "devhost: no work? %08x\n", signals); 510 return ZX_OK; 511} 512 513// handles remoteio rpc 514static zx_status_t dh_handle_fidl_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt) { 515 iostate_t* ios = ios_from_ph(ph); 516 517 zx_status_t r; 518 if (signals & ZX_CHANNEL_READABLE) { 519 if ((r = zxfidl_handler(ph->handle, devhost_fidl_handler, ios)) == ZX_OK) { 520 return ZX_OK; 521 } 522 } else if (signals & ZX_CHANNEL_PEER_CLOSED) { 523 zxfidl_handler(ZX_HANDLE_INVALID, devhost_fidl_handler, ios); 524 r = ZX_ERR_STOP; 525 } else { 526 printf("dh_handle_fidl_rpc: invalid signals %x\n", signals); 527 exit(0); 528 } 529 530 // We arrive here if handle_rpc was a clean close (ERR_DISPATCHER_DONE), 531 // or close-due-to-error (non-ZX_OK), or if the channel was closed 532 // out from under us (ZX_ERR_STOP). In all cases, the ios's reference to 533 // the device was released, and will no longer be used, so we will free 534 // it before returning. 535 zx_handle_close(ios->ph.handle); 536 free(ios); 537 return r; 538} 539 540 541// Handling RPC From Proxy Devices to BusDevs 542 543static zx_status_t dh_handle_proxy_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt) { 544 proxy_iostate_t* ios = proxy_ios_from_ph(ph); 545 546 if (evt != 0) { 547 log(RPC_SDW, "proxy-rpc: destroy (ios=%p)\n", ios); 548 // we send an event to request the destruction 549 // of an iostate, to ensure that's the *last* 550 // packet about the iostate that we get 551 free(ios); 552 return ZX_ERR_STOP; 553 } 554 if (ios->dev == nullptr) { 555 log(RPC_SDW, "proxy-rpc: stale rpc? (ios=%p)\n", ios); 556 // ports does not let us cancel packets that are 557 // already in the queue, so the dead flag enables us 558 // to ignore them 559 return ZX_ERR_STOP; 560 } 561 if (signals & ZX_CHANNEL_READABLE) { 562 log(RPC_SDW, "proxy-rpc: rpc readable (ios=%p,dev=%p)\n", ios, ios->dev); 563 zx_status_t r; 564 r = ios->dev->ops->rxrpc(ios->dev->ctx, ph->handle); 565 if (r != ZX_OK) { 566 log(RPC_SDW, "proxy-rpc: rpc cb error %d (ios=%p,dev=%p)\n", r, ios, ios->dev); 567destroy: 568 ios->dev->proxy_ios = nullptr; 569 zx_handle_close(ios->ph.handle); 570 free(ios); 571 return ZX_ERR_STOP; 572 } 573 return ZX_OK; 574 } 575 if (signals & ZX_CHANNEL_PEER_CLOSED) { 576 log(RPC_SDW, "proxy-rpc: peer closed (ios=%p,dev=%p)\n", ios, ios->dev); 577 goto destroy; 578 } 579 log(ERROR, "devhost: no work? %08x\n", signals); 580 return ZX_OK; 581} 582 583static void proxy_ios_create(zx_device_t* dev, zx_handle_t h) { 584 if (dev->proxy_ios) { 585 proxy_ios_destroy(dev); 586 } 587 588 proxy_iostate_t* ios; 589 if ((ios = static_cast<proxy_iostate_t*>(calloc(sizeof(proxy_iostate_t), 1))) == nullptr) { 590 zx_handle_close(h); 591 return; 592 } 593 new (ios) proxy_iostate_t; 594 595 ios->dev = dev; 596 ios->ph.handle = h; 597 ios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 598 ios->ph.func = dh_handle_proxy_rpc; 599 if (port_wait(&dh_port, &ios->ph) != ZX_OK) { 600 zx_handle_close(h); 601 free(ios); 602 } else { 603 dev->proxy_ios = ios; 604 } 605} 606 607static void proxy_ios_destroy(zx_device_t* dev) { 608 proxy_iostate_t* ios = dev->proxy_ios; 609 if (ios) { 610 dev->proxy_ios = nullptr; 611 612 // mark iostate detached 613 ios->dev = nullptr; 614 615 // cancel any pending waits 616 port_cancel(&dh_port, &ios->ph); 617 618 zx_handle_close(ios->ph.handle); 619 ios->ph.handle = ZX_HANDLE_INVALID; 620 621 // queue an event to destroy the iostate 622 port_queue(&dh_port, &ios->ph, 1); 623 } 624} 625 626 627#define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t)) 628 629static zx_handle_t devhost_log_handle; 630 631static ssize_t _devhost_log_write(uint32_t flags, const void* _data, size_t len) { 632 static thread_local struct Context { 633 uint32_t next; 634 zx_handle_t handle; 635 char data[LOGBUF_MAX]; 636 }* ctx = nullptr; 637 638 if (ctx == nullptr) { 639 if ((ctx = static_cast<decltype(ctx)>(calloc(1, sizeof(*ctx)))) == nullptr) { 640 return len; 641 } 642 new (ctx) Context; 643 ctx->handle = devhost_log_handle; 644 } 645 646 const char* data = static_cast<const char*>(_data); 647 size_t r = len; 648 649 while (len-- > 0) { 650 char c = *data++; 651 if (c == '\n') { 652 if (ctx->next) { 653flush_ctx: 654 zx_debuglog_write(ctx->handle, flags, ctx->data, ctx->next); 655 ctx->next = 0; 656 } 657 continue; 658 } 659 if (c < ' ') { 660 continue; 661 } 662 ctx->data[ctx->next++] = c; 663 if (ctx->next == LOGBUF_MAX) { 664 goto flush_ctx; 665 } 666 } 667 return r; 668} 669 670__EXPORT void driver_printf(uint32_t flags, const char* fmt, ...) { 671 char buffer[512]; 672 va_list ap; 673 va_start(ap, fmt); 674 int r = vsnprintf(buffer, sizeof(buffer), fmt, ap); 675 va_end(ap); 676 677 if (r > (int)sizeof(buffer)) { 678 r = sizeof(buffer); 679 } 680 681 _devhost_log_write(flags, buffer, r); 682} 683 684static ssize_t devhost_log_write(void* cookie, const void* data, size_t len) { 685 return _devhost_log_write(0, data, len); 686} 687 688static void devhost_io_init() { 689 if (zx_debuglog_create(ZX_HANDLE_INVALID, 0, &devhost_log_handle) < 0) { 690 return; 691 } 692 fdio_t* io; 693 if ((io = fdio_output_create(devhost_log_write, nullptr)) == nullptr) { 694 return; 695 } 696 close(1); 697 fdio_bind_to_fd(io, 1, 0); 698 dup2(1, 2); 699} 700 701// Send message to devcoordinator asking to add child device to 702// parent device. Called under devhost api lock. 703zx_status_t devhost_add(zx_device_t* parent, zx_device_t* child, const char* proxy_args, 704 const zx_device_prop_t* props, uint32_t prop_count) { 705 char buffer[512]; 706 const char* path = mkdevpath(parent, buffer, sizeof(buffer)); 707 log(RPC_OUT, "devhost[%s] add '%s'\n", path, child->name); 708 709 const char* libname = child->driver->libname; 710 size_t namelen = strlen(libname) + strlen(child->name) + 2; 711 char name[namelen]; 712 snprintf(name, namelen, "%s,%s", libname, child->name); 713 714 zx_status_t r; 715 iostate_t* ios = static_cast<iostate_t*>(calloc(1, sizeof(*ios))); 716 if (ios == nullptr) { 717 r = ZX_ERR_NO_MEMORY; 718 goto fail; 719 } 720 new (ios) iostate_t; 721 722 dc_msg_t msg; 723 uint32_t msglen; 724 if ((r = dc_msg_pack(&msg, &msglen, 725 props, prop_count * sizeof(zx_device_prop_t), 726 name, proxy_args)) < 0) { 727 goto fail; 728 } 729 msg.op = (child->flags & DEV_FLAG_INVISIBLE) ? 730 dc_msg_t::Op::kAddDeviceInvisible : dc_msg_t::Op::kAddDevice; 731 msg.protocol_id = child->protocol_id; 732 733 // handles: remote endpoint, resource (optional) 734 zx_handle_t hrpc, hsend; 735 if ((r = zx_channel_create(0, &hrpc, &hsend)) < 0) { 736 goto fail; 737 } 738 739 dc_status_t rsp; 740 if ((r = dc_msg_rpc(parent->rpc, &msg, msglen, &hsend, 1, &rsp, sizeof(rsp), nullptr, nullptr)) < 0) { 741 log(ERROR, "devhost[%s] add '%s': rpc failed: %d\n", path, child->name, r); 742 } else { 743 ios->dev = child; 744 ios->ph.handle = hrpc; 745 ios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 746 ios->ph.func = dh_handle_dc_rpc; 747 if ((r = port_wait(&dh_port, &ios->ph)) == ZX_OK) { 748 child->rpc = hrpc; 749 child->ios = ios; 750 return ZX_OK; 751 } 752 753 } 754 zx_handle_close(hrpc); 755 free(ios); 756 return r; 757 758fail: 759 free(ios); 760 return r; 761} 762 763static zx_status_t devhost_rpc_etc(zx_device_t* dev, dc_msg_t::Op op, 764 const char* args, const char* opname, 765 uint32_t value, const void* data, size_t datalen, 766 dc_status_t* rsp, size_t rsp_len, size_t* actual, 767 zx_handle_t* outhandle) { 768 char buffer[512]; 769 const char* path = mkdevpath(dev, buffer, sizeof(buffer)); 770 log(RPC_OUT, "devhost[%s] %s args='%s'\n", path, opname, args ? args : ""); 771 dc_msg_t msg; 772 uint32_t msglen; 773 zx_status_t r; 774 if ((r = dc_msg_pack(&msg, &msglen, data, datalen, nullptr, args)) < 0) { 775 return r; 776 } 777 msg.op = op; 778 msg.value = value; 779 if ((r = dc_msg_rpc(dev->rpc, &msg, msglen, nullptr, 0, rsp, rsp_len, actual, outhandle)) < 0) { 780 if (!(op == dc_msg_t::Op::kGetMetadata && r == ZX_ERR_NOT_FOUND)) { 781 log(ERROR, "devhost: rpc:%s failed: %d\n", opname, r); 782 } 783 } 784 return r; 785} 786 787static zx_status_t devhost_rpc(zx_device_t* dev, dc_msg_t::Op op, 788 const char* args, const char* opname, 789 dc_status_t* rsp, size_t rsp_len, 790 zx_handle_t* outhandle) { 791 return devhost_rpc_etc(dev, op, args, opname, 0, nullptr, 0, rsp, rsp_len, nullptr, outhandle); 792} 793 794void devhost_make_visible(zx_device_t* dev) { 795 dc_status_t rsp; 796 devhost_rpc(dev, dc_msg_t::Op::kMakeVisible, nullptr, "make-visible", &rsp, 797 sizeof(rsp), nullptr); 798} 799 800// Send message to devcoordinator informing it that this device 801// is being removed. Called under devhost api lock. 802zx_status_t devhost_remove(zx_device_t* dev) { 803 devhost_iostate_t* ios = static_cast<devhost_iostate_t*>(dev->ios); 804 if (ios == nullptr) { 805 log(ERROR, "removing device %p, ios is nullptr\n", dev); 806 return ZX_ERR_INTERNAL; 807 } 808 809 log(DEVLC, "removing device %p, ios %p\n", dev, ios); 810 811 // Make this iostate inactive (stop accepting RPCs for it) 812 // 813 // If the remove is happening on a different thread than 814 // the rpc handler, the handler might observe the peer 815 // before devhost_simple_rpc() returns. 816 ios->dev = nullptr; 817 ios->dead = true; 818 819 // ensure we get no further events 820 //TODO: this does not work yet, ports limitation 821 port_cancel(&dh_port, &ios->ph); 822 ios->ph.handle = ZX_HANDLE_INVALID; 823 dev->ios = nullptr; 824 825 dc_status_t rsp; 826 devhost_rpc(dev, dc_msg_t::Op::kRemoveDevice, nullptr, "remove-device", &rsp, 827 sizeof(rsp), nullptr); 828 829 // shut down our rpc channel 830 zx_handle_close(dev->rpc); 831 dev->rpc = ZX_HANDLE_INVALID; 832 833 // queue an event to destroy the iostate 834 port_queue(&dh_port, &ios->ph, 1); 835 836 // shut down our proxy rpc channel if it exists 837 proxy_ios_destroy(dev); 838 839 return ZX_OK; 840} 841 842zx_status_t devhost_get_topo_path(zx_device_t* dev, char* path, size_t max, size_t* actual) { 843 zx_device_t* remote_dev = dev; 844 if (dev->flags & DEV_FLAG_INSTANCE) { 845 // Instances cannot be opened a second time. If dev represents an instance, return the path 846 // to its parent, prefixed with an '@'. 847 if (max < 1) { 848 return ZX_ERR_BUFFER_TOO_SMALL; 849 } 850 path[0] = '@'; 851 path++; 852 max--; 853 remote_dev = dev->parent; 854 } 855 856 struct { 857 dc_status_t rsp; 858 char path[DC_PATH_MAX]; 859 } reply; 860 zx_status_t r; 861 if ((r = devhost_rpc(remote_dev, dc_msg_t::Op::kGetTopoPath, nullptr, "get-topo-path", 862 &reply.rsp, sizeof(reply), nullptr)) < 0) { 863 return r; 864 } 865 reply.path[DC_PATH_MAX - 1] = 0; 866 size_t len = strlen(reply.path) + 1; 867 if (len > max) { 868 return ZX_ERR_BUFFER_TOO_SMALL; 869 } 870 871 memcpy(path, reply.path, len); 872 *actual = len; 873 if (dev->flags & DEV_FLAG_INSTANCE) *actual += 1; 874 return ZX_OK; 875} 876 877zx_status_t devhost_device_bind(zx_device_t* dev, const char* drv_libname) { 878 dc_status_t rsp; 879 return devhost_rpc(dev, dc_msg_t::Op::kBindDevice, drv_libname, 880 "bind-device", &rsp, sizeof(rsp), nullptr); 881} 882 883zx_status_t devhost_load_firmware(zx_device_t* dev, const char* path, 884 zx_handle_t* vmo, size_t* size) { 885 if ((vmo == nullptr) || (size == nullptr)) { 886 return ZX_ERR_INVALID_ARGS; 887 } 888 889 struct { 890 dc_status_t rsp; 891 size_t size; 892 } reply; 893 zx_status_t r; 894 if ((r = devhost_rpc(dev, dc_msg_t::Op::kLoadFirmware, path, "load-firmware", 895 &reply.rsp, sizeof(reply), vmo)) < 0) { 896 return r; 897 } 898 if (*vmo == ZX_HANDLE_INVALID) { 899 return ZX_ERR_INTERNAL; 900 } 901 *size = reply.size; 902 return ZX_OK; 903} 904 905zx_status_t devhost_get_metadata(zx_device_t* dev, uint32_t type, void* buf, size_t buflen, 906 size_t* actual) { 907 if (!buf) { 908 return ZX_ERR_INVALID_ARGS; 909 } 910 911 struct { 912 dc_status_t rsp; 913 uint8_t data[DC_MAX_DATA]; 914 } reply; 915 zx_status_t r; 916 size_t resp_actual = 0; 917 if ((r = devhost_rpc_etc(dev, dc_msg_t::Op::kGetMetadata, nullptr, "get-metadata", type, 918 nullptr, 0, &reply.rsp, sizeof(reply), &resp_actual, nullptr)) < 0) { 919 return r; 920 } 921 if (resp_actual < sizeof(reply.rsp)) { 922 return ZX_ERR_INTERNAL; 923 } 924 resp_actual -= sizeof(reply.rsp); 925 if (resp_actual > buflen) { 926 return ZX_ERR_BUFFER_TOO_SMALL; 927 } 928 memcpy(buf, reply.data, resp_actual); 929 if (actual) { 930 *actual = resp_actual; 931 } 932 933 return ZX_OK; 934} 935 936zx_status_t devhost_add_metadata(zx_device_t* dev, uint32_t type, const void* data, 937 size_t length) { 938 dc_status_t rsp; 939 940 if (!data && length) { 941 return ZX_ERR_INVALID_ARGS; 942 } 943 return devhost_rpc_etc(dev, dc_msg_t::Op::kAddMetadata, nullptr, "add-metadata", type, data, 944 length, &rsp, sizeof(rsp), nullptr, nullptr); 945} 946 947zx_status_t devhost_publish_metadata(zx_device_t* dev, const char* path, uint32_t type, 948 const void* data, size_t length) { 949 dc_status_t rsp; 950 951 if (!path || (!data && length)) { 952 return ZX_ERR_INVALID_ARGS; 953 } 954 return devhost_rpc_etc(dev, dc_msg_t::Op::kPublishMetadata, path, "publish-metadata", type, 955 data, length, &rsp, sizeof(rsp), nullptr, nullptr); 956} 957 958zx_handle_t root_resource_handle; 959 960 961zx_status_t devhost_start_iostate(devhost_iostate_t* ios, zx_handle_t h) { 962 ios->ph.handle = h; 963 ios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 964 ios->ph.func = dh_handle_fidl_rpc; 965 return port_wait(&dh_port, &ios->ph); 966} 967 968__EXPORT int device_host_main(int argc, char** argv) { 969 devhost_io_init(); 970 971 log(TRACE, "devhost: main()\n"); 972 973 root_ios.ph.handle = zx_take_startup_handle(PA_HND(PA_USER0, 0)); 974 if (root_ios.ph.handle == ZX_HANDLE_INVALID) { 975 log(ERROR, "devhost: rpc handle invalid\n"); 976 return -1; 977 } 978 979 root_resource_handle = zx_take_startup_handle(PA_HND(PA_RESOURCE, 0)); 980 if (root_resource_handle == ZX_HANDLE_INVALID) { 981 log(ERROR, "devhost: no root resource handle!\n"); 982 } 983 984 zx_status_t r; 985 if ((r = port_init(&dh_port)) < 0) { 986 log(ERROR, "devhost: could not create port: %d\n", r); 987 return -1; 988 } 989 if ((r = port_wait(&dh_port, &root_ios.ph)) < 0) { 990 log(ERROR, "devhost: could not watch rpc channel: %d\n", r); 991 return -1; 992 } 993 994 r = port_dispatch(&dh_port, ZX_TIME_INFINITE, false); 995 log(ERROR, "devhost: port dispatch finished: %d\n", r); 996 997 return 0; 998} 999