├── 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 |
--------------------------------------------------------------------------------