blob: b4d9a307ca997dc686c964a370143f6a73704542 [file] [log] [blame]
hailfinger37b4fbf2009-06-23 11:33:43 +00001/*
2 * This file is part of the flashrom project.
3 *
stefanct69965b62011-09-15 23:38:14 +00004 * Copyright (C) 2009, 2011 Urja Rannikko <urjaman@gmail.com>
hailfinger37b4fbf2009-06-23 11:33:43 +00005 * Copyright (C) 2009 Carl-Daniel Hailfinger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
hailfinger37b4fbf2009-06-23 11:33:43 +000016 */
17
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110018#include "platform.h"
19
hailfinger4f45a4f2009-08-12 13:32:56 +000020#include <stdio.h>
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110021#if ! IS_WINDOWS /* stuff (presumably) needed for sockets only */
hailfinger37b4fbf2009-06-23 11:33:43 +000022#include <stdlib.h>
hailfinger4f45a4f2009-08-12 13:32:56 +000023#include <unistd.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000024#include <fcntl.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000025#include <sys/socket.h>
26#include <arpa/inet.h>
27#include <netinet/in.h>
28#include <netinet/tcp.h>
29#include <netdb.h>
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110030#endif
31#if IS_WINDOWS
32#include <conio.h>
33#else
34#include <termios.h>
35#endif
36#include <string.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000037#include <errno.h>
hailfinger428f6852010-07-27 22:41:39 +000038#include "flash.h"
39#include "programmer.h"
stefanct69965b62011-09-15 23:38:14 +000040#include "chipdrivers.h"
Patrick Georgib9fe7f12017-04-11 20:35:19 +020041#include "serprog.h"
hailfingerbacbc8b2009-07-21 13:02:59 +000042
stefanctd9ac2212011-10-22 21:45:27 +000043#define MSGHEADER "serprog: "
hailfingerbacbc8b2009-07-21 13:02:59 +000044
dhendrix0ffc2eb2011-06-14 01:35:36 +000045/*
46 * FIXME: This prototype was added to help reduce diffs for the shutdown
47 * registration patch, which shifted many lines of code to place
48 * serprog_shutdown() before serprog_init(). It should be removed soon.
49 */
David Hendricks93784b42016-08-09 17:00:38 -070050static int serprog_shutdown(void *data);
dhendrix0ffc2eb2011-06-14 01:35:36 +000051
hailfingerbacbc8b2009-07-21 13:02:59 +000052static uint16_t sp_device_serbuf_size = 16;
53static uint16_t sp_device_opbuf_size = 300;
54/* Bitmap of supported commands */
55static uint8_t sp_cmdmap[32];
56
uwe3a3ab2f2010-03-25 23:18:41 +000057/* sp_prev_was_write used to detect writes with contiguous addresses
hailfingerbacbc8b2009-07-21 13:02:59 +000058 and combine them to write-n's */
59static int sp_prev_was_write = 0;
60/* sp_write_n_addr used as the starting addr of the currently
61 combined write-n operation */
62static uint32_t sp_write_n_addr;
63/* The maximum length of an write_n operation; 0 = write-n not supported */
64static uint32_t sp_max_write_n = 0;
65/* The maximum length of a read_n operation; 0 = 2^24 */
66static uint32_t sp_max_read_n = 0;
67
68/* A malloc'd buffer for combining the operation's data
69 and a counter that tells how much data is there. */
70static uint8_t *sp_write_n_buf;
71static uint32_t sp_write_n_bytes = 0;
72
73/* sp_streamed_* used for flow control checking */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110074static unsigned int sp_streamed_transmit_ops = 0;
75static unsigned int sp_streamed_transmit_bytes = 0;
hailfingerbacbc8b2009-07-21 13:02:59 +000076
77/* sp_opbuf_usage used for counting the amount of
78 on-device operation buffer used */
79static int sp_opbuf_usage = 0;
80/* if true causes sp_docommand to automatically check
81 whether the command is supported before doing it */
82static int sp_check_avail_automatic = 0;
83
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110084#if ! IS_WINDOWS
hailfingerbacbc8b2009-07-21 13:02:59 +000085static int sp_opensocket(char *ip, unsigned int port)
86{
87 int flag = 1;
88 struct hostent *hostPtr = NULL;
hailfinger3e454f32009-09-05 01:10:23 +000089 union { struct sockaddr_in si; struct sockaddr s; } sp = {};
hailfingerbacbc8b2009-07-21 13:02:59 +000090 int sock;
snelson0afd28b2010-01-10 01:06:23 +000091 msg_pdbg(MSGHEADER "IP %s port %d\n", ip, port);
hailfingerbacbc8b2009-07-21 13:02:59 +000092 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110093 if (sock < 0) {
94 msg_perr("Error: serprog cannot open socket: %s\n", strerror(errno));
95 return -1;
96 }
hailfingerbacbc8b2009-07-21 13:02:59 +000097 hostPtr = gethostbyname(ip);
98 if (NULL == hostPtr) {
99 hostPtr = gethostbyaddr(ip, strlen(ip), AF_INET);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100100 if (NULL == hostPtr) {
101 close(sock);
102 msg_perr("Error: cannot resolve %s\n", ip);
103 return -1;
104 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000105 }
hailfinger3e454f32009-09-05 01:10:23 +0000106 sp.si.sin_family = AF_INET;
107 sp.si.sin_port = htons(port);
Edward O'Callaghan9987ad42019-09-03 15:58:56 +1000108 (void)memcpy(&sp.si.sin_addr, hostPtr->h_addr_list[0], hostPtr->h_length);
hailfinger3e454f32009-09-05 01:10:23 +0000109 if (connect(sock, &sp.s, sizeof(sp.si)) < 0) {
hailfingerbacbc8b2009-07-21 13:02:59 +0000110 close(sock);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100111 msg_perr("Error: serprog cannot connect: %s\n", strerror(errno));
112 return -1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000113 }
114 /* We are latency limited, and sometimes do write-write-read *
115 * (write-n) - so enable TCP_NODELAY. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100116 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) {
117 close(sock);
118 msg_perr("Error: serprog cannot set socket options: %s\n", strerror(errno));
119 return -1;
120 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000121 return sock;
122}
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100123#endif
hailfingerbacbc8b2009-07-21 13:02:59 +0000124
uwe3a3ab2f2010-03-25 23:18:41 +0000125/* Synchronize: a bit tricky algorithm that tries to (and in my tests has *
hailfingerbacbc8b2009-07-21 13:02:59 +0000126 * always succeeded in) bring the serial protocol to known waiting-for- *
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100127 * command state - uses nonblocking I/O - rest of the driver uses *
hailfingerbacbc8b2009-07-21 13:02:59 +0000128 * blocking read - TODO: add an alarm() timer for the rest of the app on *
129 * serial operations, though not such a big issue as the first thing to *
130 * do is synchronize (eg. check that device is alive). */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100131static int sp_synchronize(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000132{
133 int i;
hailfingerbacbc8b2009-07-21 13:02:59 +0000134 unsigned char buf[8];
hailfingerbacbc8b2009-07-21 13:02:59 +0000135 /* First sends 8 NOPs, then flushes the return data - should cause *
136 * the device serial parser to get to a sane state, unless if it *
137 * is waiting for a real long write-n. */
138 memset(buf, S_CMD_NOP, 8);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100139 if (serialport_write_nonblock(buf, 8, 1, NULL) != 0) {
140 goto err_out;
141 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000142 /* A second should be enough to get all the answers to the buffer */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100143 internal_delay(1000 * 1000);
hailfingerbacbc8b2009-07-21 13:02:59 +0000144 sp_flush_incoming();
145
stefanct371e7e82011-07-07 19:56:58 +0000146 /* Then try up to 8 times to send syncnop and get the correct special *
147 * return of NAK+ACK. Timing note: up to 10 characters, 10*50ms = *
148 * up to 500ms per try, 8*0.5s = 4s; +1s (above) = up to 5s sync *
149 * attempt, ~1s if immediate success. */
hailfingerbacbc8b2009-07-21 13:02:59 +0000150 for (i = 0; i < 8; i++) {
151 int n;
152 unsigned char c = S_CMD_SYNCNOP;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100153 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
154 goto err_out;
155 }
snelson0afd28b2010-01-10 01:06:23 +0000156 msg_pdbg(".");
hailfingerbacbc8b2009-07-21 13:02:59 +0000157 fflush(stdout);
158 for (n = 0; n < 10; n++) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100159 int ret = serialport_read_nonblock(&c, 1, 50, NULL);
160 if (ret < 0)
161 goto err_out;
162 if (ret > 0 || c != S_NAK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000163 continue;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100164 ret = serialport_read_nonblock(&c, 1, 20, NULL);
165 if (ret < 0)
166 goto err_out;
167 if (ret > 0 || c != S_ACK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000168 continue;
169 c = S_CMD_SYNCNOP;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100170 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
171 goto err_out;
172 }
173 ret = serialport_read_nonblock(&c, 1, 500, NULL);
174 if (ret < 0)
175 goto err_out;
176 if (ret > 0 || c != S_NAK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000177 break; /* fail */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100178 ret = serialport_read_nonblock(&c, 1, 100, NULL);
179 if (ret > 0 || ret < 0)
180 goto err_out;
hailfingerbacbc8b2009-07-21 13:02:59 +0000181 if (c != S_ACK)
182 break; /* fail */
snelson0afd28b2010-01-10 01:06:23 +0000183 msg_pdbg("\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100184 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000185 }
186 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100187err_out:
188 msg_perr("Error: cannot synchronize protocol - check communications and reset device?\n");
189 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000190}
191
192static int sp_check_commandavail(uint8_t command)
193{
194 int byteoffs, bitoffs;
195 byteoffs = command / 8;
196 bitoffs = command % 8;
197 return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
198}
199
200static int sp_automatic_cmdcheck(uint8_t cmd)
201{
202 if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
stefanctd9ac2212011-10-22 21:45:27 +0000203 msg_pdbg("Warning: Automatic command availability check failed "
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100204 "for cmd 0x%02x - won't execute cmd\n", cmd);
hailfingerbacbc8b2009-07-21 13:02:59 +0000205 return 1;
206 }
207 return 0;
208}
209
210static int sp_docommand(uint8_t command, uint32_t parmlen,
stefanctd9ac2212011-10-22 21:45:27 +0000211 uint8_t *params, uint32_t retlen, void *retparms)
hailfingerbacbc8b2009-07-21 13:02:59 +0000212{
hailfingerbacbc8b2009-07-21 13:02:59 +0000213 unsigned char c;
214 if (sp_automatic_cmdcheck(command))
215 return 1;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100216 if (serialport_write(&command, 1) != 0) {
217 msg_perr("Error: cannot write op code: %s\n", strerror(errno));
218 return 1;
219 }
220 if (serialport_write(params, parmlen) != 0) {
221 msg_perr("Error: cannot write parameters: %s\n", strerror(errno));
222 return 1;
223 }
224 if (serialport_read(&c, 1) != 0) {
225 msg_perr("Error: cannot read from device: %s\n", strerror(errno));
226 return 1;
227 }
stefanctd9ac2212011-10-22 21:45:27 +0000228 if (c == S_NAK)
229 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000230 if (c != S_ACK) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100231 msg_perr("Error: invalid response 0x%02X from device (to command 0x%02X)\n", c, command);
232 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000233 }
234 if (retlen) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100235 if (serialport_read(retparms, retlen) != 0) {
236 msg_perr("Error: cannot read return parameters: %s\n", strerror(errno));
237 return 1;
238 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000239 }
240 return 0;
241}
242
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100243static int sp_flush_stream(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000244{
245 if (sp_streamed_transmit_ops)
246 do {
247 unsigned char c;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100248 if (serialport_read(&c, 1) != 0) {
249 msg_perr("Error: cannot read from device (flushing stream)");
250 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000251 }
252 if (c == S_NAK) {
snelson0afd28b2010-01-10 01:06:23 +0000253 msg_perr("Error: NAK to a stream buffer operation\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100254 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000255 }
256 if (c != S_ACK) {
snelson0afd28b2010-01-10 01:06:23 +0000257 msg_perr("Error: Invalid reply 0x%02X from device\n", c);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100258 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000259 }
260 } while (--sp_streamed_transmit_ops);
261 sp_streamed_transmit_ops = 0;
262 sp_streamed_transmit_bytes = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100263 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000264}
265
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100266static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t *parms)
hailfingerbacbc8b2009-07-21 13:02:59 +0000267{
268 uint8_t *sp;
269 if (sp_automatic_cmdcheck(cmd))
270 return 1;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100271
hailfingerbacbc8b2009-07-21 13:02:59 +0000272 sp = malloc(1 + parmlen);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100273 if (!sp) {
274 msg_perr("Error: cannot malloc command buffer\n");
275 return 1;
276 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000277 sp[0] = cmd;
278 memcpy(&(sp[1]), parms, parmlen);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100279
280 if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size)) {
281 if (sp_flush_stream() != 0) {
282 free(sp);
283 return 1;
284 }
285 }
286 if (serialport_write(sp, 1 + parmlen) != 0) {
287 msg_perr("Error: cannot write command\n");
288 free(sp);
289 return 1;
290 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000291 sp_streamed_transmit_ops += 1;
292 sp_streamed_transmit_bytes += 1 + parmlen;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100293
294 free(sp);
hailfingerbacbc8b2009-07-21 13:02:59 +0000295 return 0;
296}
297
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100298static int serprog_spi_send_command(const struct flashctx *flash,
299 unsigned int writecnt, unsigned int readcnt,
hailfinger76bb7e92011-11-09 23:40:00 +0000300 const unsigned char *writearr,
301 unsigned char *readarr);
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100302static struct spi_master spi_master_serprog = {
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000303 .features = SPI_MASTER_4BA,
stefanct69965b62011-09-15 23:38:14 +0000304 .max_data_read = MAX_DATA_READ_UNLIMITED,
305 .max_data_write = MAX_DATA_WRITE_UNLIMITED,
306 .command = serprog_spi_send_command,
307 .multicommand = default_spi_send_multicommand,
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000308 .read = default_spi_read,
stefanct69965b62011-09-15 23:38:14 +0000309 .write_256 = default_spi_write_256,
310};
311
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700312static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
313 chipaddr addr);
314static uint8_t serprog_chip_readb(const struct flashctx *flash,
315 const chipaddr addr);
316static void serprog_chip_readn(const struct flashctx *flash, uint8_t *buf,
317 const chipaddr addr, size_t len);
Patrick Georgi0a9533a2017-02-03 19:28:38 +0100318static const struct par_master par_master_serprog = {
hailfinger76bb7e92011-11-09 23:40:00 +0000319 .chip_readb = serprog_chip_readb,
320 .chip_readw = fallback_chip_readw,
321 .chip_readl = fallback_chip_readl,
322 .chip_readn = serprog_chip_readn,
323 .chip_writeb = serprog_chip_writeb,
324 .chip_writew = fallback_chip_writew,
325 .chip_writel = fallback_chip_writel,
326 .chip_writen = fallback_chip_writen,
327};
328
329static enum chipbustype serprog_buses_supported = BUS_NONE;
330
David Hendricksac1d25c2016-08-09 17:00:58 -0700331int serprog_init(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000332{
333 uint16_t iface;
hailfingerbacbc8b2009-07-21 13:02:59 +0000334 unsigned char pgmname[17];
335 unsigned char rbuf[3];
336 unsigned char c;
hailfinger1ef766d2010-07-06 09:55:48 +0000337 char *device;
hailfinger1ef766d2010-07-06 09:55:48 +0000338 int have_device = 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000339
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100340 /* the parameter is either of format "dev=/dev/device[:baud]" or "ip=ip:port" */
hailfingerddeb4ac2010-07-08 10:13:37 +0000341 device = extract_programmer_param("dev");
hailfinger1ef766d2010-07-06 09:55:48 +0000342 if (device && strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100343 char *baud_str = strstr(device, ":");
344 if (baud_str != NULL) {
hailfinger1ef766d2010-07-06 09:55:48 +0000345 /* Split device from baudrate. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100346 *baud_str = '\0';
347 baud_str++;
hailfinger1ef766d2010-07-06 09:55:48 +0000348 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100349 int baud;
350 /* Convert baud string to value.
351 * baud_str is either NULL (if strstr can't find the colon), points to the \0 after the colon
352 * if no characters where given after the colon, or a string to convert... */
353 if (baud_str == NULL || *baud_str == '\0') {
354 baud = -1;
355 msg_pdbg("No baudrate specified, using the hardware's defaults.\n");
356 } else
357 baud = atoi(baud_str); // FIXME: replace atoi with strtoul
358 if (strlen(device) > 0) {
359 sp_fd = sp_openserport(device, baud);
360 if (sp_fd == SER_INV_FD) {
361 free(device);
362 return 1;
363 }
hailfinger1ef766d2010-07-06 09:55:48 +0000364 have_device++;
365 }
366 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100367
368#if !IS_WINDOWS
hailfinger1ef766d2010-07-06 09:55:48 +0000369 if (device && !strlen(device)) {
370 msg_perr("Error: No device specified.\n"
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100371 "Use flashrom -p serprog:dev=/dev/device[:baud]\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000372 free(device);
373 return 1;
374 }
375 free(device);
hailfingerbacbc8b2009-07-21 13:02:59 +0000376
hailfingerddeb4ac2010-07-08 10:13:37 +0000377 device = extract_programmer_param("ip");
hailfinger1ef766d2010-07-06 09:55:48 +0000378 if (have_device && device) {
379 msg_perr("Error: Both host and device specified.\n"
380 "Please use either dev= or ip= but not both.\n");
381 free(device);
382 return 1;
383 }
384 if (device && strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100385 char *port = strstr(device, ":");
386 if (port != NULL) {
hailfinger1ef766d2010-07-06 09:55:48 +0000387 /* Split host from port. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100388 *port = '\0';
389 port++;
hailfinger1ef766d2010-07-06 09:55:48 +0000390 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100391 if (!port || !strlen(port)) {
hailfinger1ef766d2010-07-06 09:55:48 +0000392 msg_perr("Error: No port specified.\n"
393 "Use flashrom -p serprog:ip=ipaddr:port\n");
394 free(device);
stefanct69965b62011-09-15 23:38:14 +0000395 return 1;
hailfinger1ef766d2010-07-06 09:55:48 +0000396 }
397 if (strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100398 sp_fd = sp_opensocket(device, atoi(port)); // FIXME: replace atoi with strtoul
399 if (sp_fd < 0) {
400 free(device);
401 return 1;
402 }
hailfinger1ef766d2010-07-06 09:55:48 +0000403 have_device++;
404 }
405 }
406 if (device && !strlen(device)) {
407 msg_perr("Error: No host specified.\n"
408 "Use flashrom -p serprog:ip=ipaddr:port\n");
409 free(device);
410 return 1;
411 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100412#endif
hailfinger1ef766d2010-07-06 09:55:48 +0000413 free(device);
414
415 if (!have_device) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100416#if IS_WINDOWS
417 msg_perr("Error: No device specified.\n"
418 "Use flashrom -p serprog:dev=comN[:baud]\n");
419#else
hailfinger1ef766d2010-07-06 09:55:48 +0000420 msg_perr("Error: Neither host nor device specified.\n"
421 "Use flashrom -p serprog:dev=/dev/device:baud or "
422 "flashrom -p serprog:ip=ipaddr:port\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100423#endif
hailfinger1ef766d2010-07-06 09:55:48 +0000424 return 1;
425 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000426
dhendrix0ffc2eb2011-06-14 01:35:36 +0000427 if (register_shutdown(serprog_shutdown, NULL))
428 return 1;
429
snelson0afd28b2010-01-10 01:06:23 +0000430 msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000431
432 sp_check_avail_automatic = 0;
433
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100434 if (sp_synchronize())
435 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000436
snelson0afd28b2010-01-10 01:06:23 +0000437 msg_pdbg(MSGHEADER "Synchronized\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000438
439 if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
stefanctd9ac2212011-10-22 21:45:27 +0000440 msg_perr("Error: NAK to query interface version\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000441 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000442 }
443
444 if (iface != 1) {
stefanctd9ac2212011-10-22 21:45:27 +0000445 msg_perr("Error: Unknown interface version: %d\n", iface);
hailfinger76bb7e92011-11-09 23:40:00 +0000446 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000447 }
448
snelson0afd28b2010-01-10 01:06:23 +0000449 msg_pdbg(MSGHEADER "Interface version ok.\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000450
451 if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
snelson0afd28b2010-01-10 01:06:23 +0000452 msg_perr("Error: query command map not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000453 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000454 }
455
456 sp_check_avail_automatic = 1;
457
hailfinger76bb7e92011-11-09 23:40:00 +0000458 /* FIXME: This assumes that serprog device bustypes are always
459 * identical with flashrom bustype enums and that they all fit
460 * in a single byte.
461 */
stefanct69965b62011-09-15 23:38:14 +0000462 if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100463 msg_pwarn("Warning: NAK to query supported buses\n");
stefanct69965b62011-09-15 23:38:14 +0000464 c = BUS_NONSPI; /* A reasonable default for now. */
hailfingerbacbc8b2009-07-21 13:02:59 +0000465 }
hailfinger76bb7e92011-11-09 23:40:00 +0000466 serprog_buses_supported = c;
467
stefanctd9ac2212011-10-22 21:45:27 +0000468 msg_pdbg(MSGHEADER "Bus support: parallel=%s, LPC=%s, FWH=%s, SPI=%s\n",
469 (c & BUS_PARALLEL) ? "on" : "off",
470 (c & BUS_LPC) ? "on" : "off",
471 (c & BUS_FWH) ? "on" : "off",
472 (c & BUS_SPI) ? "on" : "off");
stefanct69965b62011-09-15 23:38:14 +0000473 /* Check for the minimum operational set of commands. */
hailfinger76bb7e92011-11-09 23:40:00 +0000474 if (serprog_buses_supported & BUS_SPI) {
stefanct69965b62011-09-15 23:38:14 +0000475 uint8_t bt = BUS_SPI;
Edward O'Callaghan62018182020-10-03 00:16:48 +1000476 char *spispeed;
stefanct69965b62011-09-15 23:38:14 +0000477 if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
478 msg_perr("Error: SPI operation not supported while the "
479 "bustype is SPI\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000480 return 1;
stefanct69965b62011-09-15 23:38:14 +0000481 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100482 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
483 return 1;
stefanct69965b62011-09-15 23:38:14 +0000484 /* Success of any of these commands is optional. We don't need
485 the programmer to tell us its limits, but if it doesn't, we
486 will assume stuff, so it's in the programmers best interest
487 to tell us. */
stefanct69965b62011-09-15 23:38:14 +0000488 if (!sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
489 uint32_t v;
490 v = ((unsigned int)(rbuf[0]) << 0);
491 v |= ((unsigned int)(rbuf[1]) << 8);
492 v |= ((unsigned int)(rbuf[2]) << 16);
493 if (v == 0)
494 v = (1 << 24) - 1; /* SPI-op maximum. */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100495 spi_master_serprog.max_data_write = v;
stefanct69965b62011-09-15 23:38:14 +0000496 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n", v);
497 }
498 if (!sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf)) {
499 uint32_t v;
500 v = ((unsigned int)(rbuf[0]) << 0);
501 v |= ((unsigned int)(rbuf[1]) << 8);
502 v |= ((unsigned int)(rbuf[2]) << 16);
503 if (v == 0)
504 v = (1 << 24) - 1; /* SPI-op maximum. */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100505 spi_master_serprog.max_data_read = v;
stefanct69965b62011-09-15 23:38:14 +0000506 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n", v);
507 }
Edward O'Callaghan62018182020-10-03 00:16:48 +1000508 spispeed = extract_programmer_param("spispeed");
509 if (spispeed && strlen(spispeed)) {
510 uint32_t f_spi_req, f_spi;
511 uint8_t buf[4];
512 char *f_spi_suffix;
513
514 errno = 0;
515 f_spi_req = strtol(spispeed, &f_spi_suffix, 0);
516 if (errno != 0 || spispeed == f_spi_suffix) {
517 msg_perr("Error: Could not convert 'spispeed'.\n");
518 free(spispeed);
519 return 1;
520 }
521 if (strlen(f_spi_suffix) == 1) {
522 if (!strcasecmp(f_spi_suffix, "M"))
523 f_spi_req *= 1000000;
524 else if (!strcasecmp(f_spi_suffix, "k"))
525 f_spi_req *= 1000;
526 else {
527 msg_perr("Error: Garbage following 'spispeed' value.\n");
528 free(spispeed);
529 return 1;
530 }
531 } else if (strlen(f_spi_suffix) > 1) {
532 msg_perr("Error: Garbage following 'spispeed' value.\n");
533 free(spispeed);
534 return 1;
535 }
536
537 buf[0] = (f_spi_req >> (0 * 8)) & 0xFF;
538 buf[1] = (f_spi_req >> (1 * 8)) & 0xFF;
539 buf[2] = (f_spi_req >> (2 * 8)) & 0xFF;
540 buf[3] = (f_spi_req >> (3 * 8)) & 0xFF;
541
542 if (sp_check_commandavail(S_CMD_S_SPI_FREQ) == 0)
543 msg_pwarn(MSGHEADER "Warning: Setting the SPI clock rate is not supported!\n");
544 else if (sp_docommand(S_CMD_S_SPI_FREQ, 4, buf, 4, buf) == 0) {
545 f_spi = buf[0];
546 f_spi |= buf[1] << (1 * 8);
547 f_spi |= buf[2] << (2 * 8);
548 f_spi |= buf[3] << (3 * 8);
549 msg_pdbg(MSGHEADER "Requested to set SPI clock frequency to %u Hz. "
550 "It was actually set to %u Hz\n", f_spi_req, f_spi);
551 } else
552 msg_pwarn(MSGHEADER "Setting SPI clock rate to %u Hz failed!\n", f_spi_req);
553 }
554 free(spispeed);
hailfinger76bb7e92011-11-09 23:40:00 +0000555 bt = serprog_buses_supported;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100556 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
557 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000558 }
stefanct69965b62011-09-15 23:38:14 +0000559
hailfinger76bb7e92011-11-09 23:40:00 +0000560 if (serprog_buses_supported & BUS_NONSPI) {
stefanct69965b62011-09-15 23:38:14 +0000561 if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
562 msg_perr("Error: Initialize operation buffer "
563 "not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000564 return 1;
stefanct69965b62011-09-15 23:38:14 +0000565 }
566
567 if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
568 msg_perr("Error: Write to opbuf: "
569 "delay not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000570 return 1;
stefanct69965b62011-09-15 23:38:14 +0000571 }
572
573 /* S_CMD_O_EXEC availability checked later. */
574
575 if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
576 msg_perr("Error: Single byte read not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000577 return 1;
stefanct69965b62011-09-15 23:38:14 +0000578 }
579 /* This could be translated to single byte reads (if missing),
580 * but now we don't support that. */
581 if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
582 msg_perr("Error: Read n bytes not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000583 return 1;
stefanct69965b62011-09-15 23:38:14 +0000584 }
585 if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
586 msg_perr("Error: Write to opbuf: "
587 "write byte not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000588 return 1;
stefanct69965b62011-09-15 23:38:14 +0000589 }
590
591 if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
592 msg_pdbg(MSGHEADER "Write-n not supported");
593 sp_max_write_n = 0;
594 } else {
595 sp_max_write_n = ((unsigned int)(rbuf[0]) << 0);
596 sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8);
597 sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16);
598 if (!sp_max_write_n) {
599 sp_max_write_n = (1 << 24);
600 }
601 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n",
602 sp_max_write_n);
603 sp_write_n_buf = malloc(sp_max_write_n);
604 if (!sp_write_n_buf) {
605 msg_perr("Error: cannot allocate memory for "
606 "Write-n buffer\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000607 return 1;
stefanct69965b62011-09-15 23:38:14 +0000608 }
609 sp_write_n_bytes = 0;
610 }
611
612 if (sp_check_commandavail(S_CMD_Q_RDNMAXLEN) &&
613 (sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf) == 0)) {
614 sp_max_read_n = ((unsigned int)(rbuf[0]) << 0);
615 sp_max_read_n |= ((unsigned int)(rbuf[1]) << 8);
616 sp_max_read_n |= ((unsigned int)(rbuf[2]) << 16);
617 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n",
618 sp_max_read_n ? sp_max_read_n : (1 << 24));
619 } else {
620 msg_pdbg(MSGHEADER "Maximum read-n length "
621 "not reported\n");
622 sp_max_read_n = 0;
623 }
624
hailfingerbacbc8b2009-07-21 13:02:59 +0000625 }
626
627 if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100628 msg_pwarn("Warning: NAK to query programmer name\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000629 strcpy((char *)pgmname, "(unknown)");
630 }
631 pgmname[16] = 0;
stefanctd9ac2212011-10-22 21:45:27 +0000632 msg_pinfo(MSGHEADER "Programmer name is \"%s\"\n", pgmname);
hailfingerbacbc8b2009-07-21 13:02:59 +0000633
634 if (sp_docommand(S_CMD_Q_SERBUF, 0, NULL, 2, &sp_device_serbuf_size)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100635 msg_pwarn("Warning: NAK to query serial buffer size\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000636 }
stefanctd9ac2212011-10-22 21:45:27 +0000637 msg_pdbg(MSGHEADER "Serial buffer size is %d\n",
hailfingerbacbc8b2009-07-21 13:02:59 +0000638 sp_device_serbuf_size);
639
stefanct69965b62011-09-15 23:38:14 +0000640 if (sp_check_commandavail(S_CMD_O_INIT)) {
641 /* This would be inconsistent. */
642 if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
643 msg_perr("Error: Execute operation buffer not "
644 "supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000645 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000646 }
stefanct69965b62011-09-15 23:38:14 +0000647
648 if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
649 msg_perr("Error: NAK to initialize operation buffer\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000650 return 1;
stefanct69965b62011-09-15 23:38:14 +0000651 }
652
653 if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2,
654 &sp_device_opbuf_size)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100655 msg_pwarn("Warning: NAK to query operation buffer size\n");
stefanct69965b62011-09-15 23:38:14 +0000656 }
stefanctd9ac2212011-10-22 21:45:27 +0000657 msg_pdbg(MSGHEADER "operation buffer size is %d\n",
stefanct69965b62011-09-15 23:38:14 +0000658 sp_device_opbuf_size);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100659 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000660
Edward O'Callaghan62018182020-10-03 00:16:48 +1000661 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
662 uint8_t en = 1;
663 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) {
664 msg_perr("Error: could not enable output buffers\n");
665 return 1;
666 } else
667 msg_pdbg(MSGHEADER "Output drivers enabled\n");
668 } else
669 msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000670 sp_prev_was_write = 0;
671 sp_streamed_transmit_ops = 0;
672 sp_streamed_transmit_bytes = 0;
673 sp_opbuf_usage = 0;
hailfinger76bb7e92011-11-09 23:40:00 +0000674 if (serprog_buses_supported & BUS_SPI)
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100675 register_spi_master(&spi_master_serprog);
hailfinger76bb7e92011-11-09 23:40:00 +0000676 if (serprog_buses_supported & BUS_NONSPI)
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100677 register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI);
hailfingerbacbc8b2009-07-21 13:02:59 +0000678 return 0;
679}
680
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100681/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */
682static int sp_pass_writen(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000683{
684 unsigned char header[7];
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100685 msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr);
686 if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) {
687 if (sp_flush_stream() != 0) {
688 return 1;
689 }
690 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000691 /* In case it's just a single byte send it as a single write. */
692 if (sp_write_n_bytes == 1) {
693 sp_write_n_bytes = 0;
694 header[0] = (sp_write_n_addr >> 0) & 0xFF;
695 header[1] = (sp_write_n_addr >> 8) & 0xFF;
696 header[2] = (sp_write_n_addr >> 16) & 0xFF;
697 header[3] = sp_write_n_buf[0];
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100698 if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0)
699 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000700 sp_opbuf_usage += 5;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100701 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000702 }
703 header[0] = S_CMD_O_WRITEN;
704 header[1] = (sp_write_n_bytes >> 0) & 0xFF;
705 header[2] = (sp_write_n_bytes >> 8) & 0xFF;
706 header[3] = (sp_write_n_bytes >> 16) & 0xFF;
707 header[4] = (sp_write_n_addr >> 0) & 0xFF;
708 header[5] = (sp_write_n_addr >> 8) & 0xFF;
709 header[6] = (sp_write_n_addr >> 16) & 0xFF;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100710 if (serialport_write(header, 7) != 0) {
711 msg_perr(MSGHEADER "Error: cannot write write-n command\n");
712 return 1;
713 }
714 if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) {
715 msg_perr(MSGHEADER "Error: cannot write write-n data");
716 return 1;
717 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000718 sp_streamed_transmit_bytes += 7 + sp_write_n_bytes;
719 sp_streamed_transmit_ops += 1;
720 sp_opbuf_usage += 7 + sp_write_n_bytes;
721 sp_write_n_bytes = 0;
722 sp_prev_was_write = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100723 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000724}
725
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100726static int sp_execute_opbuf_noflush(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000727{
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100728 if ((sp_max_write_n) && (sp_write_n_bytes)) {
729 if (sp_pass_writen() != 0) {
730 msg_perr("Error: could not transfer write buffer\n");
731 return 1;
732 }
733 }
734 if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) {
735 msg_perr("Error: could not execute command buffer\n");
736 return 1;
737 }
738 msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage);
hailfingerbacbc8b2009-07-21 13:02:59 +0000739 sp_opbuf_usage = 0;
740 sp_prev_was_write = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100741 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000742}
743
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100744static int sp_execute_opbuf(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000745{
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100746 if (sp_execute_opbuf_noflush() != 0)
747 return 1;
748 if (sp_flush_stream() != 0)
749 return 1;
750
751 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000752}
753
David Hendricks93784b42016-08-09 17:00:38 -0700754static int serprog_shutdown(void *data)
hailfingerbacbc8b2009-07-21 13:02:59 +0000755{
hailfingerbacbc8b2009-07-21 13:02:59 +0000756 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100757 if (sp_execute_opbuf() != 0)
758 msg_pwarn("Could not flush command buffer.\n");
Edward O'Callaghan62018182020-10-03 00:16:48 +1000759 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
760 uint8_t dis = 0;
761 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0)
762 msg_pdbg(MSGHEADER "Output drivers disabled\n");
763 else
764 msg_pwarn(MSGHEADER "%s: Warning: could not disable output buffers\n", __func__);
765 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100766 /* FIXME: fix sockets on windows(?), especially closing */
767 serialport_shutdown(&sp_fd);
hailfingerbacbc8b2009-07-21 13:02:59 +0000768 if (sp_max_write_n)
769 free(sp_write_n_buf);
770 return 0;
771}
772
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100773static int sp_check_opbuf_usage(int bytes_to_be_added)
hailfingerbacbc8b2009-07-21 13:02:59 +0000774{
775 if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100776 /* If this happens in the middle of a page load the page load will probably fail. */
777 msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n");
778 if (sp_execute_opbuf() != 0)
779 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000780 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100781 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000782}
783
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100784static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
785 chipaddr addr)
hailfingerbacbc8b2009-07-21 13:02:59 +0000786{
snelson0afd28b2010-01-10 01:06:23 +0000787 msg_pspew("%s\n", __func__);
hailfingerbacbc8b2009-07-21 13:02:59 +0000788 if (sp_max_write_n) {
789 if ((sp_prev_was_write)
790 && (addr == (sp_write_n_addr + sp_write_n_bytes))) {
791 sp_write_n_buf[sp_write_n_bytes++] = val;
792 } else {
793 if ((sp_prev_was_write) && (sp_write_n_bytes))
794 sp_pass_writen();
795 sp_prev_was_write = 1;
796 sp_write_n_addr = addr;
797 sp_write_n_bytes = 1;
798 sp_write_n_buf[0] = val;
799 }
800 sp_check_opbuf_usage(7 + sp_write_n_bytes);
801 if (sp_write_n_bytes >= sp_max_write_n)
802 sp_pass_writen();
803 } else {
804 /* We will have to do single writeb ops. */
805 unsigned char writeb_parm[4];
806 sp_check_opbuf_usage(6);
807 writeb_parm[0] = (addr >> 0) & 0xFF;
808 writeb_parm[1] = (addr >> 8) & 0xFF;
809 writeb_parm[2] = (addr >> 16) & 0xFF;
810 writeb_parm[3] = val;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100811 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error
hailfingerbacbc8b2009-07-21 13:02:59 +0000812 sp_opbuf_usage += 5;
813 }
814}
815
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100816static uint8_t serprog_chip_readb(const struct flashctx *flash,
817 const chipaddr addr)
hailfingerbacbc8b2009-07-21 13:02:59 +0000818{
819 unsigned char c;
820 unsigned char buf[3];
821 /* Will stream the read operation - eg. add it to the stream buffer, *
822 * then flush the buffer, then read the read answer. */
823 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
824 sp_execute_opbuf_noflush();
825 buf[0] = ((addr >> 0) & 0xFF);
826 buf[1] = ((addr >> 8) & 0xFF);
827 buf[2] = ((addr >> 16) & 0xFF);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100828 sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error
829 sp_flush_stream(); // FIXME: return error
830 if (serialport_read(&c, 1) != 0)
831 msg_perr(MSGHEADER "readb byteread"); // FIXME: return error
Kangheui Won4974cc12019-10-18 12:59:01 +1100832 msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c);
hailfingerbacbc8b2009-07-21 13:02:59 +0000833 return c;
834}
835
uwe3a3ab2f2010-03-25 23:18:41 +0000836/* Local version that really does the job, doesn't care of max_read_n. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100837static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len)
hailfingerbacbc8b2009-07-21 13:02:59 +0000838{
hailfingerbacbc8b2009-07-21 13:02:59 +0000839 unsigned char sbuf[6];
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100840 msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len);
hailfingerbacbc8b2009-07-21 13:02:59 +0000841 /* Stream the read-n -- as above. */
842 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
843 sp_execute_opbuf_noflush();
844 sbuf[0] = ((addr >> 0) & 0xFF);
845 sbuf[1] = ((addr >> 8) & 0xFF);
846 sbuf[2] = ((addr >> 16) & 0xFF);
847 sbuf[3] = ((len >> 0) & 0xFF);
848 sbuf[4] = ((len >> 8) & 0xFF);
849 sbuf[5] = ((len >> 16) & 0xFF);
850 sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100851 if (sp_flush_stream() != 0)
852 return 1;
853 if (serialport_read(buf, len) != 0) {
854 msg_perr(MSGHEADER "Error: cannot read read-n data");
855 return 1;
856 }
857 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000858}
859
860/* The externally called version that makes sure that max_read_n is obeyed. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100861static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf,
862 const chipaddr addr, size_t len)
hailfingerbacbc8b2009-07-21 13:02:59 +0000863{
864 size_t lenm = len;
865 chipaddr addrm = addr;
stefanctd9ac2212011-10-22 21:45:27 +0000866 while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100867 sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error
hailfingerbacbc8b2009-07-21 13:02:59 +0000868 addrm += sp_max_read_n;
869 lenm -= sp_max_read_n;
870 }
stefanctd9ac2212011-10-22 21:45:27 +0000871 if (lenm)
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100872 sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error
hailfingerbacbc8b2009-07-21 13:02:59 +0000873}
874
Edward O'Callaghan8ebbd502019-09-03 15:11:02 +1000875void serprog_delay(unsigned int usecs)
hailfingerbacbc8b2009-07-21 13:02:59 +0000876{
877 unsigned char buf[4];
stefanctd9ac2212011-10-22 21:45:27 +0000878 msg_pspew("%s usecs=%d\n", __func__, usecs);
stefanct69965b62011-09-15 23:38:14 +0000879 if (!sp_check_commandavail(S_CMD_O_DELAY)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100880 msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n");
stefanctd9ac2212011-10-22 21:45:27 +0000881 internal_delay(usecs);
stefanct69965b62011-09-15 23:38:14 +0000882 return;
883 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000884 if ((sp_max_write_n) && (sp_write_n_bytes))
885 sp_pass_writen();
886 sp_check_opbuf_usage(5);
stefanctd9ac2212011-10-22 21:45:27 +0000887 buf[0] = ((usecs >> 0) & 0xFF);
888 buf[1] = ((usecs >> 8) & 0xFF);
889 buf[2] = ((usecs >> 16) & 0xFF);
890 buf[3] = ((usecs >> 24) & 0xFF);
hailfingerbacbc8b2009-07-21 13:02:59 +0000891 sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf);
892 sp_opbuf_usage += 5;
893 sp_prev_was_write = 0;
894}
stefanct69965b62011-09-15 23:38:14 +0000895
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100896static int serprog_spi_send_command(const struct flashctx *flash,
897 unsigned int writecnt, unsigned int readcnt,
898 const unsigned char *writearr,
899 unsigned char *readarr)
stefanct69965b62011-09-15 23:38:14 +0000900{
901 unsigned char *parmbuf;
902 int ret;
903 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100904 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) {
905 if (sp_execute_opbuf() != 0) {
906 msg_perr("Error: could not execute command buffer before sending SPI commands.\n");
907 return 1;
908 }
909 }
910
stefanct69965b62011-09-15 23:38:14 +0000911 parmbuf = malloc(writecnt + 6);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100912 if (!parmbuf) {
913 msg_perr("Error: could not allocate SPI send param buffer.\n");
914 return 1;
915 }
stefanct69965b62011-09-15 23:38:14 +0000916 parmbuf[0] = (writecnt >> 0) & 0xFF;
917 parmbuf[1] = (writecnt >> 8) & 0xFF;
918 parmbuf[2] = (writecnt >> 16) & 0xFF;
919 parmbuf[3] = (readcnt >> 0) & 0xFF;
920 parmbuf[4] = (readcnt >> 8) & 0xFF;
921 parmbuf[5] = (readcnt >> 16) & 0xFF;
922 memcpy(parmbuf + 6, writearr, writecnt);
923 ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt,
924 readarr);
925 free(parmbuf);
926 return ret;
927}
Edward O'Callaghan62018182020-10-03 00:16:48 +1000928
929void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len)
930{
931 /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits
932 * correctly (usually setting them to one either in software (for FWH/LPC) or relying on the fact that
933 * the hardware observes a subset of the address bits only). Combined with the standard mapping of
934 * flashrom this creates a 16 MB-wide window just below the 4 GB boundary where serprog can operate (as
935 * needed for non-SPI chips). Below we make sure that the requested range is within this window. */
936 if ((phys_addr & 0xFF000000) == 0xFF000000) {
937 return (void*)phys_addr;
938 }
939 msg_pwarn(MSGHEADER "requested mapping %s is incompatible: 0x%zx bytes at 0x%0*" PRIxPTR ".\n",
940 descr, len, PRIxPTR_WIDTH, phys_addr);
941 return NULL;
942}