1 // Copyright 2016 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/device.h> 8 #include <zircon/types.h> 9 #include <zircon/thread_annotations.h> 10 #include <stddef.h> 11 #include <stdint.h> 12 13 #if __cplusplus 14 15 #include <ddktl/device.h> 16 #include <ddktl/protocol/empty-protocol.h> 17 #include <fbl/mutex.h> 18 #include <fbl/unique_ptr.h> 19 20 namespace tpm { 21 22 typedef uint8_t Locality; 23 24 // Abstraction over the hardware access mechanism. The communication protocol 25 // relies on accessing certain hardware registers which have the same contents 26 // regardless of access mechanism. 27 class HardwareInterface { 28 public: ~HardwareInterface()29 virtual ~HardwareInterface() { } 30 31 // Return ZX_OK if the device represented by this interface is valid under 32 // the interface's constraints. This may perform IO to determine the 33 // answer, and will be called before the device is made visible to the rest 34 // of the system. Validate()35 virtual zx_status_t Validate() { return ZX_OK; } 36 37 // Read/write the ACCESS register for the given locality 38 virtual zx_status_t ReadAccess(Locality loc, uint8_t* access) = 0; 39 virtual zx_status_t WriteAccess(Locality loc, uint8_t access) = 0; 40 41 // Read/write the STS register for the given locality 42 virtual zx_status_t ReadStatus(Locality loc, uint32_t* sts) = 0; 43 virtual zx_status_t WriteStatus(Locality loc, uint32_t sts) = 0; 44 45 // Read the DID_VID register, if present 46 virtual zx_status_t ReadDidVid(uint16_t* vid, uint16_t* did) = 0; 47 48 // Read/write from the DATA_FIFO register. It is up to the caller to respect the 49 // protocol's burstCount. 50 virtual zx_status_t ReadDataFifo(Locality loc, uint8_t* buf, size_t len) = 0; 51 virtual zx_status_t WriteDataFifo(Locality loc, const uint8_t* buf, size_t len) = 0; 52 }; 53 54 class Device; 55 using DeviceType = ddk::Device<Device, ddk::Suspendable>; 56 57 class Device : public DeviceType, 58 public ddk::EmptyProtocol<ZX_PROTOCOL_TPM> { 59 public: 60 Device(zx_device_t* parent, fbl::unique_ptr<HardwareInterface> iface); 61 ~Device(); 62 63 // Send the given command packet to the TPM and wait for a response. 64 // |actual| is the number of bytes written into |resp|. 65 zx_status_t ExecuteCmd(Locality loc, const uint8_t* cmd, size_t len, 66 uint8_t* resp, size_t max_len, size_t* actual); 67 68 // DDK methods 69 void DdkRelease(); 70 zx_status_t DdkSuspend(uint32_t flags); 71 72 // Register this instance with devmgr and launch the deferred 73 // initialization. 74 zx_status_t Bind(); 75 private: 76 // Deferred initialization of the device via a thread. Once complete, this 77 // marks the device as visible. Init(void * device)78 static zx_status_t Init(void* device) { 79 return reinterpret_cast<Device*>(device)->Init(); 80 } 81 zx_status_t Init(); 82 83 // Send the given command packet to the TPM and wait for a response. 84 // |actual| is the number of bytes written into |resp|. 85 zx_status_t ExecuteCmdLocked(Locality loc, const uint8_t* cmd, size_t len, 86 uint8_t* resp, size_t max_len, size_t* actual) TA_REQ(lock_); 87 88 // Request use of the given locality 89 zx_status_t RequestLocalityLocked(Locality loc) TA_REQ(lock_); 90 // Wait for access to the requested locality 91 zx_status_t WaitForLocalityLocked(Locality loc) TA_REQ(lock_); 92 // Release the given locality 93 zx_status_t ReleaseLocalityLocked(Locality loc) TA_REQ(lock_); 94 95 // Perform the transmit half of a command 96 zx_status_t SendCmdLocked(Locality loc, const uint8_t* cmd, size_t len) TA_REQ(lock_); 97 // Perform the receive half of a command. |actual| will contain the total number of bytes in 98 // the response, may be less than max_len. 99 zx_status_t RecvRespLocked(Locality loc, uint8_t* resp, size_t max_len, 100 size_t* actual) TA_REQ(lock_); 101 102 // Issue a TPM_CC_SHUTDOWN with the given type 103 zx_status_t ShutdownLocked(uint16_t type) TA_REQ(lock_); 104 105 fbl::Mutex lock_; 106 const fbl::unique_ptr<HardwareInterface> iface_; 107 }; 108 109 enum tpm_result { 110 TPM_SUCCESS = 0x0, 111 TPM_BAD_PARAMETER = 0x3, 112 TPM_DEACTIVATED = 0x6, 113 TPM_DISABLED = 0x7, 114 TPM_DISABLED_CMD = 0x8, 115 TPM_FAIL = 0x9, 116 TPM_BAD_ORDINAL = 0xa, 117 TPM_RETRY = 0x800, 118 }; 119 120 } // namespace tpm 121 122 #endif // __cplusplus 123 124 __BEGIN_CDECLS 125 zx_status_t tpm_bind(void* ctx, zx_device_t* parent); 126 __END_CDECLS 127