1// Copyright 2018 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#pragma once
6
7#include <ddk/protocol/platform-device.h>
8#include <ddktl/device.h>
9#include <ddktl/protocol/tee.h>
10#include <fbl/function.h>
11#include <fbl/intrusive_double_list.h>
12#include <fbl/mutex.h>
13#include <fbl/unique_ptr.h>
14#include <zircon/device/tee.h>
15#include <zircon/thread_annotations.h>
16
17#include "optee-message.h"
18#include "optee-smc.h"
19#include "shared-memory.h"
20
21namespace optee {
22
23class OpteeClient;
24
25class OpteeController;
26using OpteeControllerBase = ddk::Device<OpteeController, ddk::Openable, ddk::Unbindable>;
27using OpteeControllerProtocol = ddk::TeeProtocol<OpteeController>;
28class OpteeController : public OpteeControllerBase,
29                        public OpteeControllerProtocol {
30public:
31    using RpcHandler = fbl::Function<zx_status_t(const RpcFunctionArgs&, RpcFunctionResult*)>;
32
33    explicit OpteeController(zx_device_t* parent)
34        : OpteeControllerBase(parent) {}
35
36    OpteeController(const OpteeController&) = delete;
37    OpteeController& operator=(const OpteeController&) = delete;
38
39    zx_status_t Bind();
40
41    zx_status_t DdkOpen(zx_device_t** out_dev, uint32_t flags);
42    void DdkUnbind();
43    void DdkRelease();
44
45    // Client IOCTL commands
46    zx_status_t GetDescription(tee_ioctl_description_t* out_description, size_t* out_size) const;
47
48    void RemoveClient(OpteeClient* client);
49
50    uint32_t CallWithMessage(const Message& message, RpcHandler rpc_handler);
51
52    SharedMemoryManager::DriverMemoryPool* driver_pool() const {
53        return shared_memory_manager_->driver_pool();
54    }
55
56    SharedMemoryManager::ClientMemoryPool* client_pool() const {
57        return shared_memory_manager_->client_pool();
58    }
59
60private:
61    zx_status_t ValidateApiUid() const;
62    zx_status_t ValidateApiRevision() const;
63    zx_status_t GetOsRevision();
64    zx_status_t ExchangeCapabilities();
65    void AddClient(OpteeClient* client);
66    void CloseClients();
67    zx_status_t InitializeSharedMemory();
68    zx_status_t DiscoverSharedMemoryConfig(zx_paddr_t* out_start_addr, size_t* out_size);
69
70    platform_device_protocol_t pdev_proto_ = {};
71    // TODO(rjascani): Eventually, the secure_monitor_ object should be an owned resource object
72    // created and provided to us by our parent. For now, we're simply stashing a copy of the
73    // root resource so that we can make zx_smc_calls. We can make that switch when we can properly
74    // craft a resource object dedicated only to secure monitor calls targetting the Trusted OS.
75    zx_handle_t secure_monitor_ = ZX_HANDLE_INVALID;
76    uint32_t secure_world_capabilities_ = 0;
77    tee_revision_t os_revision_ = {};
78    fbl::Mutex clients_lock_;
79    fbl::DoublyLinkedList<OpteeClient*> clients_ TA_GUARDED(clients_lock_);
80    fbl::unique_ptr<SharedMemoryManager> shared_memory_manager_;
81};
82
83} // namespace optee
84