1a2d5ed94SMarcin Wojtas /*- 2a2d5ed94SMarcin Wojtas * Copyright (c) 2018 Stormshield. 3a2d5ed94SMarcin Wojtas * Copyright (c) 2018 Semihalf. 4a2d5ed94SMarcin Wojtas * All rights reserved. 5a2d5ed94SMarcin Wojtas * 6a2d5ed94SMarcin Wojtas * Redistribution and use in source and binary forms, with or without 7a2d5ed94SMarcin Wojtas * modification, are permitted provided that the following conditions 8a2d5ed94SMarcin Wojtas * are met: 9a2d5ed94SMarcin Wojtas * 1. Redistributions of source code must retain the above copyright 10a2d5ed94SMarcin Wojtas * notice, this list of conditions and the following disclaimer. 11a2d5ed94SMarcin Wojtas * 2. Redistributions in binary form must reproduce the above copyright 12a2d5ed94SMarcin Wojtas * notice, this list of conditions and the following disclaimer in the 13a2d5ed94SMarcin Wojtas * documentation and/or other materials provided with the distribution. 14a2d5ed94SMarcin Wojtas * 15a2d5ed94SMarcin Wojtas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16a2d5ed94SMarcin Wojtas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17a2d5ed94SMarcin Wojtas * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18a2d5ed94SMarcin Wojtas * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19a2d5ed94SMarcin Wojtas * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20a2d5ed94SMarcin Wojtas * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21a2d5ed94SMarcin Wojtas * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22a2d5ed94SMarcin Wojtas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23a2d5ed94SMarcin Wojtas * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24a2d5ed94SMarcin Wojtas * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25a2d5ed94SMarcin Wojtas * POSSIBILITY OF SUCH DAMAGE. 26a2d5ed94SMarcin Wojtas */ 27a2d5ed94SMarcin Wojtas 28a2d5ed94SMarcin Wojtas #ifndef _TPM20_H_ 29a2d5ed94SMarcin Wojtas #define _TPM20_H_ 30a2d5ed94SMarcin Wojtas 31a2d5ed94SMarcin Wojtas #include <sys/cdefs.h> 32a2d5ed94SMarcin Wojtas __FBSDID("$FreeBSD$"); 33a2d5ed94SMarcin Wojtas 34a2d5ed94SMarcin Wojtas #include <sys/endian.h> 35a2d5ed94SMarcin Wojtas #include <sys/param.h> 36a2d5ed94SMarcin Wojtas #include <sys/kernel.h> 37a2d5ed94SMarcin Wojtas #include <sys/malloc.h> 38a2d5ed94SMarcin Wojtas #include <sys/proc.h> 39a2d5ed94SMarcin Wojtas #include <sys/systm.h> 40a2d5ed94SMarcin Wojtas 41a2d5ed94SMarcin Wojtas #include <sys/bus.h> 42a2d5ed94SMarcin Wojtas #include <sys/callout.h> 43a2d5ed94SMarcin Wojtas #include <sys/conf.h> 44a2d5ed94SMarcin Wojtas #include <sys/module.h> 45a2d5ed94SMarcin Wojtas #include <sys/rman.h> 46a2d5ed94SMarcin Wojtas #include <sys/sx.h> 47a2d5ed94SMarcin Wojtas #include <sys/uio.h> 48a2d5ed94SMarcin Wojtas 49a2d5ed94SMarcin Wojtas #include <machine/bus.h> 50a2d5ed94SMarcin Wojtas #include <machine/md_var.h> 51a2d5ed94SMarcin Wojtas #include <machine/resource.h> 52a2d5ed94SMarcin Wojtas 53a2d5ed94SMarcin Wojtas #include <contrib/dev/acpica/include/acpi.h> 54a2d5ed94SMarcin Wojtas #include <contrib/dev/acpica/include/accommon.h> 55a2d5ed94SMarcin Wojtas #include <dev/acpica/acpivar.h> 56a2d5ed94SMarcin Wojtas #include "opt_acpi.h" 57a2d5ed94SMarcin Wojtas 584ee7d3b0SMarcin Wojtas #include "opt_tpm.h" 594ee7d3b0SMarcin Wojtas 60a2d5ed94SMarcin Wojtas #define BIT(x) (1 << (x)) 61a2d5ed94SMarcin Wojtas 62a2d5ed94SMarcin Wojtas /* Timeouts in us */ 63a2d5ed94SMarcin Wojtas #define TPM_TIMEOUT_A 750000 64a2d5ed94SMarcin Wojtas #define TPM_TIMEOUT_B 2000000 65a2d5ed94SMarcin Wojtas #define TPM_TIMEOUT_C 200000 66a2d5ed94SMarcin Wojtas #define TPM_TIMEOUT_D 30000 67a2d5ed94SMarcin Wojtas 68a2d5ed94SMarcin Wojtas /* 69a2d5ed94SMarcin Wojtas * Generating RSA key pair takes ~(10-20s), which is significantly longer than 70a2d5ed94SMarcin Wojtas * any timeout defined in spec. Because of that we need a new one. 71a2d5ed94SMarcin Wojtas */ 72a2d5ed94SMarcin Wojtas #define TPM_TIMEOUT_LONG 40000000 73a2d5ed94SMarcin Wojtas 74a2d5ed94SMarcin Wojtas /* List of commands that require TPM_TIMEOUT_LONG time to complete */ 75a2d5ed94SMarcin Wojtas #define TPM_CC_CreatePrimary 0x00000131 76a2d5ed94SMarcin Wojtas #define TPM_CC_Create 0x00000153 77a2d5ed94SMarcin Wojtas #define TPM_CC_CreateLoaded 0x00000191 78a2d5ed94SMarcin Wojtas 79a2d5ed94SMarcin Wojtas /* List of commands that require only TPM_TIMEOUT_C time to complete */ 80a2d5ed94SMarcin Wojtas #define TPM_CC_SequenceComplete 0x0000013e 81a2d5ed94SMarcin Wojtas #define TPM_CC_Startup 0x00000144 82a2d5ed94SMarcin Wojtas #define TPM_CC_SequenceUpdate 0x0000015c 83a2d5ed94SMarcin Wojtas #define TPM_CC_GetCapability 0x0000017a 84a2d5ed94SMarcin Wojtas #define TPM_CC_PCR_Extend 0x00000182 85a2d5ed94SMarcin Wojtas #define TPM_CC_EventSequenceComplete 0x00000185 86a2d5ed94SMarcin Wojtas #define TPM_CC_HashSequenceStart 0x00000186 87a2d5ed94SMarcin Wojtas 88a2d5ed94SMarcin Wojtas /* Timeout before data in read buffer is discarded */ 89a2d5ed94SMarcin Wojtas #define TPM_READ_TIMEOUT 500000 90a2d5ed94SMarcin Wojtas 91a2d5ed94SMarcin Wojtas #define TPM_BUFSIZE 0x1000 92a2d5ed94SMarcin Wojtas 93a2d5ed94SMarcin Wojtas #define TPM_HEADER_SIZE 10 94a2d5ed94SMarcin Wojtas 95a2d5ed94SMarcin Wojtas #define TPM_CDEV_NAME "tpm0" 96a2d5ed94SMarcin Wojtas #define TPM_CDEV_PERM_FLAG 0600 97a2d5ed94SMarcin Wojtas 98877fc2e3STakanori Watanabe #define TPM2_START_METHOD_ACPI 2 99877fc2e3STakanori Watanabe #define TPM2_START_METHOD_TIS 6 100877fc2e3STakanori Watanabe #define TPM2_START_METHOD_CRB 7 101877fc2e3STakanori Watanabe #define TPM2_START_METHOD_CRB_ACPI 8 102877fc2e3STakanori Watanabe 103*59d1661cSKornel Duleba MALLOC_DECLARE(M_TPM20); 104*59d1661cSKornel Duleba 105a2d5ed94SMarcin Wojtas struct tpm_sc { 106a2d5ed94SMarcin Wojtas device_t dev; 107a2d5ed94SMarcin Wojtas 108a2d5ed94SMarcin Wojtas struct resource *mem_res; 109a2d5ed94SMarcin Wojtas struct resource *irq_res; 110a2d5ed94SMarcin Wojtas int mem_rid; 111a2d5ed94SMarcin Wojtas int irq_rid; 112a2d5ed94SMarcin Wojtas 113a2d5ed94SMarcin Wojtas struct cdev *sc_cdev; 114a2d5ed94SMarcin Wojtas 115a2d5ed94SMarcin Wojtas struct sx dev_lock; 116a2d5ed94SMarcin Wojtas struct cv buf_cv; 117a2d5ed94SMarcin Wojtas 118a2d5ed94SMarcin Wojtas void *intr_cookie; 119a2d5ed94SMarcin Wojtas int intr_type; /* Current event type */ 120a2d5ed94SMarcin Wojtas bool interrupts; 121a2d5ed94SMarcin Wojtas 122a2d5ed94SMarcin Wojtas uint8_t *buf; 123a2d5ed94SMarcin Wojtas size_t pending_data_length; 124d68a65eaSMarcin Wojtas lwpid_t owner_tid; 125a2d5ed94SMarcin Wojtas 126a2d5ed94SMarcin Wojtas struct callout discard_buffer_callout; 1274ee7d3b0SMarcin Wojtas #ifdef TPM_HARVEST 1284ee7d3b0SMarcin Wojtas struct callout harvest_callout; 1294ee7d3b0SMarcin Wojtas int harvest_ticks; 1304ee7d3b0SMarcin Wojtas #endif 131a2d5ed94SMarcin Wojtas 132a2d5ed94SMarcin Wojtas int (*transmit)(struct tpm_sc *, size_t); 133a2d5ed94SMarcin Wojtas }; 134a2d5ed94SMarcin Wojtas 135a2d5ed94SMarcin Wojtas int tpm20_suspend(device_t dev); 136a2d5ed94SMarcin Wojtas int tpm20_shutdown(device_t dev); 137a2d5ed94SMarcin Wojtas int32_t tpm20_get_timeout(uint32_t command); 138a2d5ed94SMarcin Wojtas int tpm20_init(struct tpm_sc *sc); 139a2d5ed94SMarcin Wojtas void tpm20_release(struct tpm_sc *sc); 140a2d5ed94SMarcin Wojtas 141a2d5ed94SMarcin Wojtas /* Small helper routines for io ops */ 142a2d5ed94SMarcin Wojtas static inline uint8_t 143a2d5ed94SMarcin Wojtas RD1(struct tpm_sc *sc, bus_size_t off) 144a2d5ed94SMarcin Wojtas { 145a2d5ed94SMarcin Wojtas 146a2d5ed94SMarcin Wojtas return (bus_read_1(sc->mem_res, off)); 147a2d5ed94SMarcin Wojtas } 148a2d5ed94SMarcin Wojtas static inline uint32_t 149a2d5ed94SMarcin Wojtas RD4(struct tpm_sc *sc, bus_size_t off) 150a2d5ed94SMarcin Wojtas { 151a2d5ed94SMarcin Wojtas 152a2d5ed94SMarcin Wojtas return (bus_read_4(sc->mem_res, off)); 153a2d5ed94SMarcin Wojtas } 154efa9b503SMarcin Wojtas #ifdef __amd64__ 155a2d5ed94SMarcin Wojtas static inline uint64_t 156a2d5ed94SMarcin Wojtas RD8(struct tpm_sc *sc, bus_size_t off) 157a2d5ed94SMarcin Wojtas { 158a2d5ed94SMarcin Wojtas 159a2d5ed94SMarcin Wojtas return (bus_read_8(sc->mem_res, off)); 160a2d5ed94SMarcin Wojtas } 161efa9b503SMarcin Wojtas #endif 162a2d5ed94SMarcin Wojtas static inline void 163a2d5ed94SMarcin Wojtas WR1(struct tpm_sc *sc, bus_size_t off, uint8_t val) 164a2d5ed94SMarcin Wojtas { 165a2d5ed94SMarcin Wojtas 166a2d5ed94SMarcin Wojtas bus_write_1(sc->mem_res, off, val); 167a2d5ed94SMarcin Wojtas } 168a2d5ed94SMarcin Wojtas static inline void 169a2d5ed94SMarcin Wojtas WR4(struct tpm_sc *sc, bus_size_t off, uint32_t val) 170a2d5ed94SMarcin Wojtas { 171a2d5ed94SMarcin Wojtas 172a2d5ed94SMarcin Wojtas bus_write_4(sc->mem_res, off, val); 173a2d5ed94SMarcin Wojtas } 174a2d5ed94SMarcin Wojtas static inline void 175a2d5ed94SMarcin Wojtas AND4(struct tpm_sc *sc, bus_size_t off, uint32_t val) 176a2d5ed94SMarcin Wojtas { 177a2d5ed94SMarcin Wojtas 178a2d5ed94SMarcin Wojtas WR4(sc, off, RD4(sc, off) & val); 179a2d5ed94SMarcin Wojtas } 180a2d5ed94SMarcin Wojtas static inline void 181a2d5ed94SMarcin Wojtas OR1(struct tpm_sc *sc, bus_size_t off, uint8_t val) 182a2d5ed94SMarcin Wojtas { 183a2d5ed94SMarcin Wojtas 184a2d5ed94SMarcin Wojtas WR1(sc, off, RD1(sc, off) | val); 185a2d5ed94SMarcin Wojtas } 186a2d5ed94SMarcin Wojtas static inline void 187a2d5ed94SMarcin Wojtas OR4(struct tpm_sc *sc, bus_size_t off, uint32_t val) 188a2d5ed94SMarcin Wojtas { 189a2d5ed94SMarcin Wojtas 190a2d5ed94SMarcin Wojtas WR4(sc, off, RD4(sc, off) | val); 191a2d5ed94SMarcin Wojtas } 192a2d5ed94SMarcin Wojtas #endif /* _TPM20_H_ */ 193