// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Code shared between devhost and devmgr #include #include #include #include #include #include #include "devcoordinator.h" zx_status_t dc_msg_pack(dc_msg_t* msg, uint32_t* len_out, const void* data, size_t datalen, const char* name, const char* args) { size_t max = DC_MAX_DATA; uint8_t* ptr = msg->data; if (data) { if (datalen > max) { return ZX_ERR_BUFFER_TOO_SMALL; } memcpy(ptr, data, datalen); max -= datalen; ptr += datalen; msg->datalen = static_cast(datalen); } else { msg->datalen = 0; } if (name) { datalen = strlen(name) + 1; if (datalen > max) { return ZX_ERR_BUFFER_TOO_SMALL; } memcpy(ptr, name, datalen); max -= datalen; ptr += datalen; msg->namelen = static_cast(datalen); } else { msg->namelen = 0; } if (args) { datalen = strlen(args) + 1; if (datalen > max) { return ZX_ERR_BUFFER_TOO_SMALL; } memcpy(ptr, args, datalen); ptr += datalen; msg->argslen = static_cast(datalen); } else { msg->argslen = 0; } *len_out = static_cast(sizeof(dc_msg_t) - DC_MAX_DATA + (ptr - msg->data)); return ZX_OK; } zx_status_t dc_msg_unpack(dc_msg_t* msg, size_t len, const void** data, const char** name, const char** args) { if (len < (sizeof(dc_msg_t) - DC_MAX_DATA)) { return ZX_ERR_BUFFER_TOO_SMALL; } len -= sizeof(dc_msg_t); uint8_t* ptr = msg->data; if (msg->datalen) { if (msg->datalen > len) { return ZX_ERR_BUFFER_TOO_SMALL; } *data = ptr; ptr += msg->datalen; len -= msg->datalen; } else { *data = nullptr; } if (msg->namelen) { if (msg->namelen > len) { return ZX_ERR_BUFFER_TOO_SMALL; } *name = (char*) ptr; ptr[msg->namelen - 1] = 0; ptr += msg->namelen; len -= msg->namelen; } else { *name = ""; } if (msg->argslen) { if (msg->argslen > len) { return ZX_ERR_BUFFER_TOO_SMALL; } *args = (char*) ptr; ptr[msg->argslen - 1] = 0; } else { *args = ""; } return ZX_OK; } zx_status_t dc_msg_rpc(zx_handle_t h, dc_msg_t* msg, size_t msglen, zx_handle_t* handles, size_t hcount, dc_status_t* rsp, size_t rsplen, size_t* resp_actual, zx_handle_t* outhandle) { zx_channel_call_args_t args = { .wr_bytes = msg, .wr_handles = handles, .rd_bytes = rsp, .rd_handles = outhandle, .wr_num_bytes = static_cast(msglen), .wr_num_handles = static_cast(hcount), .rd_num_bytes = static_cast(rsplen), .rd_num_handles = outhandle ? 1u : 0u, }; if (outhandle) { *outhandle = ZX_HANDLE_INVALID; } //TODO: incrementing txids msg->txid = 1; zx_status_t r; if ((r = zx_channel_call(h, 0, ZX_TIME_INFINITE, &args, &args.rd_num_bytes, &args.rd_num_handles)) < 0) { return r; } if (args.rd_num_bytes < sizeof(dc_status_t)) { return ZX_ERR_INTERNAL; } if (resp_actual) { *resp_actual = args.rd_num_bytes; } return rsp->status; }