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