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