// Copyright 2018 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.

#include <ldmsg/ldmsg.h>

#include <string.h>

static_assert(sizeof(ldmsg_req_t) == 1024,
              "Loader service requests can be at most 1024 bytes.");

static uint64_t FidlAlign(uint32_t offset) {
    const uint64_t alignment_mask = FIDL_ALIGNMENT - 1;
    return (offset + alignment_mask) & ~alignment_mask;
}

zx_status_t ldmsg_req_encode(ldmsg_req_t* req, size_t* req_len_out,
                             const char* data, size_t len) {
    size_t offset = 0;
    switch (req->header.ordinal) {
    case LDMSG_OP_DONE:
    case LDMSG_OP_DONE_OLD:
        *req_len_out = sizeof(fidl_message_header_t);
        return ZX_OK;
    case LDMSG_OP_CLONE:
    case LDMSG_OP_CLONE_OLD:
        *req_len_out = sizeof(fidl_message_header_t) + sizeof(ldmsg_clone_t);
        req->clone.object = FIDL_HANDLE_PRESENT;
        return ZX_OK;
    case LDMSG_OP_LOAD_OBJECT:
    case LDMSG_OP_LOAD_SCRIPT_INTERPRETER:
    case LDMSG_OP_CONFIG:
    case LDMSG_OP_DEBUG_LOAD_CONFIG:
    case LDMSG_OP_LOAD_OBJECT_OLD:
    case LDMSG_OP_LOAD_SCRIPT_INTERPRETER_OLD:
    case LDMSG_OP_CONFIG_OLD:
    case LDMSG_OP_DEBUG_LOAD_CONFIG_OLD:
        offset = sizeof(fidl_string_t);
        break;
    case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK:
    case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK_OLD:
        req->common.object = FIDL_HANDLE_PRESENT;
        offset = sizeof(ldmsg_common_t);
        break;
    default:
        return ZX_ERR_INVALID_ARGS;
    }

    // Reserve one byte for the null terminator on the receiving side.
    if (LDMSG_MAX_PAYLOAD - offset - 1 < len)
        return ZX_ERR_OUT_OF_RANGE;

    req->common.string.size = len;
    req->common.string.data = (char*) FIDL_ALLOC_PRESENT;
    memcpy(req->data + offset, data, len);

    *req_len_out = FidlAlign(sizeof(fidl_message_header_t) + offset + len);
    return ZX_OK;
}

zx_status_t ldmsg_req_decode(ldmsg_req_t* req, size_t req_len,
                             const char** data_out, size_t* len_out) {
    size_t offset = 0;
    switch (req->header.ordinal) {
    case LDMSG_OP_DONE:
    case LDMSG_OP_DONE_OLD:
        if (req_len != sizeof(fidl_message_header_t))
            return ZX_ERR_INVALID_ARGS;
        *data_out = 0;
        *len_out = 0;
        return ZX_OK;
    case LDMSG_OP_CLONE:
    case LDMSG_OP_CLONE_OLD:
        if (req_len != sizeof(fidl_message_header_t) + sizeof(ldmsg_clone_t)
            || req->clone.object != FIDL_HANDLE_PRESENT)
            return ZX_ERR_INVALID_ARGS;
        *data_out = 0;
        *len_out = 0;
        return ZX_OK;
    case LDMSG_OP_LOAD_OBJECT:
    case LDMSG_OP_LOAD_SCRIPT_INTERPRETER:
    case LDMSG_OP_CONFIG:
    case LDMSG_OP_DEBUG_LOAD_CONFIG:
    case LDMSG_OP_LOAD_OBJECT_OLD:
    case LDMSG_OP_LOAD_SCRIPT_INTERPRETER_OLD:
    case LDMSG_OP_CONFIG_OLD:
    case LDMSG_OP_DEBUG_LOAD_CONFIG_OLD:

        if ((uintptr_t)req->common.string.data != FIDL_ALLOC_PRESENT)
            return ZX_ERR_INVALID_ARGS;
        offset = sizeof(fidl_string_t);
        break;
    case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK:
    case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK_OLD:
        if ((uintptr_t)req->common.string.data != FIDL_ALLOC_PRESENT
            || req->common.object != FIDL_HANDLE_PRESENT)
            return ZX_ERR_INVALID_ARGS;
        offset = sizeof(ldmsg_common_t);
        break;
    default:
        return ZX_ERR_INVALID_ARGS;
    }

    size_t size = req->common.string.size;
    if (LDMSG_MAX_PAYLOAD - offset - 1 < size
        || req_len != FidlAlign(sizeof(fidl_message_header_t) + offset + size))
        return ZX_ERR_INVALID_ARGS;

    // Null terminate the string. The message isn't required to have a null
    // terminated string, but we have enough space in our buffer for the null
    // terminator and adding it makes life easier for our caller.
    req->data[offset + size] = '\0';

    *data_out = req->data + offset;
    *len_out = size;
    return ZX_OK;
}

size_t ldmsg_rsp_get_size(ldmsg_rsp_t* rsp) {
    switch (rsp->header.ordinal) {
    case LDMSG_OP_LOAD_OBJECT:
    case LDMSG_OP_LOAD_SCRIPT_INTERPRETER:
    case LDMSG_OP_DEBUG_LOAD_CONFIG:
    case LDMSG_OP_LOAD_OBJECT_OLD:
    case LDMSG_OP_LOAD_SCRIPT_INTERPRETER_OLD:
    case LDMSG_OP_DEBUG_LOAD_CONFIG_OLD:
    case LDMSG_OP_CONFIG:
    case LDMSG_OP_CLONE:
    case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK:
    case LDMSG_OP_CONFIG_OLD:
    case LDMSG_OP_CLONE_OLD:
    case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK_OLD:
        return sizeof(ldmsg_rsp_t);
    case LDMSG_OP_DONE:
    case LDMSG_OP_DONE_OLD:
    default:
        return 0;
    }
}
