// 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 "optee-message.h"

#include <ddk/debug.h>
#include <endian.h>
#include <limits>
#include <string.h>

namespace optee {

namespace {

// Converts a big endian UUID from a MessageParam value to a host endian TEEC_UUID.
// The fields of a UUID are stored in big endian in a MessageParam by the TEE and is thus why the
// parameter value cannot be directly reinterpreted as a UUID.
void ConvertMessageParamToUuid(const MessageParam::Value& src, TEEC_UUID* dst) {
    // Convert TEEC_UUID fields from big endian to host endian
    dst->timeLow = betoh32(src.uuid_big_endian.timeLow);
    dst->timeMid = betoh16(src.uuid_big_endian.timeMid);
    dst->timeHiAndVersion = betoh16(src.uuid_big_endian.timeHiAndVersion);

    // Because clockSeqAndNode is uint8_t, no need to convert endianness - just memcpy
    memcpy(dst->clockSeqAndNode,
           src.uuid_big_endian.clockSeqAndNode,
           sizeof(src.uuid_big_endian.clockSeqAndNode));
}

constexpr bool IsParameterInput(fuchsia_tee_Direction direction) {
    return (direction == fuchsia_tee_Direction_INPUT) ||
           (direction == fuchsia_tee_Direction_INOUT);
}

constexpr bool IsParameterOutput(fuchsia_tee_Direction direction) {
    return (direction == fuchsia_tee_Direction_OUTPUT) ||
           (direction == fuchsia_tee_Direction_INOUT);
}

} // namespace

bool Message::TryInitializeParameters(size_t starting_param_index,
                                      const fuchsia_tee_ParameterSet& parameter_set,
                                      SharedMemoryManager::ClientMemoryPool* temp_memory_pool) {
    // If we don't have any parameters to parse, then we can just skip this
    if (parameter_set.count == 0) {
        return true;
    }

    bool is_valid = true;
    for (size_t i = 0; i < parameter_set.count; i++) {
        MessageParam& optee_param = params()[starting_param_index + i];
        const fuchsia_tee_Parameter& zx_param = parameter_set.parameters[i];

        switch (zx_param.tag) {
        case fuchsia_tee_ParameterTag_empty:
            optee_param.attribute = MessageParam::kAttributeTypeNone;
            break;
        case fuchsia_tee_ParameterTag_value:
            is_valid = TryInitializeValue(zx_param.value, &optee_param);
            break;
        case fuchsia_tee_ParameterTag_buffer:
            is_valid = TryInitializeBuffer(zx_param.buffer, temp_memory_pool, &optee_param);
            break;
        default:
            return false;
        }

        if (!is_valid) {
            zxlogf(ERROR, "optee: failed to initialize parameters\n");
            return false;
        }
    }

    return true;
}

bool Message::TryInitializeValue(const fuchsia_tee_Value& value, MessageParam* out_param) {
    ZX_DEBUG_ASSERT(out_param != nullptr);

    switch (value.direction) {
    case fuchsia_tee_Direction_INPUT:
        out_param->attribute = MessageParam::kAttributeTypeValueInput;
        break;
    case fuchsia_tee_Direction_OUTPUT:
        out_param->attribute = MessageParam::kAttributeTypeValueOutput;
        break;
    case fuchsia_tee_Direction_INOUT:
        out_param->attribute = MessageParam::kAttributeTypeValueInOut;
        break;
    default:
        return false;
    }
    out_param->payload.value.generic.a = value.a;
    out_param->payload.value.generic.b = value.b;
    out_param->payload.value.generic.c = value.c;

    return true;
}

bool Message::TryInitializeBuffer(const fuchsia_tee_Buffer& buffer,
                                  SharedMemoryManager::ClientMemoryPool* temp_memory_pool,
                                  MessageParam* out_param) {
    ZX_DEBUG_ASSERT(temp_memory_pool != nullptr);
    ZX_DEBUG_ASSERT(out_param != nullptr);

    // Take ownership of the provided VMO. If we have to return early for any reason, this will
    // take care of closing the VMO.
    zx::vmo vmo(buffer.vmo);

    MessageParam::AttributeType attribute;
    switch (buffer.direction) {
    case fuchsia_tee_Direction_INPUT:
        attribute = MessageParam::kAttributeTypeTempMemInput;
        break;
    case fuchsia_tee_Direction_OUTPUT:
        attribute = MessageParam::kAttributeTypeTempMemOutput;
        break;
    case fuchsia_tee_Direction_INOUT:
        attribute = MessageParam::kAttributeTypeTempMemInOut;
        break;
    default:
        return false;
    }

    // If an invalid VMO was provided, but the buffer is only an output, this is just a size check.
    if (!vmo.is_valid()) {
        if (IsParameterInput(buffer.direction)) {
            return false;
        } else {
            // No need to allocate a temporary buffer from the shared memory pool,
            out_param->attribute = attribute;
            out_param->payload.temporary_memory.buffer = 0;
            out_param->payload.temporary_memory.size = buffer.size;
            out_param->payload.temporary_memory.shared_memory_reference = 0;
            return true;
        }
    }

    // For most buffer types, we must allocate a temporary shared memory buffer within the physical
    // pool to share it with the TEE. We'll attach them to the Message object so that they can be
    // looked up upon return from TEE and to tie the lifetimes of the Message and the temporary
    // shared memory together.
    SharedMemoryPtr shared_mem;
    if (temp_memory_pool->Allocate(buffer.size, &shared_mem) != ZX_OK) {
        zxlogf(ERROR, "optee: Failed to allocate temporary shared memory (%" PRIu64 ")\n",
               buffer.size);
        return false;
    }

    uint64_t paddr = static_cast<uint64_t>(shared_mem->paddr());

    TemporarySharedMemory temp_shared_mem{std::move(vmo), buffer.offset, buffer.size,
                                          std::move(shared_mem)};

    // Input buffers should be copied into the shared memory buffer. Output only buffers can skip
    // this step.
    if (IsParameterInput(buffer.direction)) {
        zx_status_t status = temp_shared_mem.SyncToSharedMemory();
        if (status != ZX_OK) {
            zxlogf(ERROR, "optee: shared memory sync failed (%d)\n", status);
            return false;
        }
    }

    allocated_temp_memory_.push_back(std::move(temp_shared_mem));
    uint64_t index = static_cast<uint64_t>(allocated_temp_memory_.size()) - 1;

    out_param->attribute = attribute;
    out_param->payload.temporary_memory.buffer = paddr;
    out_param->payload.temporary_memory.size = buffer.size;
    out_param->payload.temporary_memory.shared_memory_reference = index;
    return true;
}

zx_status_t
Message::CreateOutputParameterSet(size_t starting_param_index,
                                  fuchsia_tee_ParameterSet* out_parameter_set) {
    ZX_DEBUG_ASSERT(out_parameter_set != nullptr);

    // Use a temporary parameter set to avoid populating the output until we're sure it's valid.
    fuchsia_tee_ParameterSet parameter_set = {};

    // Below code assumes that we can fit all of the parameters from optee into the FIDL parameter
    // set. This static assert ensures that the FIDL parameter set can always fit the number of
    // parameters into the count.
    static_assert(fbl::count_of(parameter_set.parameters) <=
                      std::numeric_limits<decltype(parameter_set.count)>::max(),
                  "The size of the tee parameter set has outgrown the count");

    if (header()->num_params < starting_param_index) {
        zxlogf(ERROR, "optee: Message contained fewer parameters (%" PRIu32 ") than required %zd\n",
               header()->num_params, starting_param_index);
        return ZX_ERR_INVALID_ARGS;
    }

    // Ensure that the number of parameters returned by the TEE does not exceed the parameter set
    // array of parameters.
    const size_t count = header()->num_params - starting_param_index;
    if (count > fbl::count_of(parameter_set.parameters)) {
        zxlogf(ERROR, "optee: Message contained more parameters (%zd) than allowed\n", count);
        return ZX_ERR_INVALID_ARGS;
    }

    parameter_set.count = static_cast<uint16_t>(count);
    for (size_t i = starting_param_index; i < header()->num_params; i++) {
        const MessageParam& optee_param = params()[i];
        fuchsia_tee_Parameter& zx_param = parameter_set.parameters[i];

        switch (optee_param.attribute) {
        case MessageParam::kAttributeTypeNone:
            zx_param.tag = fuchsia_tee_ParameterTag_empty;
            zx_param.empty = {};
            break;
        case MessageParam::kAttributeTypeValueInput:
        case MessageParam::kAttributeTypeValueOutput:
        case MessageParam::kAttributeTypeValueInOut:
            zx_param.tag = fuchsia_tee_ParameterTag_value;
            zx_param.value = CreateOutputValueParameter(optee_param);
            break;
        case MessageParam::kAttributeTypeTempMemInput:
        case MessageParam::kAttributeTypeTempMemOutput:
        case MessageParam::kAttributeTypeTempMemInOut:
            zx_param.tag = fuchsia_tee_ParameterTag_buffer;
            if (zx_status_t status = CreateOutputBufferParameter(optee_param, &zx_param.buffer);
                status != ZX_OK) {
                return status;
            }
            break;
        case MessageParam::kAttributeTypeRegMemInput:
        case MessageParam::kAttributeTypeRegMemOutput:
        case MessageParam::kAttributeTypeRegMemInOut:
        default:
            break;
        }
    }

    *out_parameter_set = parameter_set;
    return ZX_OK;
}

fuchsia_tee_Value Message::CreateOutputValueParameter(const MessageParam& optee_param) {
    fuchsia_tee_Value zx_value = {};

    switch (optee_param.attribute) {
    case MessageParam::kAttributeTypeValueInput:
        zx_value.direction = fuchsia_tee_Direction_INPUT;
        break;
    case MessageParam::kAttributeTypeValueOutput:
        zx_value.direction = fuchsia_tee_Direction_OUTPUT;
        break;
    case MessageParam::kAttributeTypeValueInOut:
        zx_value.direction = fuchsia_tee_Direction_INOUT;
        break;
    default:
        ZX_PANIC("Invalid OP-TEE attribute specified\n");
    }

    const MessageParam::Value& optee_value = optee_param.payload.value;

    if (IsParameterOutput(zx_value.direction)) {
        zx_value.a = optee_value.generic.a;
        zx_value.b = optee_value.generic.b;
        zx_value.c = optee_value.generic.c;
    }
    return zx_value;
}

zx_status_t Message::CreateOutputBufferParameter(const MessageParam& optee_param,
                                                 fuchsia_tee_Buffer* out_buffer) {
    ZX_DEBUG_ASSERT(out_buffer != nullptr);

    // Use a temporary buffer to avoid populating the output until we're sure it's valid.
    fuchsia_tee_Buffer zx_buffer = {};

    switch (optee_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput:
        zx_buffer.direction = fuchsia_tee_Direction_INPUT;
        break;
    case MessageParam::kAttributeTypeTempMemOutput:
        zx_buffer.direction = fuchsia_tee_Direction_OUTPUT;
        break;
    case MessageParam::kAttributeTypeTempMemInOut:
        zx_buffer.direction = fuchsia_tee_Direction_INOUT;
        break;
    default:
        ZX_PANIC("Invalid OP-TEE attribute specified\n");
    }

    const MessageParam::TemporaryMemory& optee_temp_mem = optee_param.payload.temporary_memory;

    zx_buffer.size = optee_temp_mem.size;

    if (optee_temp_mem.buffer == 0) {
        // If there was no buffer and this was just a size check, just return the size.
        *out_buffer = zx_buffer;
        return ZX_OK;
    }

    if (optee_temp_mem.shared_memory_reference >= allocated_temp_memory_.size()) {
        zxlogf(ERROR, "optee: TEE returned an invalid shared_memory_reference (%" PRIu64 ")\n",
               optee_temp_mem.shared_memory_reference);
        return ZX_ERR_INVALID_ARGS;
    }

    auto& temp_shared_memory = allocated_temp_memory_[optee_temp_mem.shared_memory_reference];

    if (!temp_shared_memory.is_valid()) {
        zxlogf(ERROR, "optee: Invalid TemporarySharedMemory attempted to be used\n");
        return ZX_ERR_INVALID_ARGS;
    }

    // For output buffers, we need to sync the shared memory buffer back to the VMO. It's possible
    // that the returned size is smaller or larger than the originally provided buffer.
    if (IsParameterOutput(zx_buffer.direction)) {
        if (zx_status_t status = temp_shared_memory.SyncToVmo(zx_buffer.size); status != ZX_OK) {
            zxlogf(ERROR, "optee: SharedMemory writeback to vmo failed (%d)\n", status);
            return status;
        }
    }

    zx_buffer.vmo = temp_shared_memory.ReleaseVmo();
    zx_buffer.offset = temp_shared_memory.vmo_offset();

    *out_buffer = zx_buffer;

    return ZX_OK;
}

Message::TemporarySharedMemory::TemporarySharedMemory(zx::vmo vmo, uint64_t vmo_offset, size_t size,
                                                      fbl::unique_ptr<SharedMemory> shared_memory)
    : vmo_(std::move(vmo)), vmo_offset_(vmo_offset), size_(size),
      shared_memory_(std::move(shared_memory)) {}

zx_status_t Message::TemporarySharedMemory::SyncToSharedMemory() {
    ZX_DEBUG_ASSERT(is_valid());
    return vmo_.read(reinterpret_cast<void*>(shared_memory_->vaddr()), vmo_offset_, size_);
}

zx_status_t Message::TemporarySharedMemory::SyncToVmo(size_t actual_size) {
    ZX_DEBUG_ASSERT(is_valid());
    // If the actual size of the data is larger than the size of the vmo, then we should skip the
    // actual write. This is a valid scenario and the Trusted World will be responsible for
    // providing the short buffer error code in it's result.
    if (actual_size > size_) {
        return ZX_OK;
    }
    return vmo_.write(reinterpret_cast<void*>(shared_memory_->vaddr()), vmo_offset_, actual_size);
}

zx_handle_t Message::TemporarySharedMemory::ReleaseVmo() {
    return vmo_.release();
}

OpenSessionMessage::OpenSessionMessage(SharedMemoryManager::DriverMemoryPool* message_pool,
                                       SharedMemoryManager::ClientMemoryPool* temp_memory_pool,
                                       const Uuid& trusted_app,
                                       const fuchsia_tee_ParameterSet& parameter_set) {
    ZX_DEBUG_ASSERT(message_pool != nullptr);

    const size_t num_params = parameter_set.count + kNumFixedOpenSessionParams;
    ZX_DEBUG_ASSERT(num_params <= std::numeric_limits<uint32_t>::max());

    zx_status_t status = message_pool->Allocate(CalculateSize(num_params), &memory_);

    if (status != ZX_OK) {
        memory_ = nullptr;
        return;
    }

    header()->command = Command::kOpenSession;
    header()->cancel_id = 0;
    header()->num_params = static_cast<uint32_t>(num_params);

    MessageParam& trusted_app_param = params()[kTrustedAppParamIndex];
    MessageParam& client_app_param = params()[kClientAppParamIndex];

    trusted_app_param.attribute = MessageParam::kAttributeTypeMeta |
                                  MessageParam::kAttributeTypeValueInput;
    trusted_app.ToUint64Pair(&trusted_app_param.payload.value.generic.a,
                             &trusted_app_param.payload.value.generic.b);

    client_app_param.attribute = MessageParam::kAttributeTypeMeta |
                                 MessageParam::kAttributeTypeValueInput;
    // Not really any need to provide client app uuid, so just fill in with 0s
    client_app_param.payload.value.generic.a = 0;
    client_app_param.payload.value.generic.b = 0;
    client_app_param.payload.value.generic.c = TEEC_LOGIN_PUBLIC;

    // If we fail to initialize the parameters, then null out the message memory.
    if (!TryInitializeParameters(kNumFixedOpenSessionParams, parameter_set, temp_memory_pool)) {
        memory_ = nullptr;
    }
}

CloseSessionMessage::CloseSessionMessage(SharedMemoryManager::DriverMemoryPool* message_pool,
                                         uint32_t session_id) {
    ZX_DEBUG_ASSERT(message_pool != nullptr);

    zx_status_t status = message_pool->Allocate(CalculateSize(kNumParams), &memory_);

    if (status != ZX_OK) {
        memory_ = nullptr;
        return;
    }

    header()->command = Command::kCloseSession;
    header()->num_params = static_cast<uint32_t>(kNumParams);
    header()->session_id = session_id;
}

InvokeCommandMessage::InvokeCommandMessage(SharedMemoryManager::DriverMemoryPool* message_pool,
                                           SharedMemoryManager::ClientMemoryPool* temp_memory_pool,
                                           uint32_t session_id, uint32_t command_id,
                                           const fuchsia_tee_ParameterSet& parameter_set) {
    ZX_DEBUG_ASSERT(message_pool != nullptr);

    zx_status_t status = message_pool->Allocate(CalculateSize(parameter_set.count), &memory_);

    if (status != ZX_OK) {
        memory_ = nullptr;
        return;
    }

    header()->command = Command::kInvokeCommand;
    header()->session_id = session_id;
    header()->app_function = command_id;
    header()->cancel_id = 0;
    header()->num_params = parameter_set.count;

    if (!TryInitializeParameters(0, parameter_set, temp_memory_pool)) {
        memory_ = nullptr;
    }
}

bool RpcMessage::TryInitializeMembers() {
    size_t memory_size = memory_->size();
    if (memory_size < sizeof(MessageHeader)) {
        zxlogf(ERROR,
               "optee: shared memory region passed into RPC command could not be parsed into a "
               "valid message!\n");
        return false;
    }

    if (memory_size < CalculateSize(header()->num_params)) {
        zxlogf(ERROR,
               "optee: shared memory region passed into RPC command could not be parsed into a "
               "valid message!\n");
        // Can at least write error code to the header since that has been checked already
        header()->return_origin = TEEC_ORIGIN_COMMS;
        header()->return_code = TEEC_ERROR_BAD_PARAMETERS;
        return false;
    }

    return true;
}

bool LoadTaRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to load trusted app received unexpected number of parameters!"
               "\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the UUID of the trusted application from the parameters
    MessageParam& uuid_param = params()[kUuidParamIndex];
    switch (uuid_param.attribute) {
    case MessageParam::kAttributeTypeValueInput:
    case MessageParam::kAttributeTypeValueInOut:
        ConvertMessageParamToUuid(uuid_param.payload.value, &ta_uuid_);
        break;
    default:
        zxlogf(ERROR,
               "optee: RPC command to load trusted app received unexpected first parameter!\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse where in memory to write the trusted application
    MessageParam& memory_reference_param = params()[kMemoryReferenceParamIndex];
    switch (memory_reference_param.attribute) {
    case MessageParam::kAttributeTypeTempMemOutput:
    case MessageParam::kAttributeTypeTempMemInOut: {
        MessageParam::TemporaryMemory& temp_mem = memory_reference_param.payload.temporary_memory;
        mem_id_ = temp_mem.shared_memory_reference;
        mem_size_ = static_cast<size_t>(temp_mem.size);
        mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        out_ta_size_ = &temp_mem.size;
        break;
    }
    case MessageParam::kAttributeTypeRegMemOutput:
    case MessageParam::kAttributeTypeRegMemInOut:
        zxlogf(ERROR,
               "optee: received unsupported registered memory parameter!\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to load trusted app received unexpected second parameter!\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    return true;
}

bool GetTimeRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to get current time received unexpected number of parameters!"
               "\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the output time parameter
    MessageParam& time_param = params()[kTimeParamIndex];
    if (time_param.attribute != MessageParam::kAttributeTypeValueOutput) {
        zxlogf(ERROR,
               "optee: RPC command to get current time received unexpected first parameter!\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
    }

    out_secs_ = &time_param.payload.value.get_time_specs.seconds;
    out_nanosecs_ = &time_param.payload.value.get_time_specs.nanoseconds;

    return true;
}

bool AllocateMemoryRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to allocate shared memory received unexpected number of "
               "parameters!\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the memory specifications parameter
    MessageParam& value_param = params()[kMemorySpecsParamIndex];
    if (value_param.attribute != MessageParam::kAttributeTypeValueInput) {
        zxlogf(ERROR,
               "optee: RPC command to allocate shared memory received unexpected first parameter!"
               "\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    auto& memory_specs_param = value_param.payload.value.allocate_memory_specs;

    switch (memory_specs_param.memory_type) {
    case SharedMemoryType::kApplication:
    case SharedMemoryType::kKernel:
    case SharedMemoryType::kGlobal:
        memory_type_ = static_cast<SharedMemoryType>(memory_specs_param.memory_type);
        break;
    default:
        zxlogf(ERROR,
               "optee: received unknown memory type %" PRIu64 " to allocate\n",
               memory_specs_param.memory_type);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    memory_size_ = static_cast<size_t>(memory_specs_param.memory_size);

    // Set up the memory output parameter
    MessageParam& out_param = params()[kOutputTemporaryMemoryParamIndex];
    out_param.attribute = MessageParam::AttributeType::kAttributeTypeTempMemOutput;
    MessageParam::TemporaryMemory& out_temp_mem_param = out_param.payload.temporary_memory;
    out_memory_size_ = &out_temp_mem_param.size;
    out_memory_buffer_ = &out_temp_mem_param.buffer;
    out_memory_id_ = &out_temp_mem_param.shared_memory_reference;

    return true;
}

bool FreeMemoryRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to free shared memory received unexpected number of parameters!"
               "\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the memory specifications parameter
    MessageParam& value_param = params()[kMemorySpecsParamIndex];
    if (value_param.attribute != MessageParam::kAttributeTypeValueInput) {
        zxlogf(ERROR,
               "optee: RPC command to free shared memory received unexpected first parameter!"
               "\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    auto& memory_specs_param = value_param.payload.value.free_memory_specs;

    switch (memory_specs_param.memory_type) {
    case SharedMemoryType::kApplication:
    case SharedMemoryType::kKernel:
    case SharedMemoryType::kGlobal:
        memory_type_ = static_cast<SharedMemoryType>(memory_specs_param.memory_type);
        break;
    default:
        zxlogf(ERROR,
               "optee: received unknown memory type %" PRIu64 " to free\n",
               memory_specs_param.memory_type);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    memory_id_ = memory_specs_param.memory_id;
    return true;
}

bool FileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params < kMinNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to access file system received unexpected number of parameters "
               "(%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file system command parameter
    MessageParam& command_param = params()[kFileSystemCommandParamIndex];
    switch (command_param.attribute) {
    case MessageParam::kAttributeTypeValueInput:
    case MessageParam::kAttributeTypeValueInOut:
        break;
    default:
        zxlogf(ERROR,
               "optee: RPC command to access file system received unexpected first parameter!\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    uint64_t command_num = command_param.payload.value.file_system_command.command_number;
    if (command_num >= kNumFileSystemCommands) {
        zxlogf(ERROR, "optee: received unknown file system command %" PRIu64 "\n", command_num);
        set_return_code(TEEC_ERROR_NOT_SUPPORTED);
        return false;
    }

    fs_command_ = static_cast<FileSystemCommand>(command_num);
    return true;
}

bool OpenFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to open file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file name parameter
    MessageParam& path_param = params()[kPathParamIndex];
    switch (path_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput: {
        MessageParam::TemporaryMemory& temp_mem = path_param.payload.temporary_memory;
        path_mem_id_ = temp_mem.shared_memory_reference;
        path_mem_size_ = temp_mem.size;
        path_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR,
               "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to open file received unexpected second parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the output file identifier parameter
    MessageParam& out_fs_object_id_param = params()[kOutFileSystemObjectIdParamIndex];
    if (out_fs_object_id_param.attribute != MessageParam::kAttributeTypeValueOutput) {
        zxlogf(ERROR,
               "optee: RPC command to open file received unexpected third parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    out_fs_object_id_ = &out_fs_object_id_param.payload.value.file_system_object.identifier;

    return true;
}

bool CreateFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to create file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file name parameter
    MessageParam& path_param = params()[kPathParamIndex];
    switch (path_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput: {
        MessageParam::TemporaryMemory& temp_mem = path_param.payload.temporary_memory;
        path_mem_id_ = temp_mem.shared_memory_reference;
        path_mem_size_ = temp_mem.size;
        path_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR,
               "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to create file received unexpected second parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the output file identifier parameter
    MessageParam& out_fs_object_param = params()[kOutFileSystemObjectIdParamIndex];
    if (out_fs_object_param.attribute != MessageParam::kAttributeTypeValueOutput) {
        zxlogf(ERROR,
               "optee: RPC command to create file received unexpected third parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    out_fs_object_id_ = &out_fs_object_param.payload.value.file_system_object.identifier;

    return true;
}

bool CloseFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to close file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file name parameter
    MessageParam& command_param = params()[kFileSystemCommandParamIndex];

    // The attribute was already validated by FileSystemRpcMessage
    ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput ||
                    command_param.attribute == MessageParam::kAttributeTypeValueInOut);

    fs_object_id_ = command_param.payload.value.file_system_command.object_identifier;

    return true;
}

bool ReadFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to read file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file name parameter
    MessageParam& command_param = params()[kFileSystemCommandParamIndex];

    // The attribute was already validated by FileSystemRpcMessage
    ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput ||
                    command_param.attribute == MessageParam::kAttributeTypeValueInOut);

    fs_object_id_ = command_param.payload.value.file_system_command.object_identifier;
    file_offset_ = command_param.payload.value.file_system_command.object_offset;

    // Parse the output memory parameter
    MessageParam& out_mem_param = params()[kOutReadBufferMemoryParamIndex];
    switch (out_mem_param.attribute) {
    case MessageParam::kAttributeTypeTempMemOutput: {
        MessageParam::TemporaryMemory& temp_mem = out_mem_param.payload.temporary_memory;
        file_contents_memory_identifier_ = temp_mem.shared_memory_reference;
        file_contents_memory_size_ = static_cast<size_t>(temp_mem.size);
        file_contents_memory_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        out_file_contents_size_ = &temp_mem.size;
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR,
               "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to read file received unexpected second parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    return true;
}

bool WriteFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to write file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file name parameter
    MessageParam& command_param = params()[kFileSystemCommandParamIndex];

    // The attribute was already validated by FileSystemRpcMessage
    ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput ||
                    command_param.attribute == MessageParam::kAttributeTypeValueInOut);

    fs_object_id_ = command_param.payload.value.file_system_command.object_identifier;
    file_offset_ = command_param.payload.value.file_system_command.object_offset;

    // Parse the write memory parameter
    MessageParam& mem_param = params()[kWriteBufferMemoryParam];
    switch (mem_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput: {
        MessageParam::TemporaryMemory& temp_mem = mem_param.payload.temporary_memory;
        file_contents_memory_identifier_ = temp_mem.shared_memory_reference;
        file_contents_memory_size_ = static_cast<size_t>(temp_mem.size);
        file_contents_memory_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR,
               "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to write file received unexpected second parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    return true;
}

bool TruncateFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to truncate file received unexpected number of parameters "
               "(%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file command parameter
    MessageParam& command_param = params()[kFileSystemCommandParamIndex];

    // The attribute was already validated by FileSystemRpcMessage
    ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput ||
                    command_param.attribute == MessageParam::kAttributeTypeValueInOut);

    fs_object_id_ = command_param.payload.value.file_system_command.object_identifier;
    target_file_size_ = command_param.payload.value.file_system_command.object_offset;

    return true;
}

bool RemoveFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to remove file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the file name parameter
    MessageParam& path_param = params()[kFileNameParamIndex];
    switch (path_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput: {
        MessageParam::TemporaryMemory& temp_mem = path_param.payload.temporary_memory;
        path_mem_id_ = temp_mem.shared_memory_reference;
        path_mem_size_ = temp_mem.size;
        path_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR,
               "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to remove file received unexpected second parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    return true;
}

bool RenameFileFileSystemRpcMessage::TryInitializeMembers() {
    if (header()->num_params != kNumParams) {
        zxlogf(ERROR,
               "optee: RPC command to rename file received unexpected number of parameters (%u)\n",
               header()->num_params);
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the overwrite value
    MessageParam& command_param = params()[kFileSystemCommandParamIndex];

    // The attribute was already validated by FileSystemRpcMessage
    ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput ||
                    command_param.attribute == MessageParam::kAttributeTypeValueInOut);

    should_overwrite_ = (command_param.payload.value.generic.b != 0);

    // Parse the old file name parameter
    MessageParam& old_file_name_param = params()[kOldFileNameParamIndex];
    switch (old_file_name_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput: {
        MessageParam::TemporaryMemory& temp_mem = old_file_name_param.payload.temporary_memory;
        old_file_name_mem_id_ = temp_mem.shared_memory_reference;
        old_file_name_mem_size_ = temp_mem.size;
        old_file_name_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR, "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR,
               "optee: RPC command to rename file received unexpected second parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    // Parse the new file name parameter
    MessageParam& new_file_name_param = params()[kNewFileNameParamIndex];
    switch (new_file_name_param.attribute) {
    case MessageParam::kAttributeTypeTempMemInput: {
        MessageParam::TemporaryMemory& temp_mem = new_file_name_param.payload.temporary_memory;
        new_file_name_mem_id_ = temp_mem.shared_memory_reference;
        new_file_name_mem_size_ = temp_mem.size;
        new_file_name_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer);
        break;
    }
    case MessageParam::kAttributeTypeRegMemInput:
        zxlogf(ERROR, "optee: received unsupported registered memory parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_NOT_IMPLEMENTED);
        return false;
    default:
        zxlogf(ERROR, "optee: RPC command to rename file received unexpected third parameter\n");
        set_return_origin(TEEC_ORIGIN_COMMS);
        set_return_code(TEEC_ERROR_BAD_PARAMETERS);
        return false;
    }

    return true;
}

} // namespace optee
