├── LICENSE ├── Makefile ├── README.md ├── config.h ├── ftdi_spi_tpm.c ├── ftdi_spi_tpm.h ├── mpsse.c ├── mpsse.h ├── ntpm.c ├── support.c ├── support.h ├── tcgt ├── tpm2lib_wrapper.c └── tpm2lib_wrapper.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Vadim Bendebury 2 | All rights reserved. 3 | 4 | This repository is partially based on Craig Heffner's work published at 5 | https://github.com/devttys0/libmpsse 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | TPM2_SRC ?= $(shell readlink -f ../tpm2) 3 | obj ?= $(shell readlink -f ..)/build/tpm2_server 4 | CC = $(CROSS_COMPILE)gcc 5 | 6 | CFLAGS = 7 | ifneq ($(DEBUG),) 8 | CFLAGS += -g -O0 9 | endif 10 | CFLAGS += -I $(TPM2_SRC) 11 | CFLAGS += -Wall 12 | CFLAGS += -Wdeclaration-after-statement 13 | CFLAGS += -Werror 14 | CFLAGS += -Werror-implicit-function-declaration 15 | CFLAGS += -Wmaybe-uninitialized 16 | CFLAGS += -Wno-format-security 17 | CFLAGS += -Wno-pointer-sign 18 | CFLAGS += -Wno-trigraphs 19 | CFLAGS += -Wstrict-prototypes 20 | CFLAGS += -Wundef 21 | CFLAGS += -Wuninitialized 22 | CFLAGS += -c 23 | CFLAGS += -fconserve-stack 24 | CFLAGS += -fno-delete-null-pointer-checks 25 | CFLAGS += -fno-strict-aliasing 26 | CFLAGS += -fno-strict-overflow 27 | CFLAGS += -fshort-wchar 28 | 29 | # Use V=1 for verbose output 30 | ifeq ($(V),) 31 | Q := @ 32 | else 33 | Q := 34 | endif 35 | 36 | # This is the default target 37 | all: $(obj)/ntpm 38 | 39 | SOURCES = ftdi_spi_tpm.c mpsse.c ntpm.c support.c tpm2lib_wrapper.c 40 | 41 | OBJS = $(patsubst %.c,$(obj)/%.o,$(SOURCES)) 42 | DEPS = $(patsubst %.c,$(obj)/%.d,$(SOURCES)) 43 | 44 | export V DEBUG CFLAGS 45 | .PHONY: $(obj)/libtpm2.a 46 | $(obj)/libtpm2.a: 47 | make -C $(TPM2_SRC) obj=$(obj) 48 | $(Q)$(AR) scr $@ $^ 49 | 50 | $(obj): 51 | @echo " MKDIR $(obj)" 52 | $(Q)mkdir -p $(obj) 53 | 54 | $(obj)/%.d $(obj)/%.o: %.c | $(obj) 55 | @echo " CC $(notdir $<)" 56 | $(Q)$(CC) $(CFLAGS) -c -MMD -MF $(basename $@).d -o $(basename $@).o $< 57 | 58 | .PHONY: clean 59 | clean: 60 | @echo " RM $(obj)" 61 | $(Q)rm -rf $(obj) 62 | 63 | ifneq ($(MAKECMDGOALS),clean) 64 | -include $(DEPS) 65 | endif 66 | 67 | $(obj)/ntpm: $(OBJS) $(obj)/libtpm2.a 68 | gcc -o $@ $^ -lftdi -lcrypto 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tpm2_server 2 | 3 | This repository implements a server which provides access to a real or 4 | simulated TPM2 device over a socket interface. 5 | 6 | A real TPM device could be connected over a USB-to-FTDI-to-SPI cable (for 7 | instance http://goo.gl/VDlr8H). Software TPM2 implementation published at 8 | https://goo.gl/r4qGVZ is used when running in simulation mode. 9 | 10 | The `Makefile` by default assumes the following directory layout: 11 | 12 |
13 | .
14 | |-- build/
15 | |   `-- tpm2_server   <= build directory
16 | |-- tpm2              <= TPM2 library (downloaded separately)
17 | `-- tpm2_server       <= this server implementation
18 | 
19 | 20 | Building the code on a recent Ubuntu host requires `gcc` toolchain and 21 | `crypto` and `ftdi` libraries, other than that it is as simple as running 22 | `make -j` in the `./tpm2_server` root directory. 23 | 24 | The executable including the software TPM2 implementation is produced as 25 | `../build/tpm2_server/ntpm` 26 | 27 | Note that you don't need to build the TPM2 library separately, but if required 28 | a standalone TPM2 library can be produced by running `make -j` in the 29 | `../tpm2` directory, it is generated as `../tpm2/build/libtpm2.a` 30 | 31 | ==== Running the server ===== 32 | 33 | The server accepts the following command line options: 34 |
35 |   -d        - enable debug tracing
36 |   -f NUM    - ftdi clock frequency  ## when using a TPM2 chip over USB
37 |   -p NUM    - port number  ## port the server listens on, default value is 9833
38 |   -s        - use simulator instead of the USB interface
39 | 
40 | 41 | When you run `../build/tpm2_server/ntpm` with no command line arguments, it 42 | will find and connect to a USB-to-FTDI-to-SPI adapter which expected to have a 43 | TPM2 device attached (see below). 44 | 45 | If you run it with `-s` command line argument, it starts the built-in TPM2 46 | simulator instead. 47 | 48 | Once initialized, the server listens on `localhost:9833` for incoming 49 | connections. To talk to the TPM, you can send and receive binary data over the 50 | socket. For example, the `TPM2_Startup` command is sent as 51 |
52 | 80 01 00 00 00 0c 00 00 01 44 00 00
53 | 
54 | and the expected response is 55 |
56 | 80 01 00 00 00 0a 00 00 00 00
57 | 
58 | 59 | ==== Connecting an actual TPM2 device ========= 60 | 61 | If using the C232HM cable, the leads are connected to TPM pins as follows: 62 | 63 | | Cable lead | TPM pin | 64 | |-------------:|:--------| 65 | | black | GROUND | 66 | | red | VPP | 67 | | green | MISO | 68 | | yellow | MOSI | 69 | | brown | CS | 70 | | orange | CLK | 71 | | gray | RESET | 72 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef __TPM2_SERVER_CONFIG_H 2 | #define __TPM2_SERVER_CONFIG_H 3 | 4 | #define BYTES_PER_LINE 24 5 | 6 | #endif // __TPM2_SERVER_CONFIG_H 7 | -------------------------------------------------------------------------------- /ftdi_spi_tpm.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ftdi_spi_tpm.h" 8 | 9 | static struct mpsse_context* mpsse_; 10 | static unsigned locality_; // Set at initialization. 11 | static int debug_level; 12 | 13 | // Assorted TPM2 registers for interface type FIFO. 14 | #define TPM_REG_BASE 0xd40000 15 | 16 | #define TPM_ACCESS_REG (TPM_REG_BASE + locality_ * 0x1000 + 0x0) 17 | #define TPM_STS_REG (TPM_REG_BASE + locality_ * 0x1000 + 0x18) 18 | #define TPM_DATA_FIFO_REG (TPM_REG_BASE + locality_ * 0x1000 + 0x24) 19 | #define TPM_DID_VID_REG (TPM_REG_BASE + locality_ * 0x1000 + 0xf00) 20 | #define TPM_RID_REG (TPM_REG_BASE + locality_ * 0x1000 + 0xf04) 21 | 22 | // Locality management bits (in TPM_ACCESS_REG) 23 | enum TpmAccessBits { 24 | tpmRegValidSts = (1 << 7), 25 | activeLocality = (1 << 5), 26 | requestUse = (1 << 1), 27 | tpmEstablishment = (1 << 0), 28 | }; 29 | 30 | enum TpmStsBits { 31 | tpmFamilyShift = 26, 32 | tpmFamilyMask = ((1 << 2) - 1), // 2 bits wide 33 | tpmFamilyTPM2 = 1, 34 | resetEstablishmentBit = (1 << 25), 35 | commandCancel = (1 << 24), 36 | burstCountShift = 8, 37 | burstCountMask = ((1 << 16) -1), // 16 bits wide 38 | stsValid = (1 << 7), 39 | commandReady = (1 << 6), 40 | tpmGo = (1 << 5), 41 | dataAvail = (1 << 4), 42 | Expect = (1 << 3), 43 | selfTestDone = (1 << 2), 44 | responseRetry = (1 << 1), 45 | }; 46 | 47 | // SPI frame header for TPM transactions is 4 bytes in size, it is described 48 | // in section "6.4.6 Spi Bit Protocol" of the TCG issued "TPM Profile (PTP) 49 | // Specification Revision 00.43. 50 | typedef struct { 51 | unsigned char body[4]; 52 | } SpiFrameHeader; 53 | 54 | void FtdiStop(void) { 55 | if (mpsse_) 56 | Close(mpsse_); 57 | 58 | mpsse_ = NULL; 59 | } 60 | 61 | static void StartTransaction(int read_write, size_t bytes, unsigned addr) 62 | { 63 | unsigned char *response; 64 | SpiFrameHeader header; 65 | int i; 66 | 67 | usleep(10000); // give it 10 ms. TODO(vbendeb): remove this once 68 | // cr50 SPS TPM driver performance is fixed. 69 | 70 | // The first byte of the frame header encodes the transaction type (read or 71 | // write) and size (set to lenth - 1). 72 | header.body[0] = (read_write ? 0x80 : 0) | 0x40 | (bytes - 1); 73 | 74 | // The rest of the frame header is the internal address in the TPM 75 | for (i = 0; i < 3; i++) 76 | header.body[i + 1] = (addr >> (8 * (2 - i))) & 0xff; 77 | 78 | Start(mpsse_); 79 | 80 | response = Transfer(mpsse_, header.body, sizeof(header.body)); 81 | 82 | // The TCG TPM over SPI specification itroduces the notion of SPI flow 83 | // control (Section "6.4.5 Flow Control" of the TCG issued "TPM Profile 84 | // (PTP) Specification Revision 00.43). 85 | 86 | // The slave (TPM device) expects each transaction to start with a 4 byte 87 | // header trasmitted by master. If the slave needs to stall the transaction, 88 | // it sets the MOSI bit to 0 during the last clock of the 4 byte header. In 89 | // this case the master is supposed to start polling the line, byte at time, 90 | // until the last bit in the received byte (transferred during the last 91 | // clock of the byte) is set to 1. 92 | while (!(response[3] & 1)) { 93 | unsigned char *poll_state; 94 | 95 | poll_state = Read(mpsse_, 1); 96 | response[3] = *poll_state; 97 | free(poll_state); 98 | } 99 | free(response); 100 | } 101 | 102 | static void trace_dump(const char *prefix, unsigned reg, size_t bytes, const uint8_t *buffer) 103 | { 104 | static char prev_prefix; 105 | static unsigned prev_reg; 106 | static int current_line; 107 | 108 | if (!debug_level) 109 | return; 110 | 111 | if ((debug_level < 2) && (reg != TPM_DATA_FIFO_REG)) 112 | return; 113 | 114 | if ((prev_prefix != *prefix) || (prev_reg != reg)) { 115 | prev_prefix = *prefix; 116 | prev_reg = reg; 117 | printf("\n%s %2.2x:", prefix, reg); 118 | current_line = 0; 119 | } 120 | 121 | if ((reg != TPM_DATA_FIFO_REG) && (bytes == 4)) { 122 | printf(" %8.8x", *(const uint32_t*) buffer); 123 | } else { 124 | int i; 125 | for (i = 0; i < bytes; i++) { 126 | if (current_line && !(current_line % BYTES_PER_LINE)) { 127 | printf("\n "); 128 | current_line = 0; 129 | } 130 | current_line++; 131 | printf(" %2.2x", buffer[i]); 132 | } 133 | } 134 | } 135 | 136 | static int FtdiWriteReg(unsigned reg_number, size_t bytes, const void *buffer) 137 | { 138 | if (!mpsse_) 139 | return false; 140 | 141 | trace_dump("W", reg_number, bytes, buffer); 142 | StartTransaction(false, bytes, reg_number); 143 | Write(mpsse_, buffer, bytes); 144 | Stop(mpsse_); 145 | return true; 146 | } 147 | 148 | static int FtdiReadReg(unsigned reg_number, size_t bytes, void *buffer) 149 | { 150 | unsigned char *value; 151 | 152 | if (!mpsse_) 153 | return false; 154 | 155 | StartTransaction(true, bytes, reg_number); 156 | value = Read(mpsse_, bytes); 157 | if (buffer) 158 | memcpy(buffer, value, bytes); 159 | free(value); 160 | Stop(mpsse_); 161 | trace_dump("R", reg_number, bytes, buffer); 162 | return true; 163 | } 164 | 165 | static int ReadTpmSts(uint32_t *status) 166 | { 167 | return FtdiReadReg(TPM_STS_REG, sizeof(*status), status); 168 | } 169 | 170 | static int WriteTpmSts(uint32_t status) 171 | { 172 | return FtdiWriteReg(TPM_STS_REG, sizeof(status), &status); 173 | } 174 | 175 | static uint32_t GetBurstCount(void) 176 | { 177 | uint32_t status; 178 | 179 | ReadTpmSts(&status); 180 | return (status >> burstCountShift) & burstCountMask; 181 | } 182 | 183 | int FtdiSpiInit(uint32_t freq, int enable_debug) { 184 | uint32_t did_vid, status; 185 | uint8_t cmd; 186 | uint16_t vid; 187 | 188 | if (mpsse_) 189 | return true; 190 | 191 | debug_level = enable_debug; 192 | 193 | /* round frequency down to the closest 100KHz */ 194 | freq = (freq /(100 * 1000)) * 100 * 1000; 195 | 196 | printf("Starting MPSSE at %d kHz\n", freq/1000); 197 | mpsse_ = MPSSE(SPI0, freq, MSB); 198 | if (!mpsse_) 199 | return false; 200 | 201 | // Reset the TPM using GPIOL0, issue a 100 ms long pulse. 202 | PinLow(mpsse_, GPIOL0); 203 | usleep(100000); 204 | PinHigh(mpsse_, GPIOL0); 205 | 206 | FtdiReadReg(TPM_DID_VID_REG, sizeof(did_vid), &did_vid); 207 | 208 | vid = did_vid & 0xffff; 209 | if ((vid != 0x15d1) && (vid != 0x1ae0)) { 210 | fprintf(stderr, "unknown did_vid: %#x\n", did_vid); 211 | return false; 212 | } 213 | 214 | // Try claiming locality zero. 215 | FtdiReadReg(TPM_ACCESS_REG, sizeof(cmd), &cmd); 216 | if ((cmd & (activeLocality & tpmRegValidSts)) == 217 | (activeLocality & tpmRegValidSts)) { 218 | /* 219 | * Locality active - maybe reset line is not connected? 220 | * Release the locality and try again 221 | */ 222 | cmd = activeLocality; 223 | FtdiWriteReg(TPM_ACCESS_REG, sizeof(cmd), &cmd); 224 | FtdiReadReg(TPM_ACCESS_REG, sizeof(cmd), &cmd); 225 | } 226 | // tpmEstablishment can be either set or not. 227 | if ((cmd & ~(tpmEstablishment | activeLocality)) != tpmRegValidSts) { 228 | fprintf(stderr, "invalid reset status: %#x\n", cmd); 229 | return false; 230 | } 231 | cmd = requestUse; 232 | FtdiWriteReg(TPM_ACCESS_REG, sizeof(cmd), &cmd); 233 | FtdiReadReg(TPM_ACCESS_REG, sizeof(cmd), &cmd); 234 | if ((cmd & ~tpmEstablishment) != (tpmRegValidSts | activeLocality)) { 235 | fprintf(stderr, "failed to claim locality, status: %#x\n", cmd); 236 | return false; 237 | } 238 | 239 | ReadTpmSts(&status); 240 | if (((status >> tpmFamilyShift) & tpmFamilyMask) != tpmFamilyTPM2) { 241 | fprintf(stderr, "unexpected TPM family value, status: %#x\n", status); 242 | return false; 243 | } 244 | FtdiReadReg(TPM_RID_REG, sizeof(cmd), &cmd); 245 | printf("Connected to device vid:did:rid of %4.4x:%4.4x:%2.2x\n", 246 | did_vid & 0xffff, did_vid >> 16, cmd); 247 | 248 | return true; 249 | } 250 | 251 | /* This is in seconds. */ 252 | #define MAX_STATUS_TIMEOUT 120 253 | static int WaitForStatus(uint32_t statusMask, uint32_t statusExpected) 254 | { 255 | uint32_t status; 256 | time_t target_time; 257 | static unsigned max_timeout; 258 | 259 | target_time = time(NULL) + MAX_STATUS_TIMEOUT; 260 | do { 261 | usleep(10000); 262 | if (time(NULL) >= target_time) { 263 | fprintf(stderr, "failed to get expected status %x\n", statusExpected); 264 | return false; 265 | } 266 | ReadTpmSts(&status); 267 | } while ((status & statusMask) != statusExpected); 268 | 269 | /* Calculate time spent waiting */ 270 | target_time = MAX_STATUS_TIMEOUT - target_time + time(NULL); 271 | if (max_timeout < (unsigned)target_time) { 272 | max_timeout = target_time; 273 | printf("\nNew max timeout: %d s\n", max_timeout); 274 | } 275 | 276 | return true; 277 | } 278 | 279 | static void SpinSpinner(void) 280 | { 281 | static const char *spinner = "\\|/-"; 282 | static int index; 283 | 284 | if (index > strlen(spinner)) 285 | index = 0; 286 | /* 8 is the code for 'cursor left' */ 287 | fprintf(stdout, "%c%c", 8, spinner[index++]); 288 | fflush(stdout); 289 | } 290 | 291 | #define MAX_RESPONSE_SIZE 4096 292 | #define HEADER_SIZE 6 293 | 294 | /* tpm_command points at a buffer 4096 bytes in size */ 295 | size_t FtdiSendCommandAndWait(uint8_t *tpm_command, size_t command_size) 296 | { 297 | uint32_t status; 298 | uint32_t expected_status_bits; 299 | size_t handled_so_far; 300 | uint32_t payload_size; 301 | char message[100]; 302 | int offset = 0; 303 | 304 | if (!mpsse_) { 305 | fprintf(stderr, "attempt to use an uninitialized FTDI TPM!\n"); 306 | return 0; 307 | } 308 | 309 | handled_so_far = 0; 310 | 311 | WriteTpmSts(commandReady); 312 | 313 | memcpy(&payload_size, tpm_command + 2, sizeof(payload_size)); 314 | payload_size = be32toh(payload_size); 315 | offset += snprintf(message, sizeof(message), "Message size %d", payload_size); 316 | 317 | // No need to wait for the sts.Expect bit to be set, at least with the 318 | // 15d1:001b device, let's just write the command into FIFO, make sure not 319 | // to exceed the burst count. 320 | do { 321 | uint32_t transaction_size; 322 | uint32_t burst_count = GetBurstCount(); 323 | 324 | if (burst_count > 64) 325 | burst_count = 64; 326 | 327 | transaction_size = command_size - handled_so_far; 328 | if (transaction_size > burst_count) 329 | transaction_size = burst_count; 330 | 331 | if (transaction_size) { 332 | FtdiWriteReg(TPM_DATA_FIFO_REG, transaction_size, 333 | tpm_command + handled_so_far); 334 | handled_so_far += transaction_size; 335 | } 336 | } while(handled_so_far != command_size); 337 | 338 | 339 | // And tell the device it can start processing it. 340 | WriteTpmSts(tpmGo); 341 | 342 | expected_status_bits = stsValid | dataAvail; 343 | if (!WaitForStatus(expected_status_bits, expected_status_bits)) { 344 | size_t i; 345 | 346 | printf("Failed processing. %s:", message); 347 | for (i = 0; i < command_size; i++) { 348 | if (!(i % 16)) 349 | printf("\n"); 350 | printf(" %2.2x", tpm_command[i]); 351 | } 352 | printf("\n"); 353 | return 0; 354 | } 355 | 356 | // The tpm_command is ready, let's read it. 357 | // First we read the FIFO payload header, to see how much data to expect. 358 | // The header size is fixed to six bytes, the total payload size is stored 359 | // in network order in the last four bytes of the header. 360 | 361 | // Let's read the header first. 362 | FtdiReadReg(TPM_DATA_FIFO_REG, HEADER_SIZE, tpm_command); 363 | handled_so_far = HEADER_SIZE; 364 | 365 | // Figure out the total payload size. 366 | memcpy(&payload_size, tpm_command + 2, sizeof(payload_size)); 367 | payload_size = be32toh(payload_size); 368 | 369 | if (!debug_level) 370 | SpinSpinner(); 371 | 372 | if (payload_size > MAX_RESPONSE_SIZE) 373 | return 0; 374 | 375 | // Let's read all but the last byte in the FIFO to make sure the status 376 | // register is showing correct flow control bits: 'more data' until the last 377 | // byte and then 'no more data' once the last byte is read. 378 | payload_size = payload_size - 1; 379 | do { 380 | uint32_t transaction_size; 381 | uint32_t burst_count = GetBurstCount(); 382 | 383 | if (burst_count > 64) 384 | burst_count = 64; 385 | 386 | transaction_size = payload_size - handled_so_far; 387 | if (transaction_size > burst_count) 388 | transaction_size = burst_count; 389 | 390 | if (transaction_size) { 391 | FtdiReadReg(TPM_DATA_FIFO_REG, transaction_size, tpm_command + handled_so_far); 392 | handled_so_far += transaction_size; 393 | } 394 | } while(handled_so_far != payload_size); 395 | 396 | // Verify that there is still data to come. 397 | ReadTpmSts(&status); 398 | if ((status & expected_status_bits) != expected_status_bits) { 399 | fprintf(stderr, "unexpected status %#x\n", status); 400 | return 0; 401 | } 402 | 403 | FtdiReadReg(TPM_DATA_FIFO_REG, 1, tpm_command + handled_so_far); 404 | 405 | // Verify that 'data available' is not asseretd any more. 406 | ReadTpmSts(&status); 407 | if ((status & expected_status_bits) != stsValid) { 408 | fprintf(stderr, "unexpected status %#x\n", status); 409 | return 0; 410 | } 411 | 412 | /* Move the TPM back to idle state. */ 413 | WriteTpmSts(commandReady); 414 | 415 | return handled_so_far + 1; 416 | } 417 | -------------------------------------------------------------------------------- /ftdi_spi_tpm.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium OS 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 | #ifndef TRUNKS_TRUNKS_FTDI_SPI_H_ 6 | #define TRUNKS_TRUNKS_FTDI_SPI_H_ 7 | 8 | #include "config.h" 9 | #include "mpsse.h" 10 | 11 | typedef enum { 12 | false = 0, 13 | true, 14 | } bool; 15 | 16 | int FtdiSpiInit(uint32_t freq, int enable_debug); 17 | void FtdiStop(void); 18 | size_t FtdiSendCommandAndWait(uint8_t *tpm_command, size_t command_size); 19 | 20 | #endif // TRUNKS_TRUNKS_FTDI_SPI_H_ 21 | -------------------------------------------------------------------------------- /mpsse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | * 6 | * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 7 | * f1a6744b), and modified to suite the Chromium OS project. 8 | * 9 | * Main libmpsse source file. 10 | * 11 | * Craig Heffner 12 | * 27 December 2011 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "support.h" 21 | 22 | static struct mpsse_context* OpenIndex(int vid, int pid, enum modes mode, 23 | int freq, int endianess, int interface, 24 | const char* description, 25 | const char* serial, int index); 26 | 27 | /* List of known FT2232-based devices */ 28 | struct vid_pid supported_devices[] = { 29 | {0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd", 1}, 30 | {0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd"}, 31 | {0x0403, 0x6014, "FT232H Future Technology Devices International, Ltd"}, 32 | 33 | /* These devices are based on FT2232 chips, but have not been tested. */ 34 | {0x0403, 0x8878, "Bus Blaster v2 (channel A)"}, 35 | {0x0403, 0x8879, "Bus Blaster v2 (channel B)"}, 36 | {0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A"}, 37 | {0x0403, 0xCFF8, "Amontec JTAGkey"}, 38 | {0x0403, 0x8A98, "TIAO Multi Protocol Adapter"}, 39 | {0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG"}, 40 | {0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY"}, 41 | {0x18d1, 0x0304, "Google UltraDebug", 1}, 42 | 43 | {0, 0, NULL}}; 44 | 45 | /* 46 | * Opens and initializes the first FTDI device found. 47 | * 48 | * @mode - Mode to open the device in. One of enum modes. 49 | * @freq - Clock frequency to use for the specified mode. 50 | * @endianess - Specifies how data is clocked in/out (MSB, LSB). 51 | * 52 | * Returns a pointer to an MPSSE context structure if succeeded, NULL otherwise. 53 | */ 54 | struct mpsse_context* MPSSE(enum modes mode, int freq, int endianess) { 55 | int i = 0; 56 | struct mpsse_context* mpsse = NULL; 57 | 58 | for (i = 0; supported_devices[i].vid != 0; i++) { 59 | mpsse = OpenIndex(supported_devices[i].vid, supported_devices[i].pid, mode, 60 | freq, endianess, supported_devices[i].use_B ? 61 | IFACE_B : IFACE_A, 62 | NULL, NULL, 0); 63 | if (mpsse) { 64 | mpsse->description = supported_devices[i].description; 65 | return mpsse; 66 | } 67 | } 68 | 69 | return NULL; 70 | } 71 | 72 | /* 73 | * Open device by VID/PID/index 74 | * 75 | * @vid - Device vendor ID. 76 | * @pid - Device product ID. 77 | * @mode - MPSSE mode, one of enum modes. 78 | * @freq - Clock frequency to use for the specified mode. 79 | * @endianess - Specifies how data is clocked in/out (MSB, LSB). 80 | * @interface - FTDI interface to use (IFACE_A - IFACE_D). 81 | * @description - Device product description (set to NULL if not needed). 82 | * @serial - Device serial number (set to NULL if not needed). 83 | * @index - Device index (set to 0 if not needed). 84 | * 85 | * Returns a pointer to an MPSSE context structure. 86 | * On success, mpsse->open will be set to 1. 87 | * On failure, mpsse->open will be set to 0. 88 | */ 89 | static struct mpsse_context* OpenIndex(int vid, 90 | int pid, 91 | enum modes mode, 92 | int freq, 93 | int endianess, 94 | int interface, 95 | const char* description, 96 | const char* serial, 97 | int index) { 98 | int status = 0; 99 | struct mpsse_context* mpsse = NULL; 100 | 101 | mpsse = malloc(sizeof(struct mpsse_context)); 102 | if (!mpsse) 103 | return NULL; 104 | 105 | memset(mpsse, 0, sizeof(struct mpsse_context)); 106 | 107 | /* Legacy; flushing is no longer needed, so disable it by default. */ 108 | FlushAfterRead(mpsse, 0); 109 | 110 | /* ftdilib initialization */ 111 | if (ftdi_init(&mpsse->ftdi)) { 112 | free(mpsse); 113 | return NULL; 114 | } 115 | 116 | /* Set the FTDI interface */ 117 | ftdi_set_interface(&mpsse->ftdi, interface); 118 | 119 | /* Open the specified device */ 120 | if (!ftdi_usb_open_desc_index(&mpsse->ftdi, vid, pid, description, serial, 121 | index)) { 122 | mpsse->mode = mode; 123 | mpsse->vid = vid; 124 | mpsse->pid = pid; 125 | mpsse->status = STOPPED; 126 | mpsse->endianess = endianess; 127 | 128 | /* Set the appropriate transfer size for the requested protocol */ 129 | if (mpsse->mode == I2C) 130 | mpsse->xsize = I2C_TRANSFER_SIZE; 131 | else 132 | mpsse->xsize = SPI_RW_SIZE; 133 | 134 | status |= ftdi_usb_reset(&mpsse->ftdi); 135 | status |= ftdi_set_latency_timer(&mpsse->ftdi, LATENCY_MS); 136 | status |= ftdi_write_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE); 137 | status |= ftdi_read_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE); 138 | status |= ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET); 139 | 140 | if (status == 0) { 141 | /* Set the read and write timeout periods */ 142 | set_timeouts(mpsse, USB_TIMEOUT); 143 | 144 | if (mpsse->mode != BITBANG) { 145 | ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_MPSSE); 146 | 147 | if (SetClock(mpsse, freq) == MPSSE_OK) { 148 | if (SetMode(mpsse, endianess) == MPSSE_OK) { 149 | mpsse->opened = 1; 150 | 151 | /* Give the chip a few mS to initialize */ 152 | usleep(SETUP_DELAY); 153 | 154 | /* 155 | * Not all FTDI chips support all the commands that SetMode may 156 | * have sent. 157 | * This clears out any errors from unsupported commands that 158 | * might have been sent during set up. 159 | */ 160 | ftdi_usb_purge_buffers(&mpsse->ftdi); 161 | } 162 | } 163 | } else { 164 | /* Skip the setup functions if we're just operating in BITBANG mode 165 | */ 166 | if (!ftdi_set_bitmode(&mpsse->ftdi, 0xFF, BITMODE_BITBANG)) 167 | mpsse->opened = 1; 168 | } 169 | } 170 | } 171 | 172 | if (mpsse && !mpsse->opened) { 173 | Close(mpsse); 174 | mpsse = NULL; 175 | } 176 | 177 | return mpsse; 178 | } 179 | 180 | /* 181 | * Closes the device, deinitializes libftdi, and frees the MPSSE context 182 | *pointer. 183 | * 184 | * @mpsse - MPSSE context pointer. 185 | * 186 | * Returns void. 187 | */ 188 | void Close(struct mpsse_context* mpsse) { 189 | if (!mpsse) 190 | return; 191 | 192 | if (mpsse->opened) { 193 | /* Shut these down only if initialization succeeded before. */ 194 | ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET); 195 | ftdi_usb_close(&mpsse->ftdi); 196 | } 197 | ftdi_deinit(&mpsse->ftdi); 198 | free(mpsse); 199 | } 200 | 201 | /* Enables bit-wise data transfers. 202 | * Must be called after MPSSE() / Open() / OpenIndex(). 203 | * 204 | * Returns void. 205 | */ 206 | void EnableBitmode(struct mpsse_context* mpsse, int tf) { 207 | if (is_valid_context(mpsse)) { 208 | if (tf) { 209 | mpsse->tx |= MPSSE_BITMODE; 210 | mpsse->rx |= MPSSE_BITMODE; 211 | mpsse->txrx |= MPSSE_BITMODE; 212 | } else { 213 | mpsse->tx &= ~MPSSE_BITMODE; 214 | mpsse->rx &= ~MPSSE_BITMODE; 215 | mpsse->txrx &= ~MPSSE_BITMODE; 216 | } 217 | } 218 | } 219 | 220 | /* 221 | * Sets the appropriate transmit and receive commands based on the requested 222 | *mode and byte order. 223 | * 224 | * @mpsse - MPSSE context pointer. 225 | * @endianess - MPSSE_MSB or MPSSE_LSB. 226 | * 227 | * Returns MPSSE_OK on success. 228 | * Returns MPSSE_FAIL on failure. 229 | */ 230 | int SetMode(struct mpsse_context* mpsse, int endianess) { 231 | int retval = MPSSE_OK, i = 0, setup_commands_size = 0; 232 | uint8_t buf[CMD_SIZE] = {0}; 233 | uint8_t setup_commands[CMD_SIZE * MAX_SETUP_COMMANDS] = {0}; 234 | 235 | /* Do not call is_valid_context() here, as the FTDI chip may not be completely 236 | * configured when SetMode is called */ 237 | if (mpsse) { 238 | /* Read and write commands need to include endianess */ 239 | mpsse->tx = MPSSE_DO_WRITE | endianess; 240 | mpsse->rx = MPSSE_DO_READ | endianess; 241 | mpsse->txrx = MPSSE_DO_WRITE | MPSSE_DO_READ | endianess; 242 | 243 | /* Clock, data out, chip select pins are outputs; all others are inputs. */ 244 | mpsse->tris = DEFAULT_TRIS; 245 | 246 | /* Clock and chip select pins idle high; all others are low */ 247 | mpsse->pidle = mpsse->pstart = mpsse->pstop = DEFAULT_PORT; 248 | 249 | /* During reads and writes the chip select pin is brought low */ 250 | mpsse->pstart &= ~CS; 251 | 252 | /* Disable FTDI internal loopback */ 253 | SetLoopback(mpsse, 0); 254 | 255 | /* Send ACKs by default */ 256 | SetAck(mpsse, ACK); 257 | 258 | /* Ensure adaptive clock is disabled */ 259 | setup_commands[setup_commands_size++] = DISABLE_ADAPTIVE_CLOCK; 260 | 261 | switch (mpsse->mode) { 262 | case SPI0: 263 | /* SPI mode 0 clock idles low */ 264 | mpsse->pidle &= ~SK; 265 | mpsse->pstart &= ~SK; 266 | mpsse->pstop &= ~SK; 267 | /* SPI mode 0 propogates data on the falling edge and read data on the 268 | * rising edge of the clock */ 269 | mpsse->tx |= MPSSE_WRITE_NEG; 270 | mpsse->rx &= ~MPSSE_READ_NEG; 271 | mpsse->txrx |= MPSSE_WRITE_NEG; 272 | mpsse->txrx &= ~MPSSE_READ_NEG; 273 | break; 274 | case SPI3: 275 | /* SPI mode 3 clock idles high */ 276 | mpsse->pidle |= SK; 277 | mpsse->pstart |= SK; 278 | /* Keep the clock low while the CS pin is brought high to ensure we 279 | * don't accidentally clock out an extra bit */ 280 | mpsse->pstop &= ~SK; 281 | /* SPI mode 3 propogates data on the falling edge and read data on the 282 | * rising edge of the clock */ 283 | mpsse->tx |= MPSSE_WRITE_NEG; 284 | mpsse->rx &= ~MPSSE_READ_NEG; 285 | mpsse->txrx |= MPSSE_WRITE_NEG; 286 | mpsse->txrx &= ~MPSSE_READ_NEG; 287 | break; 288 | case SPI1: 289 | /* SPI mode 1 clock idles low */ 290 | mpsse->pidle &= ~SK; 291 | /* Since this mode idles low, the start condition should ensure that the 292 | * clock is low */ 293 | mpsse->pstart &= ~SK; 294 | /* Even though we idle low in this mode, we need to keep the clock line 295 | * high when we set the CS pin high to prevent 296 | * an unintended clock cycle from being sent by the FT2232. This way, 297 | * the clock goes high, but does not go low until 298 | * after the CS pin goes high. 299 | */ 300 | mpsse->pstop |= SK; 301 | /* Data read on falling clock edge */ 302 | mpsse->rx |= MPSSE_READ_NEG; 303 | mpsse->tx &= ~MPSSE_WRITE_NEG; 304 | mpsse->txrx |= MPSSE_READ_NEG; 305 | mpsse->txrx &= ~MPSSE_WRITE_NEG; 306 | break; 307 | case SPI2: 308 | /* SPI 2 clock idles high */ 309 | mpsse->pidle |= SK; 310 | mpsse->pstart |= SK; 311 | mpsse->pstop |= SK; 312 | /* Data read on falling clock edge */ 313 | mpsse->rx |= MPSSE_READ_NEG; 314 | mpsse->tx &= ~MPSSE_WRITE_NEG; 315 | mpsse->txrx |= MPSSE_READ_NEG; 316 | mpsse->txrx &= ~MPSSE_WRITE_NEG; 317 | break; 318 | case I2C: 319 | /* I2C propogates data on the falling clock edge and reads data on the 320 | * falling (or rising) clock edge */ 321 | mpsse->tx |= MPSSE_WRITE_NEG; 322 | mpsse->rx &= ~MPSSE_READ_NEG; 323 | /* In I2C, both the clock and the data lines idle high */ 324 | mpsse->pidle |= DO | DI; 325 | /* I2C start bit == data line goes from high to low while clock line is 326 | * high */ 327 | mpsse->pstart &= ~DO & ~DI; 328 | /* I2C stop bit == data line goes from low to high while clock line is 329 | * high - set data line low here, so the transition to the idle state 330 | * triggers the stop condition. */ 331 | mpsse->pstop &= ~DO & ~DI; 332 | /* Enable three phase clock to ensure that I2C data is available on both 333 | * the rising and falling clock edges */ 334 | setup_commands[setup_commands_size++] = ENABLE_3_PHASE_CLOCK; 335 | break; 336 | case GPIO: 337 | break; 338 | default: 339 | retval = MPSSE_FAIL; 340 | } 341 | 342 | /* Send any setup commands to the chip */ 343 | if (retval == MPSSE_OK && setup_commands_size > 0) { 344 | retval = raw_write(mpsse, setup_commands, setup_commands_size); 345 | } 346 | 347 | if (retval == MPSSE_OK) { 348 | /* Set the idle pin states */ 349 | set_bits_low(mpsse, mpsse->pidle); 350 | 351 | /* All GPIO pins are outputs, set low */ 352 | mpsse->trish = 0xFF; 353 | mpsse->gpioh = 0x00; 354 | 355 | buf[i++] = SET_BITS_HIGH; 356 | buf[i++] = mpsse->gpioh; 357 | buf[i++] = mpsse->trish; 358 | 359 | retval = raw_write(mpsse, buf, i); 360 | } 361 | } else { 362 | retval = MPSSE_FAIL; 363 | } 364 | 365 | return retval; 366 | } 367 | 368 | /* 369 | * Sets the appropriate divisor for the desired clock frequency. 370 | * 371 | * @mpsse - MPSSE context pointer. 372 | * @freq - Desired clock frequency in hertz. 373 | * 374 | * Returns MPSSE_OK on success. 375 | * Returns MPSSE_FAIL on failure. 376 | */ 377 | int SetClock(struct mpsse_context* mpsse, uint32_t freq) { 378 | int retval = MPSSE_FAIL; 379 | uint32_t system_clock = 0; 380 | uint16_t divisor = 0; 381 | uint8_t buf[CMD_SIZE] = {0}; 382 | 383 | /* Do not call is_valid_context() here, as the FTDI chip may not be completely 384 | * configured when SetClock is called */ 385 | if (mpsse) { 386 | if (freq > SIX_MHZ) { 387 | buf[0] = TCK_X5; 388 | system_clock = SIXTY_MHZ; 389 | } else { 390 | buf[0] = TCK_D5; 391 | system_clock = TWELVE_MHZ; 392 | } 393 | 394 | if (raw_write(mpsse, buf, 1) == MPSSE_OK) { 395 | if (freq <= 0) { 396 | divisor = 0xFFFF; 397 | } else { 398 | divisor = freq2div(system_clock, freq); 399 | } 400 | 401 | buf[0] = TCK_DIVISOR; 402 | buf[1] = (divisor & 0xFF); 403 | buf[2] = ((divisor >> 8) & 0xFF); 404 | 405 | if (raw_write(mpsse, buf, 3) == MPSSE_OK) { 406 | mpsse->clock = div2freq(system_clock, divisor); 407 | retval = MPSSE_OK; 408 | } 409 | } 410 | } 411 | 412 | return retval; 413 | } 414 | 415 | /* 416 | * Retrieves the last error string from libftdi. 417 | * 418 | * @mpsse - MPSSE context pointer. 419 | * 420 | * Returns a pointer to the last error string. 421 | */ 422 | const char* ErrorString(struct mpsse_context* mpsse) { 423 | if (mpsse != NULL) { 424 | return ftdi_get_error_string(&mpsse->ftdi); 425 | } 426 | 427 | return NULL_CONTEXT_ERROR_MSG; 428 | } 429 | 430 | /* 431 | * Gets the currently configured clock rate. 432 | * 433 | * @mpsse - MPSSE context pointer. 434 | * 435 | * Returns the existing clock rate in hertz. 436 | */ 437 | int GetClock(struct mpsse_context* mpsse) { 438 | int clock = 0; 439 | 440 | if (is_valid_context(mpsse)) { 441 | clock = mpsse->clock; 442 | } 443 | 444 | return clock; 445 | } 446 | 447 | /* 448 | * Returns the vendor ID of the FTDI chip. 449 | * 450 | * @mpsse - MPSSE context pointer. 451 | * 452 | * Returns the integer value of the vendor ID. 453 | */ 454 | int GetVid(struct mpsse_context* mpsse) { 455 | int vid = 0; 456 | 457 | if (is_valid_context(mpsse)) { 458 | vid = mpsse->vid; 459 | } 460 | 461 | return vid; 462 | } 463 | 464 | /* 465 | * Returns the product ID of the FTDI chip. 466 | * 467 | * @mpsse - MPSSE context pointer. 468 | * 469 | * Returns the integer value of the product ID. 470 | */ 471 | int GetPid(struct mpsse_context* mpsse) { 472 | int pid = 0; 473 | 474 | if (is_valid_context(mpsse)) { 475 | pid = mpsse->pid; 476 | } 477 | 478 | return pid; 479 | } 480 | 481 | /* 482 | * Returns the description of the FTDI chip, if any. 483 | * 484 | * @mpsse - MPSSE context pointer. 485 | * 486 | * Returns the description of the FTDI chip. 487 | */ 488 | const char* GetDescription(struct mpsse_context* mpsse) { 489 | char* description = NULL; 490 | 491 | if (is_valid_context(mpsse)) { 492 | description = mpsse->description; 493 | } 494 | 495 | return description; 496 | } 497 | 498 | /* 499 | * Enable / disable internal loopback. 500 | * 501 | * @mpsse - MPSSE context pointer. 502 | * @enable - Zero to disable loopback, 1 to enable loopback. 503 | * 504 | * Returns MPSSE_OK on success. 505 | * Returns MPSSE_FAIL on failure. 506 | */ 507 | int SetLoopback(struct mpsse_context* mpsse, int enable) { 508 | uint8_t buf[1] = {0}; 509 | int retval = MPSSE_FAIL; 510 | 511 | if (is_valid_context(mpsse)) { 512 | if (enable) { 513 | buf[0] = LOOPBACK_START; 514 | } else { 515 | buf[0] = LOOPBACK_END; 516 | } 517 | 518 | retval = raw_write(mpsse, buf, 1); 519 | } 520 | 521 | return retval; 522 | } 523 | 524 | /* 525 | * Sets the idle state of the chip select pin. CS idles high by default. 526 | * 527 | * @mpsse - MPSSE context pointer. 528 | * @idle - Set to 1 to idle high, 0 to idle low. 529 | * 530 | * Returns void. 531 | */ 532 | void SetCSIdle(struct mpsse_context* mpsse, int idle) { 533 | if (is_valid_context(mpsse)) { 534 | if (idle > 0) { 535 | /* Chip select idles high, active low */ 536 | mpsse->pidle |= CS; 537 | mpsse->pstop |= CS; 538 | mpsse->pstart &= ~CS; 539 | } else { 540 | /* Chip select idles low, active high */ 541 | mpsse->pidle &= ~CS; 542 | mpsse->pstop &= ~CS; 543 | mpsse->pstart |= CS; 544 | } 545 | } 546 | 547 | return; 548 | } 549 | 550 | /* 551 | * Enables or disables flushing of the FTDI chip's RX buffers after each read 552 | *operation. 553 | * Flushing is disable by default. 554 | * 555 | * @mpsse - MPSSE context pointer. 556 | * @tf - Set to 1 to enable flushing, or 0 to disable flushing. 557 | * 558 | * Returns void. 559 | */ 560 | void FlushAfterRead(struct mpsse_context* mpsse, int tf) { 561 | mpsse->flush_after_read = tf; 562 | return; 563 | } 564 | 565 | /* 566 | * Send data start condition. 567 | * 568 | * @mpsse - MPSSE context pointer. 569 | * 570 | * Returns MPSSE_OK on success. 571 | * Returns MPSSE_FAIL on failure. 572 | */ 573 | int Start(struct mpsse_context* mpsse) { 574 | int status = MPSSE_OK; 575 | 576 | if (is_valid_context(mpsse)) { 577 | if (mpsse->mode == I2C && mpsse->status == STARTED) { 578 | /* Set the default pin states while the clock is low since this is an I2C 579 | * repeated start condition */ 580 | status |= set_bits_low(mpsse, (mpsse->pidle & ~SK)); 581 | 582 | /* Make sure the pins are in their default idle state */ 583 | status |= set_bits_low(mpsse, mpsse->pidle); 584 | } 585 | 586 | /* Set the start condition */ 587 | status |= set_bits_low(mpsse, mpsse->pstart); 588 | 589 | /* 590 | * Hackish work around to properly support SPI mode 3. 591 | * SPI3 clock idles high, but needs to be set low before sending out 592 | * data to prevent unintenteded clock glitches from the FT2232. 593 | */ 594 | if (mpsse->mode == SPI3) { 595 | status |= set_bits_low(mpsse, (mpsse->pstart & ~SK)); 596 | } 597 | /* 598 | * Hackish work around to properly support SPI mode 1. 599 | * SPI1 clock idles low, but needs to be set high before sending out 600 | * data to preven unintended clock glitches from the FT2232. 601 | */ 602 | else if (mpsse->mode == SPI1) { 603 | status |= set_bits_low(mpsse, (mpsse->pstart | SK)); 604 | } 605 | 606 | mpsse->status = STARTED; 607 | } else { 608 | status = MPSSE_FAIL; 609 | mpsse->status = STOPPED; 610 | } 611 | 612 | return status; 613 | } 614 | 615 | /* 616 | * Performs a bit-wise write of up to 8 bits at a time. 617 | * 618 | * @mpsse - MPSSE context pointer. 619 | * @bits - A byte containing the desired bits to write. 620 | * @size - The number of bits from the 'bits' byte to write. 621 | * 622 | * Returns MPSSE_OK on success, MPSSE_FAIL on failure. 623 | */ 624 | int WriteBits(struct mpsse_context* mpsse, char bits, size_t size) { 625 | uint8_t data[8] = {0}; 626 | size_t i = 0; 627 | int retval = MPSSE_OK; 628 | 629 | if (size > sizeof(data)) { 630 | size = sizeof(data); 631 | } 632 | 633 | /* Convert each bit in bits to an array of bytes */ 634 | for (i = 0; i < size; i++) { 635 | if (bits & (1 << i)) { 636 | /* Be sure to honor endianess */ 637 | if (mpsse->endianess == LSB) { 638 | data[i] = '\xFF'; 639 | } else { 640 | data[size - i - 1] = '\xFF'; 641 | } 642 | } 643 | } 644 | 645 | /* Enable bit mode before writing, then disable it afterwards. */ 646 | EnableBitmode(mpsse, 1); 647 | retval = Write(mpsse, data, size); 648 | EnableBitmode(mpsse, 0); 649 | 650 | return retval; 651 | } 652 | 653 | /* 654 | * Send data out via the selected serial protocol. 655 | * 656 | * @mpsse - MPSSE context pointer. 657 | * @data - Buffer of data to send. 658 | * @size - Size of data. 659 | * 660 | * Returns MPSSE_OK on success. 661 | * Returns MPSSE_FAIL on failure. 662 | */ 663 | int Write(struct mpsse_context* mpsse, const void* vdata, int size) { 664 | const uint8_t* data = vdata; 665 | uint8_t* buf = NULL; 666 | int retval = MPSSE_FAIL, buf_size = 0, txsize = 0, n = 0; 667 | 668 | if (is_valid_context(mpsse)) { 669 | if (mpsse->mode) { 670 | while (n < size) { 671 | txsize = size - n; 672 | if (txsize > mpsse->xsize) { 673 | txsize = mpsse->xsize; 674 | } 675 | 676 | /* 677 | * For I2C we need to send each byte individually so that we can 678 | * read back each individual ACK bit, so set the transmit size to 1. 679 | */ 680 | if (mpsse->mode == I2C) { 681 | txsize = 1; 682 | } 683 | 684 | buf = build_block_buffer(mpsse, mpsse->tx, data + n, txsize, &buf_size); 685 | if (buf) { 686 | retval = raw_write(mpsse, buf, buf_size); 687 | n += txsize; 688 | free(buf); 689 | 690 | if (retval == MPSSE_FAIL) { 691 | break; 692 | } 693 | 694 | /* Read in the ACK bit and store it in mpsse->rack */ 695 | if (mpsse->mode == I2C) { 696 | raw_read(mpsse, (uint8_t*)&mpsse->rack, 1); 697 | } 698 | } else { 699 | break; 700 | } 701 | } 702 | } 703 | 704 | if (retval == MPSSE_OK && n == size) { 705 | retval = MPSSE_OK; 706 | } 707 | } 708 | 709 | return retval; 710 | } 711 | 712 | /* Performs a read. For internal use only; see Read() and ReadBits(). */ 713 | static uint8_t* InternalRead(struct mpsse_context* mpsse, int size) { 714 | uint8_t *data = NULL, *buf = NULL; 715 | uint8_t sbuf[SPI_RW_SIZE] = {0}; 716 | int n = 0, rxsize = 0, data_size = 0, retval = 0; 717 | 718 | if (is_valid_context(mpsse)) { 719 | if (mpsse->mode) { 720 | buf = malloc(size); 721 | if (buf) { 722 | memset(buf, 0, size); 723 | 724 | while (n < size) { 725 | rxsize = size - n; 726 | if (rxsize > mpsse->xsize) { 727 | rxsize = mpsse->xsize; 728 | } 729 | 730 | data = build_block_buffer(mpsse, mpsse->rx, sbuf, rxsize, &data_size); 731 | if (data) { 732 | retval = raw_write(mpsse, data, data_size); 733 | free(data); 734 | 735 | if (retval == MPSSE_OK) { 736 | n += raw_read(mpsse, buf + n, rxsize); 737 | } else { 738 | break; 739 | } 740 | } else { 741 | break; 742 | } 743 | } 744 | } 745 | } 746 | } 747 | 748 | return buf; 749 | } 750 | 751 | /* 752 | * Reads data over the selected serial protocol. 753 | * 754 | * @mpsse - MPSSE context pointer. 755 | * @size - Number of bytes to read. 756 | * 757 | * Returns a pointer to the read data on success. 758 | * Returns NULL on failure. 759 | */ 760 | #ifdef SWIGPYTHON 761 | swig_string_data Read(struct mpsse_context* mpsse, int size) 762 | #else 763 | uint8_t* Read(struct mpsse_context* mpsse, int size) 764 | #endif 765 | { 766 | uint8_t* buf = NULL; 767 | 768 | buf = InternalRead(mpsse, size); 769 | 770 | #ifdef SWIGPYTHON 771 | swig_string_data sdata = {0}; 772 | sdata.size = size; 773 | sdata.data = buf; 774 | return sdata; 775 | #else 776 | return buf; 777 | #endif 778 | } 779 | 780 | /* 781 | * Performs a bit-wise read of up to 8 bits. 782 | * 783 | * @mpsse - MPSSE context pointer. 784 | * @size - Number of bits to read. 785 | * 786 | * Returns an 8-bit byte containing the read bits. 787 | */ 788 | char ReadBits(struct mpsse_context* mpsse, int size) { 789 | char bits = 0; 790 | uint8_t* rdata = NULL; 791 | 792 | if (size > 8) { 793 | size = 8; 794 | } 795 | 796 | EnableBitmode(mpsse, 1); 797 | rdata = InternalRead(mpsse, size); 798 | EnableBitmode(mpsse, 0); 799 | 800 | if (rdata) { 801 | /* The last byte in rdata will have all the read bits set or unset as 802 | * needed. */ 803 | bits = rdata[size - 1]; 804 | 805 | if (mpsse->endianess == MSB) { 806 | /* 807 | * In MSB mode, bits are sifted in from the left. If less than 8 bits were 808 | * read, we need to shift them left accordingly. 809 | */ 810 | bits = bits << (8 - size); 811 | } else if (mpsse->endianess == LSB) { 812 | /* 813 | * In LSB mode, bits are shifted in from the right. If less than 8 bits 814 | * were 815 | * read, we need to shift them right accordingly. 816 | */ 817 | bits = bits >> (8 - size); 818 | } 819 | 820 | free(rdata); 821 | } 822 | 823 | return bits; 824 | } 825 | 826 | /* 827 | * Reads and writes data over the selected serial protocol (SPI only). 828 | * 829 | * @mpsse - MPSSE context pointer. 830 | * @data - Buffer containing bytes to write. 831 | * @size - Number of bytes to transfer. 832 | * 833 | * Returns a pointer to the read data on success. 834 | * Returns NULL on failure. 835 | */ 836 | #ifdef SWIGPYTHON 837 | swig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size) 838 | #else 839 | uint8_t* Transfer(struct mpsse_context* mpsse, uint8_t* data, int size) 840 | #endif 841 | { 842 | uint8_t *txdata = NULL, *buf = NULL; 843 | int n = 0, data_size = 0, rxsize = 0, retval = 0; 844 | 845 | if (is_valid_context(mpsse)) { 846 | /* Make sure we're configured for one of the SPI modes */ 847 | if (mpsse->mode >= SPI0 && mpsse->mode <= SPI3) { 848 | buf = malloc(size); 849 | if (buf) { 850 | memset(buf, 0, size); 851 | 852 | while (n < size) { 853 | /* When sending and recieving, FTDI chips don't seem to like large 854 | * data blocks. Limit the size of each block to SPI_TRANSFER_SIZE */ 855 | rxsize = size - n; 856 | if (rxsize > SPI_TRANSFER_SIZE) { 857 | rxsize = SPI_TRANSFER_SIZE; 858 | } 859 | 860 | txdata = 861 | build_block_buffer(mpsse, mpsse->txrx, data + n, 862 | rxsize, &data_size); 863 | if (txdata) { 864 | retval = raw_write(mpsse, txdata, data_size); 865 | free(txdata); 866 | 867 | if (retval == MPSSE_OK) { 868 | n += raw_read(mpsse, (buf + n), rxsize); 869 | } else { 870 | break; 871 | } 872 | } else { 873 | break; 874 | } 875 | } 876 | } 877 | } 878 | } 879 | 880 | #ifdef SWIGPYTHON 881 | swig_string_data sdata = {0}; 882 | sdata.size = n; 883 | sdata.data = (char*)buf; 884 | return sdata; 885 | #else 886 | return buf; 887 | #endif 888 | } 889 | 890 | /* 891 | * Returns the last received ACK bit. 892 | * 893 | * @mpsse - MPSSE context pointer. 894 | * 895 | * Returns either an ACK (0) or a NACK (1). 896 | */ 897 | int GetAck(struct mpsse_context* mpsse) { 898 | int ack = 0; 899 | 900 | if (is_valid_context(mpsse)) { 901 | ack = (mpsse->rack & 0x01); 902 | } 903 | 904 | return ack; 905 | } 906 | 907 | /* 908 | * Sets the transmitted ACK bit. 909 | * 910 | * @mpsse - MPSSE context pointer. 911 | * @ack - 0 to send ACKs, 1 to send NACKs. 912 | * 913 | * Returns void. 914 | */ 915 | void SetAck(struct mpsse_context* mpsse, int ack) { 916 | if (is_valid_context(mpsse)) { 917 | if (ack == NACK) { 918 | mpsse->tack = 0xFF; 919 | } else { 920 | mpsse->tack = 0x00; 921 | } 922 | } 923 | 924 | return; 925 | } 926 | 927 | /* 928 | * Causes libmpsse to send ACKs after each read byte in I2C mode. 929 | * 930 | * @mpsse - MPSSE context pointer. 931 | * 932 | * Returns void. 933 | */ 934 | void SendAcks(struct mpsse_context* mpsse) { 935 | return SetAck(mpsse, ACK); 936 | } 937 | 938 | /* 939 | * Causes libmpsse to send NACKs after each read byte in I2C mode. 940 | * 941 | * @mpsse - MPSSE context pointer. 942 | * 943 | * Returns void. 944 | */ 945 | void SendNacks(struct mpsse_context* mpsse) { 946 | return SetAck(mpsse, NACK); 947 | } 948 | 949 | /* 950 | * Send data stop condition. 951 | * 952 | * @mpsse - MPSSE context pointer. 953 | * 954 | * Returns MPSSE_OK on success. 955 | * Returns MPSSE_FAIL on failure. 956 | */ 957 | int Stop(struct mpsse_context* mpsse) { 958 | int retval = MPSSE_OK; 959 | 960 | if (is_valid_context(mpsse)) { 961 | /* In I2C mode, we need to ensure that the data line goes low while the 962 | * clock line is low to avoid sending an inadvertent start condition */ 963 | if (mpsse->mode == I2C) { 964 | retval |= set_bits_low(mpsse, (mpsse->pidle & ~DO & ~SK)); 965 | } 966 | 967 | /* Send the stop condition */ 968 | retval |= set_bits_low(mpsse, mpsse->pstop); 969 | 970 | if (retval == MPSSE_OK) { 971 | /* Restore the pins to their idle states */ 972 | retval |= set_bits_low(mpsse, mpsse->pidle); 973 | } 974 | 975 | mpsse->status = STOPPED; 976 | } else { 977 | retval = MPSSE_FAIL; 978 | mpsse->status = STOPPED; 979 | } 980 | 981 | return retval; 982 | } 983 | 984 | /* 985 | * Sets the specified pin high. 986 | * 987 | * @mpsse - MPSSE context pointer. 988 | * @pin - Pin number to set high. 989 | * 990 | * Returns MPSSE_OK on success. 991 | * Returns MPSSE_FAIL on failure. 992 | */ 993 | int PinHigh(struct mpsse_context* mpsse, int pin) { 994 | int retval = MPSSE_FAIL; 995 | 996 | if (is_valid_context(mpsse)) { 997 | retval = gpio_write(mpsse, pin, HIGH); 998 | } 999 | 1000 | return retval; 1001 | } 1002 | 1003 | /* 1004 | * Sets the specified pin low. 1005 | * 1006 | * @mpsse - MPSSE context pointer. 1007 | * @pin - Pin number to set low. 1008 | * 1009 | * Returns MPSSE_OK on success. 1010 | * Returns MPSSE_FAIL on failure. 1011 | */ 1012 | int PinLow(struct mpsse_context* mpsse, int pin) { 1013 | int retval = MPSSE_FAIL; 1014 | 1015 | if (is_valid_context(mpsse)) { 1016 | retval = gpio_write(mpsse, pin, LOW); 1017 | } 1018 | 1019 | return retval; 1020 | } 1021 | 1022 | /* 1023 | * Sets the input/output direction of all pins. For use in BITBANG mode only. 1024 | * 1025 | * @mpsse - MPSSE context pointer. 1026 | * @direction - Byte indicating input/output direction of each bit. 1 is out. 1027 | * 1028 | * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. 1029 | */ 1030 | int SetDirection(struct mpsse_context* mpsse, uint8_t direction) { 1031 | int retval = MPSSE_FAIL; 1032 | 1033 | if (is_valid_context(mpsse)) { 1034 | if (mpsse->mode == BITBANG) { 1035 | if (ftdi_set_bitmode(&mpsse->ftdi, direction, BITMODE_BITBANG) == 0) { 1036 | retval = MPSSE_OK; 1037 | } 1038 | } 1039 | } 1040 | 1041 | return retval; 1042 | } 1043 | 1044 | /* 1045 | * Sets the input/output value of all pins. For use in BITBANG mode only. 1046 | * 1047 | * @mpsse - MPSSE context pointer. 1048 | * @data - Byte indicating bit hi/low value of each bit. 1049 | * 1050 | * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. 1051 | */ 1052 | int WritePins(struct mpsse_context* mpsse, uint8_t data) { 1053 | int retval = MPSSE_FAIL; 1054 | 1055 | if (is_valid_context(mpsse)) { 1056 | if (mpsse->mode == BITBANG) { 1057 | if (ftdi_write_data(&mpsse->ftdi, &data, 1) == 0) { 1058 | retval = MPSSE_OK; 1059 | } 1060 | } 1061 | } 1062 | 1063 | return retval; 1064 | } 1065 | 1066 | /* 1067 | * Reads the state of the chip's pins. For use in BITBANG mode only. 1068 | * 1069 | * @mpsse - MPSSE context pointer. 1070 | * 1071 | * Returns a byte with the corresponding pin's bits set to 1 or 0. 1072 | */ 1073 | int ReadPins(struct mpsse_context* mpsse) { 1074 | uint8_t val = 0; 1075 | 1076 | if (is_valid_context(mpsse)) { 1077 | ftdi_read_pins((struct ftdi_context*)&mpsse->ftdi, (uint8_t*)&val); 1078 | } 1079 | 1080 | return (int)val; 1081 | } 1082 | 1083 | /* 1084 | * Checks if a specific pin is high or low. For use in BITBANG mode only. 1085 | * 1086 | * @mpsse - MPSSE context pointer. 1087 | * @pin - The pin number. 1088 | * @state - The state of the pins, as returned by ReadPins. 1089 | * If set to -1, ReadPins will automatically be called. 1090 | * 1091 | * Returns a 1 if the pin is high, 0 if the pin is low. 1092 | */ 1093 | int PinState(struct mpsse_context* mpsse, int pin, int state) { 1094 | if (state == -1) { 1095 | state = ReadPins(mpsse); 1096 | } 1097 | 1098 | /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert 1099 | * these defines into an absolute pin number. */ 1100 | if (mpsse->mode != BITBANG) { 1101 | pin += NUM_GPIOL_PINS; 1102 | } 1103 | 1104 | return ((state & (1 << pin)) >> pin); 1105 | } 1106 | 1107 | /* 1108 | * Places all I/O pins into a tristate mode. 1109 | * 1110 | * @mpsse - MPSSE context pointer. 1111 | * 1112 | * Returns MPSSE_OK on success, MPSSE_FAIL on failure. 1113 | */ 1114 | int Tristate(struct mpsse_context* mpsse) { 1115 | uint8_t cmd[CMD_SIZE] = {0}; 1116 | 1117 | /* Tristate the all I/O pins (FT232H only) */ 1118 | cmd[0] = TRISTATE_IO; 1119 | cmd[1] = 0xFF; 1120 | cmd[2] = 0xFF; 1121 | 1122 | return raw_write(mpsse, cmd, sizeof(cmd)); 1123 | } 1124 | -------------------------------------------------------------------------------- /mpsse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | * 6 | * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 7 | * f1a6744b), and modified to suite the Chromium OS project. 8 | */ 9 | 10 | #ifndef TRUNKS_FTDI_MPSSE_H_ 11 | #define TRUNKS_FTDI_MPSSE_H_ 12 | 13 | #include 14 | #include 15 | 16 | #define MPSSE_OK 0 17 | #define MPSSE_FAIL -1 18 | 19 | #define MSB 0x00 20 | #define LSB 0x08 21 | 22 | #define CHUNK_SIZE 65535 23 | #define SPI_RW_SIZE (63 * 1024) 24 | #define SPI_TRANSFER_SIZE 512 25 | #define I2C_TRANSFER_SIZE 64 26 | 27 | #define LATENCY_MS 2 28 | #define TIMEOUT_DIVISOR 1000000 29 | #define USB_TIMEOUT 120000 30 | #define SETUP_DELAY 25000 31 | 32 | #define BITMODE_RESET 0 33 | #define BITMODE_MPSSE 2 34 | 35 | #define CMD_SIZE 3 36 | #define MAX_SETUP_COMMANDS 10 37 | #define SS_TX_COUNT 3 38 | 39 | #define LOW 0 40 | #define HIGH 1 41 | #define NUM_GPIOL_PINS 4 42 | #define NUM_GPIO_PINS 12 43 | 44 | #define NULL_CONTEXT_ERROR_MSG "NULL MPSSE context pointer!" 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | /* FTDI interfaces */ 51 | enum interface { 52 | IFACE_ANY = INTERFACE_ANY, 53 | IFACE_A = INTERFACE_A, 54 | IFACE_B = INTERFACE_B, 55 | IFACE_C = INTERFACE_C, 56 | IFACE_D = INTERFACE_D 57 | }; 58 | 59 | /* Common clock rates */ 60 | enum clock_rates { 61 | ONE_HUNDRED_KHZ = 100000, 62 | FOUR_HUNDRED_KHZ = 400000, 63 | ONE_MHZ = 1000000, 64 | TWO_MHZ = 2000000, 65 | FIVE_MHZ = 5000000, 66 | SIX_MHZ = 6000000, 67 | TEN_MHZ = 10000000, 68 | TWELVE_MHZ = 12000000, 69 | FIFTEEN_MHZ = 15000000, 70 | THIRTY_MHZ = 30000000, 71 | SIXTY_MHZ = 60000000 72 | }; 73 | 74 | /* Supported MPSSE modes */ 75 | enum modes { 76 | SPI0 = 1, 77 | SPI1 = 2, 78 | SPI2 = 3, 79 | SPI3 = 4, 80 | I2C = 5, 81 | GPIO = 6, 82 | BITBANG = 7, 83 | }; 84 | 85 | enum pins { 86 | SK = 1, 87 | DO = 2, 88 | DI = 4, 89 | CS = 8, 90 | GPIO0 = 16, 91 | GPIO1 = 32, 92 | GPIO2 = 64, 93 | GPIO3 = 128 94 | }; 95 | 96 | enum gpio_pins { 97 | GPIOL0 = 0, 98 | GPIOL1 = 1, 99 | GPIOL2 = 2, 100 | GPIOL3 = 3, 101 | GPIOH0 = 4, 102 | GPIOH1 = 5, 103 | GPIOH2 = 6, 104 | GPIOH3 = 7, 105 | GPIOH4 = 8, 106 | GPIOH5 = 9, 107 | GPIOH6 = 10, 108 | GPIOH7 = 11 109 | }; 110 | 111 | enum i2c_ack { ACK = 0, NACK = 1 }; 112 | 113 | /* SK/DO/CS and GPIOs are outputs, DI is an input */ 114 | #define DEFAULT_TRIS (SK | DO | CS | GPIO0 | GPIO1 | GPIO2 | GPIO3) 115 | /* SK, CS and reset are high, the rest are low */ 116 | #define DEFAULT_PORT (SK | CS | GPIO1) 117 | 118 | enum mpsse_commands { 119 | INVALID_COMMAND = 0xAB, 120 | ENABLE_ADAPTIVE_CLOCK = 0x96, 121 | DISABLE_ADAPTIVE_CLOCK = 0x97, 122 | ENABLE_3_PHASE_CLOCK = 0x8C, 123 | DISABLE_3_PHASE_CLOCK = 0x8D, 124 | TCK_X5 = 0x8A, 125 | TCK_D5 = 0x8B, 126 | CLOCK_N_CYCLES = 0x8E, 127 | CLOCK_N8_CYCLES = 0x8F, 128 | PULSE_CLOCK_IO_HIGH = 0x94, 129 | PULSE_CLOCK_IO_LOW = 0x95, 130 | CLOCK_N8_CYCLES_IO_HIGH = 0x9C, 131 | CLOCK_N8_CYCLES_IO_LOW = 0x9D, 132 | TRISTATE_IO = 0x9E, 133 | }; 134 | 135 | enum low_bits_status { STARTED, STOPPED }; 136 | 137 | struct vid_pid { 138 | int vid; 139 | int pid; 140 | char* description; 141 | int use_B; 142 | }; 143 | 144 | struct mpsse_context { 145 | char* description; 146 | struct ftdi_context ftdi; 147 | enum modes mode; 148 | enum low_bits_status status; 149 | int flush_after_read; 150 | int vid; 151 | int pid; 152 | int clock; 153 | int xsize; 154 | uint8_t endianess; 155 | uint8_t opened; 156 | uint8_t tris; 157 | uint8_t pstart; 158 | uint8_t pstop; 159 | uint8_t pidle; 160 | uint8_t gpioh; 161 | uint8_t trish; 162 | uint8_t bitbang; 163 | uint8_t tx; 164 | uint8_t rx; 165 | uint8_t txrx; 166 | uint8_t tack; 167 | uint8_t rack; 168 | }; 169 | 170 | struct mpsse_context* MPSSE(enum modes mode, int freq, int endianess); 171 | void Close(struct mpsse_context* mpsse); 172 | const char* ErrorString(struct mpsse_context* mpsse); 173 | int SetMode(struct mpsse_context* mpsse, int endianess); 174 | void EnableBitmode(struct mpsse_context* mpsse, int tf); 175 | int SetClock(struct mpsse_context* mpsse, uint32_t freq); 176 | int GetClock(struct mpsse_context* mpsse); 177 | int GetVid(struct mpsse_context* mpsse); 178 | int GetPid(struct mpsse_context* mpsse); 179 | const char* GetDescription(struct mpsse_context* mpsse); 180 | int SetLoopback(struct mpsse_context* mpsse, int enable); 181 | void SetCSIdle(struct mpsse_context* mpsse, int idle); 182 | int Start(struct mpsse_context* mpsse); 183 | int Write(struct mpsse_context* mpsse, const void* data, int size); 184 | int Stop(struct mpsse_context* mpsse); 185 | int GetAck(struct mpsse_context* mpsse); 186 | void SetAck(struct mpsse_context* mpsse, int ack); 187 | void SendAcks(struct mpsse_context* mpsse); 188 | void SendNacks(struct mpsse_context* mpsse); 189 | void FlushAfterRead(struct mpsse_context* mpsse, int tf); 190 | int PinHigh(struct mpsse_context* mpsse, int pin); 191 | int PinLow(struct mpsse_context* mpsse, int pin); 192 | int SetDirection(struct mpsse_context* mpsse, uint8_t direction); 193 | int WriteBits(struct mpsse_context* mpsse, char bits, size_t size); 194 | char ReadBits(struct mpsse_context* mpsse, int size); 195 | int WritePins(struct mpsse_context* mpsse, uint8_t data); 196 | int ReadPins(struct mpsse_context* mpsse); 197 | int PinState(struct mpsse_context* mpsse, int pin, int state); 198 | int Tristate(struct mpsse_context* mpsse); 199 | char Version(void); 200 | 201 | #ifdef SWIGPYTHON 202 | typedef struct swig_string_data { 203 | int size; 204 | char* data; 205 | } swig_string_data; 206 | 207 | swig_string_data Read(struct mpsse_context* mpsse, int size); 208 | swig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size); 209 | #else 210 | uint8_t* Read(struct mpsse_context* mpsse, int size); 211 | uint8_t* Transfer(struct mpsse_context* mpsse, 212 | uint8_t* data, int size); 213 | 214 | int FastWrite(struct mpsse_context* mpsse, char* data, int size); 215 | int FastRead(struct mpsse_context* mpsse, char* data, int size); 216 | int FastTransfer(struct mpsse_context* mpsse, 217 | char* wdata, 218 | char* rdata, 219 | int size); 220 | #endif 221 | #ifdef __cplusplus 222 | } 223 | #endif 224 | #endif /* TRUNKS_FTDI_MPSSE_H_ */ 225 | -------------------------------------------------------------------------------- /ntpm.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "ftdi_spi_tpm.h" 12 | #include "tpm2lib_wrapper.h" 13 | 14 | #define SOCKET_ERROR -1 15 | 16 | static struct tpm_driver { 17 | /* Parameter(s) may be irrelevant for some drivers. */ 18 | int (*drv_init)(uint32_t freq, int debug); 19 | size_t (*drv_process)(uint8_t *message, size_t message_size); 20 | void (*drv_stop)(void); /* Could be NULL. */ 21 | } drivers[] = { 22 | {FtdiSpiInit, FtdiSendCommandAndWait, FtdiStop}, 23 | {Tpm2LibInit, Tpm2LibProcess} 24 | }; 25 | 26 | const static char *help_msg = 27 | " Command line options:\n" 28 | " -d[d] - enable debug tracing (more d's - more debug)\n" 29 | " -f NUM - ftdi clock frequency\n" 30 | " -p NUM - port number\n" 31 | " -s - use simulator instead of the USB interface\n"; 32 | 33 | int main( int argc, char *argv[] ) 34 | { 35 | // create and open network socket 36 | struct sockaddr_in serv_addr; 37 | int sockfd; 38 | int opt; 39 | uint16_t port = 9883; /* default port */ 40 | uint32_t freq = 1000 * 1000; /* Default frequency 1 MHz */ 41 | int driver_index = 0; 42 | int debug_level = 0; 43 | int c; 44 | 45 | debug_level = 0; 46 | 47 | while ((c = getopt(argc, argv, "df:p:s")) != -1) { 48 | switch (c) { 49 | case 'd': 50 | debug_level++; 51 | break; 52 | case 'f': 53 | freq = atoi(optarg); 54 | break; 55 | case 'p': 56 | port = atoi(optarg); 57 | break; 58 | case 's': 59 | driver_index = 1; 60 | break; 61 | case '?': 62 | if ((optopt == 'p') || (optopt == 'f')) { 63 | fprintf (stderr, "Option -%c requires an argument.\n", optopt); 64 | return -1; 65 | } 66 | if (!isprint (optopt)) 67 | fprintf (stderr, "Unknown option character \\x%x'.\n", optopt); 68 | default: 69 | fprintf(stderr, "%s", help_msg); 70 | return -2; 71 | } 72 | } 73 | 74 | sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 75 | if (sockfd == SOCKET_ERROR) { 76 | fprintf(stderr, "failed to create socket, error %s\n", strerror(errno)); 77 | return -1; 78 | } 79 | 80 | memset( (char *) &serv_addr, 0, sizeof( serv_addr ) ); 81 | 82 | printf("Opening socket on port %d\n", port); 83 | serv_addr.sin_family = AF_INET; 84 | serv_addr.sin_addr.s_addr = INADDR_ANY; 85 | serv_addr.sin_port = htons(port); 86 | 87 | opt = 1; 88 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)); 89 | 90 | if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) { 91 | fprintf(stderr, "failed to bind, error %s\n", strerror(errno)); 92 | return -1; 93 | } 94 | 95 | if (listen(sockfd, 1) == SOCKET_ERROR) { 96 | fprintf(stderr, "Error %s on listen()\n", strerror(errno)); 97 | return -1; 98 | } 99 | 100 | if (!drivers[driver_index].drv_init(freq, debug_level)) { 101 | fprintf(stderr, "Failed to initialize FTDI SPI\n"); 102 | return -1; 103 | } 104 | 105 | while (true) { 106 | // main loop 107 | uint8_t buffer[4096]; 108 | int len; 109 | int newsockfd; 110 | 111 | printf("\nWaiting for new connection..."); 112 | fflush(stdout); 113 | newsockfd = accept(sockfd, 0, 0); 114 | if (newsockfd == SOCKET_ERROR) { 115 | fprintf(stderr, "ERROR on accept (%s)\n", strerror(errno)); 116 | shutdown(sockfd, SHUT_RDWR); 117 | return -1; 118 | } 119 | printf("connected.\n"); 120 | 121 | do { 122 | int written = 0; 123 | 124 | len = recv(newsockfd, (char*) buffer, sizeof(buffer), 0); 125 | 126 | if ( len == SOCKET_ERROR ) { 127 | fprintf(stderr, "ERROR reading from socket %s\n", strerror(errno)); 128 | break; 129 | } 130 | if (!len) { 131 | /* Socket reset on the client side. */ 132 | continue; 133 | } 134 | 135 | // write command to TPM and read result 136 | len = drivers[driver_index].drv_process(buffer, len); 137 | 138 | // write result to network 139 | while (written != len) { 140 | int count = send(newsockfd, buffer + written, len - written, 0); 141 | if (count == SOCKET_ERROR ) 142 | fprintf(stderr, "ERROR writing to socket (%s)\n", strerror(errno)); 143 | written += count; 144 | } 145 | } while ( len > 0 ); 146 | shutdown(newsockfd, SHUT_RDWR); 147 | } 148 | 149 | shutdown(sockfd, SHUT_RDWR); 150 | if (drivers[driver_index].drv_stop) 151 | drivers[driver_index].drv_stop(); 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /support.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | * 6 | * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 7 | * f1a6744b), and modified to suite the Chromium OS project. 8 | * 9 | * Internal functions used by libmpsse. 10 | * 11 | * Craig Heffner 12 | * 27 December 2011 13 | */ 14 | 15 | #include 16 | 17 | #include "support.h" 18 | 19 | /* Write data to the FTDI chip */ 20 | int raw_write(struct mpsse_context* mpsse, uint8_t* buf, int size) { 21 | int retval = MPSSE_FAIL; 22 | 23 | if (mpsse->mode) { 24 | if (ftdi_write_data(&mpsse->ftdi, buf, size) == size) { 25 | retval = MPSSE_OK; 26 | } 27 | } 28 | 29 | return retval; 30 | } 31 | 32 | /* Read data from the FTDI chip */ 33 | int raw_read(struct mpsse_context* mpsse, uint8_t* buf, int size) { 34 | int n = 0, r = 0; 35 | 36 | if (mpsse->mode) { 37 | while (n < size) { 38 | r = ftdi_read_data(&mpsse->ftdi, buf, size); 39 | if (r < 0) 40 | break; 41 | n += r; 42 | } 43 | 44 | if (mpsse->flush_after_read) { 45 | /* 46 | * Make sure the buffers are cleared after a read or subsequent reads may 47 | *fail. 48 | * 49 | * Is this needed anymore? It slows down repetitive read operations by 50 | *~8%. 51 | */ 52 | ftdi_usb_purge_rx_buffer(&mpsse->ftdi); 53 | } 54 | } 55 | 56 | return n; 57 | } 58 | 59 | /* Sets the read and write timeout periods for bulk usb data transfers. */ 60 | void set_timeouts(struct mpsse_context* mpsse, int timeout) { 61 | if (mpsse->mode) { 62 | mpsse->ftdi.usb_read_timeout = timeout; 63 | mpsse->ftdi.usb_write_timeout = timeout; 64 | } 65 | 66 | return; 67 | } 68 | 69 | /* Convert a frequency to a clock divisor */ 70 | uint16_t freq2div(uint32_t system_clock, uint32_t freq) { 71 | return (((system_clock / freq) / 2) - 1); 72 | } 73 | 74 | /* Convert a clock divisor to a frequency */ 75 | uint32_t div2freq(uint32_t system_clock, uint16_t div) { 76 | return (system_clock / ((1 + div) * 2)); 77 | } 78 | 79 | /* Builds a buffer of commands + data blocks */ 80 | uint8_t* build_block_buffer(struct mpsse_context* mpsse, 81 | uint8_t cmd, 82 | const uint8_t* data, 83 | int size, 84 | int* buf_size) { 85 | uint8_t* buf = NULL; 86 | int i = 0, j = 0, k = 0, dsize = 0, num_blocks = 0, total_size = 0, 87 | xfer_size = 0; 88 | uint16_t rsize = 0; 89 | 90 | *buf_size = 0; 91 | 92 | /* Data block size is 1 in I2C, or when in bitmode */ 93 | if (mpsse->mode == I2C || (cmd & MPSSE_BITMODE)) { 94 | xfer_size = 1; 95 | } else { 96 | xfer_size = mpsse->xsize; 97 | } 98 | 99 | num_blocks = (size / xfer_size); 100 | if (size % xfer_size) { 101 | num_blocks++; 102 | } 103 | 104 | /* The total size of the data will be the data size + the write command */ 105 | total_size = size + (CMD_SIZE * num_blocks); 106 | 107 | /* In I2C we have to add 3 additional commands per data block */ 108 | if (mpsse->mode == I2C) { 109 | total_size += (CMD_SIZE * 3 * num_blocks); 110 | } 111 | 112 | buf = malloc(total_size); 113 | if (buf) { 114 | memset(buf, 0, total_size); 115 | 116 | for (j = 0; j < num_blocks; j++) { 117 | dsize = size - k; 118 | if (dsize > xfer_size) { 119 | dsize = xfer_size; 120 | } 121 | 122 | /* The reported size of this block is block size - 1 */ 123 | rsize = dsize - 1; 124 | 125 | /* For I2C we need to ensure that the clock pin is set low prior to 126 | * clocking out data */ 127 | if (mpsse->mode == I2C) { 128 | buf[i++] = SET_BITS_LOW; 129 | buf[i++] = mpsse->pstart & ~SK; 130 | 131 | /* On receive, we need to ensure that the data out line is set as an 132 | * input to avoid contention on the bus */ 133 | if (cmd == mpsse->rx) { 134 | buf[i++] = mpsse->tris & ~DO; 135 | } else { 136 | buf[i++] = mpsse->tris; 137 | } 138 | } 139 | 140 | /* Copy in the command for this block */ 141 | buf[i++] = cmd; 142 | buf[i++] = (rsize & 0xFF); 143 | if (!(cmd & MPSSE_BITMODE)) { 144 | buf[i++] = ((rsize >> 8) & 0xFF); 145 | } 146 | 147 | /* On a write, copy the data to transmit after the command */ 148 | if (cmd == mpsse->tx || cmd == mpsse->txrx) { 149 | memcpy(buf + i, data + k, dsize); 150 | 151 | /* i == offset into buf */ 152 | i += dsize; 153 | /* k == offset into data */ 154 | k += dsize; 155 | } 156 | 157 | /* In I2C mode we need to clock one ACK bit after each byte */ 158 | if (mpsse->mode == I2C) { 159 | /* If we are receiving data, then we need to clock out an ACK for each 160 | * byte */ 161 | if (cmd == mpsse->rx) { 162 | buf[i++] = SET_BITS_LOW; 163 | buf[i++] = mpsse->pstart & ~SK; 164 | buf[i++] = mpsse->tris; 165 | 166 | buf[i++] = mpsse->tx | MPSSE_BITMODE; 167 | buf[i++] = 0; 168 | buf[i++] = mpsse->tack; 169 | } 170 | /* If we are sending data, then we need to clock in an ACK for each byte 171 | */ 172 | else if (cmd == mpsse->tx) { 173 | /* Need to make data out an input to avoid contention on the bus when 174 | * the slave sends an ACK */ 175 | buf[i++] = SET_BITS_LOW; 176 | buf[i++] = mpsse->pstart & ~SK; 177 | buf[i++] = mpsse->tris & ~DO; 178 | 179 | buf[i++] = mpsse->rx | MPSSE_BITMODE; 180 | buf[i++] = 0; 181 | buf[i++] = SEND_IMMEDIATE; 182 | } 183 | } 184 | } 185 | 186 | *buf_size = i; 187 | } 188 | 189 | return buf; 190 | } 191 | 192 | /* Set the low bit pins high/low */ 193 | int set_bits_low(struct mpsse_context* mpsse, int port) { 194 | char buf[CMD_SIZE] = {0}; 195 | 196 | buf[0] = SET_BITS_LOW; 197 | buf[1] = port; 198 | buf[2] = mpsse->tris; 199 | 200 | return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf)); 201 | } 202 | 203 | /* Set the high bit pins high/low */ 204 | int set_bits_high(struct mpsse_context* mpsse, int port) { 205 | char buf[CMD_SIZE] = {0}; 206 | 207 | buf[0] = SET_BITS_HIGH; 208 | buf[1] = port; 209 | buf[2] = mpsse->trish; 210 | 211 | return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf)); 212 | } 213 | 214 | /* Set the GPIO pins high/low */ 215 | int gpio_write(struct mpsse_context* mpsse, int pin, int direction) { 216 | int retval = MPSSE_FAIL; 217 | 218 | if (mpsse->mode == BITBANG) { 219 | if (direction == HIGH) { 220 | mpsse->bitbang |= (1 << pin); 221 | } else { 222 | mpsse->bitbang &= ~(1 << pin); 223 | } 224 | 225 | if (set_bits_high(mpsse, mpsse->bitbang) == MPSSE_OK) { 226 | retval = raw_write(mpsse, (uint8_t*)&mpsse->bitbang, 1); 227 | } 228 | } else { 229 | /* The first four pins can't be changed unless we are in a stopped status */ 230 | if (pin < NUM_GPIOL_PINS && mpsse->status == STOPPED) { 231 | /* Convert pin number (0-3) to the corresponding pin bit */ 232 | pin = (GPIO0 << pin); 233 | 234 | if (direction == HIGH) { 235 | mpsse->pstart |= pin; 236 | mpsse->pidle |= pin; 237 | mpsse->pstop |= pin; 238 | } else { 239 | mpsse->pstart &= ~pin; 240 | mpsse->pidle &= ~pin; 241 | mpsse->pstop &= ~pin; 242 | } 243 | 244 | retval = set_bits_low(mpsse, mpsse->pstop); 245 | } else if (pin >= NUM_GPIOL_PINS && pin < NUM_GPIO_PINS) { 246 | /* Convert pin number (4 - 11) to the corresponding pin bit */ 247 | pin -= NUM_GPIOL_PINS; 248 | 249 | if (direction == HIGH) { 250 | mpsse->gpioh |= (1 << pin); 251 | } else { 252 | mpsse->gpioh &= ~(1 << pin); 253 | } 254 | 255 | retval = set_bits_high(mpsse, mpsse->gpioh); 256 | } 257 | } 258 | 259 | return retval; 260 | } 261 | 262 | /* Checks if a given MPSSE context is valid. */ 263 | int is_valid_context(struct mpsse_context* mpsse) { 264 | return mpsse != NULL; 265 | } 266 | -------------------------------------------------------------------------------- /support.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | * 6 | * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 7 | * f1a6744b), and modified to suite the Chromium OS project. 8 | */ 9 | 10 | #ifndef TRUNKS_FTDI_SUPPORT_H_ 11 | #define TRUNKS_FTDI_SUPPORT_H_ 12 | 13 | #include "mpsse.h" 14 | 15 | int raw_write(struct mpsse_context* mpsse, uint8_t* buf, int size); 16 | int raw_read(struct mpsse_context* mpsse, uint8_t* buf, int size); 17 | void set_timeouts(struct mpsse_context* mpsse, int timeout); 18 | uint16_t freq2div(uint32_t system_clock, uint32_t freq); 19 | uint32_t div2freq(uint32_t system_clock, uint16_t div); 20 | uint8_t* build_block_buffer(struct mpsse_context* mpsse, 21 | uint8_t cmd, 22 | const uint8_t* data, 23 | int size, 24 | int* buf_size); 25 | int set_bits_high(struct mpsse_context* mpsse, int port); 26 | int set_bits_low(struct mpsse_context* mpsse, int port); 27 | int gpio_write(struct mpsse_context* mpsse, int pin, int direction); 28 | int is_valid_context(struct mpsse_context* mpsse); 29 | 30 | #endif /* TRUNKS_FTDI_SUPPORT_H_ */ 31 | -------------------------------------------------------------------------------- /tcgt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TCG_ROOT="${TCG_ROOT:-"$(readlink -f "$(dirname $0)"/../build/test-tpm2)"}" 4 | last_success='.last_success' 5 | 6 | if [ -f "${last_success}" ]; then 7 | skip=1 8 | until="$(cat "${last_success}")" 9 | fi 10 | 11 | # List of tests which are known to fail on the simulator (none at this time). 12 | excludes='noncence' 13 | 14 | if [ "${1}" == '-h' ]; then 15 | cat < "${last_success}" 71 | fi 72 | else 73 | echo 'excluded' 74 | continue 75 | fi 76 | done 77 | echo "${count} tests passed" 78 | -------------------------------------------------------------------------------- /tpm2lib_wrapper.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include <_TPM_Init_fp.h> 11 | 12 | #include "tpm2lib_wrapper.h" 13 | 14 | static int enable_debug; 15 | 16 | static void dump_message(const char *prefix, 17 | uint8_t *message, size_t message_size) 18 | { 19 | uint32_t length, type, i; 20 | 21 | if (!enable_debug) 22 | return; 23 | 24 | if (message_size < 10) { 25 | printf("misformatted %s, %zd bytes\n", prefix, message_size); 26 | return; 27 | } 28 | 29 | memcpy(&length, message + 2, sizeof(length)); 30 | memcpy(&type, message + 6, sizeof(type)); 31 | 32 | length = be32toh(length); 33 | type = be32toh(type); 34 | 35 | printf("%s of type %3x, length %d", prefix, type, length); 36 | if (length != message_size) 37 | printf(" message size %zd", message_size); 38 | for (i = 0; i < message_size; i++) { 39 | if (!(i % BYTES_PER_LINE)) 40 | printf("\n"); 41 | printf(" %2.2x", message[i]); 42 | } 43 | printf("\n"); 44 | } 45 | 46 | int Tpm2LibInit(uint32_t freq, int debug) 47 | { 48 | /* TPM2 library initialization functions. */ 49 | printf("Initiazling tpm2 simulator\n"); 50 | _plat__Signal_PowerOn(); 51 | _plat__NVEnable(NULL); 52 | if (TPM_Manufacture(TRUE)) { 53 | printf("Manufacture Initialization failed\n"); 54 | return 1; 55 | } 56 | if (TPM_Manufacture(FALSE) != 1) { 57 | printf("Manufacture Re-Initialization failed\n"); 58 | return 1; 59 | } 60 | TPM_TearDown(); 61 | if(TPM_Manufacture(TRUE)) { 62 | printf("Teardown failed\n"); 63 | return 1; 64 | } 65 | // Disable NV memory 66 | _plat__NVDisable(); 67 | _TPM_Init(); 68 | _plat__SetNvAvail(); 69 | 70 | enable_debug = debug; 71 | return 1; 72 | } 73 | 74 | 75 | 76 | size_t Tpm2LibProcess(uint8_t *message, size_t message_size) 77 | { 78 | void *response; 79 | unsigned response_size; 80 | 81 | dump_message("Command", message, message_size); 82 | ExecuteCommand(message_size, message, &response_size, (uint8_t **)&response); 83 | memset(message, 0xaa, 4096); 84 | memcpy(message, response, response_size); 85 | dump_message("Response", message, response_size); 86 | 87 | return response_size; 88 | } 89 | -------------------------------------------------------------------------------- /tpm2lib_wrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef __FTDI_TPM2LIB_WRAPPER_C 2 | #define __FTDI_TPM2LIB_WRAPPER_C 3 | 4 | #include 5 | #include 6 | 7 | #include "config.h" 8 | 9 | int Tpm2LibInit(uint32_t freq, int debug); 10 | size_t Tpm2LibProcess(uint8_t *message, size_t message_size); 11 | 12 | #endif // __FTDI_TPM2LIB_WRAPPER_C 13 | --------------------------------------------------------------------------------