blob: eb15219f33b9b4a1d7a4134de4ba6214a96f61c8 [file] [log] [blame]
Urja Rannikko22915352009-06-23 11:33:43 +00001/*
2 * This file is part of the flashrom project.
3 *
Urja Rannikkoc93f5f12011-09-15 23:38:14 +00004 * Copyright (C) 2009, 2011 Urja Rannikko <urjaman@gmail.com>
Urja Rannikko22915352009-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.
Urja Rannikko22915352009-06-23 11:33:43 +000016 */
17
Felix Singer815eb792022-08-19 01:02:42 +020018#include <stdbool.h>
Carl-Daniel Hailfingeref58a9c2009-08-12 13:32:56 +000019#include <stdio.h>
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000020#if ! IS_WINDOWS /* stuff (presumably) needed for sockets only */
Urja Rannikko22915352009-06-23 11:33:43 +000021#include <stdlib.h>
Carl-Daniel Hailfingeref58a9c2009-08-12 13:32:56 +000022#include <unistd.h>
Urja Rannikko22915352009-06-23 11:33:43 +000023#include <fcntl.h>
Urja Rannikko22915352009-06-23 11:33:43 +000024#include <sys/socket.h>
25#include <arpa/inet.h>
26#include <netinet/in.h>
27#include <netinet/tcp.h>
28#include <netdb.h>
Stefan Tauner52b6e9d2013-04-01 00:46:05 +000029#endif
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000030#if IS_WINDOWS
Stefan Tauner52b6e9d2013-04-01 00:46:05 +000031#include <conio.h>
32#else
Urja Rannikko22915352009-06-23 11:33:43 +000033#include <termios.h>
Stefan Tauner52b6e9d2013-04-01 00:46:05 +000034#endif
35#include <string.h>
36#include <errno.h>
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000037#include "flash.h"
38#include "programmer.h"
Urja Rannikkoc93f5f12011-09-15 23:38:14 +000039#include "chipdrivers.h"
Felix Singer100be2c2021-10-13 13:40:07 +020040
41/* According to Serial Flasher Protocol Specification - version 1 */
42#define S_ACK 0x06
43#define S_NAK 0x15
44#define S_CMD_NOP 0x00 /* No operation */
45#define S_CMD_Q_IFACE 0x01 /* Query interface version */
46#define S_CMD_Q_CMDMAP 0x02 /* Query supported commands bitmap */
47#define S_CMD_Q_PGMNAME 0x03 /* Query programmer name */
48#define S_CMD_Q_SERBUF 0x04 /* Query Serial Buffer Size */
49#define S_CMD_Q_BUSTYPE 0x05 /* Query supported bustypes */
50#define S_CMD_Q_CHIPSIZE 0x06 /* Query supported chipsize (2^n format) */
51#define S_CMD_Q_OPBUF 0x07 /* Query operation buffer size */
52#define S_CMD_Q_WRNMAXLEN 0x08 /* Query Write to opbuf: Write-N maximum length */
53#define S_CMD_R_BYTE 0x09 /* Read a single byte */
54#define S_CMD_R_NBYTES 0x0A /* Read n bytes */
55#define S_CMD_O_INIT 0x0B /* Initialize operation buffer */
56#define S_CMD_O_WRITEB 0x0C /* Write opbuf: Write byte with address */
57#define S_CMD_O_WRITEN 0x0D /* Write to opbuf: Write-N */
58#define S_CMD_O_DELAY 0x0E /* Write opbuf: udelay */
59#define S_CMD_O_EXEC 0x0F /* Execute operation buffer */
60#define S_CMD_SYNCNOP 0x10 /* Special no-operation that returns NAK+ACK */
61#define S_CMD_Q_RDNMAXLEN 0x11 /* Query read-n maximum length */
62#define S_CMD_S_BUSTYPE 0x12 /* Set used bustype(s). */
63#define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */
64#define S_CMD_S_SPI_FREQ 0x14 /* Set SPI clock frequency */
65#define S_CMD_S_PIN_STATE 0x15 /* Enable/disable output drivers */
Urja Rannikkof3196df2009-07-21 13:02:59 +000066
Stefan Tauner31019d42011-10-22 21:45:27 +000067#define MSGHEADER "serprog: "
Urja Rannikkof3196df2009-07-21 13:02:59 +000068
David Hendricks8bb20212011-06-14 01:35:36 +000069/*
70 * FIXME: This prototype was added to help reduce diffs for the shutdown
71 * registration patch, which shifted many lines of code to place
72 * serprog_shutdown() before serprog_init(). It should be removed soon.
73 */
74static int serprog_shutdown(void *data);
75
Urja Rannikkof3196df2009-07-21 13:02:59 +000076static uint16_t sp_device_serbuf_size = 16;
77static uint16_t sp_device_opbuf_size = 300;
78/* Bitmap of supported commands */
79static uint8_t sp_cmdmap[32];
80
Uwe Hermann4e3d0b32010-03-25 23:18:41 +000081/* sp_prev_was_write used to detect writes with contiguous addresses
Urja Rannikkof3196df2009-07-21 13:02:59 +000082 and combine them to write-n's */
83static int sp_prev_was_write = 0;
84/* sp_write_n_addr used as the starting addr of the currently
85 combined write-n operation */
86static uint32_t sp_write_n_addr;
87/* The maximum length of an write_n operation; 0 = write-n not supported */
88static uint32_t sp_max_write_n = 0;
89/* The maximum length of a read_n operation; 0 = 2^24 */
90static uint32_t sp_max_read_n = 0;
91
92/* A malloc'd buffer for combining the operation's data
93 and a counter that tells how much data is there. */
94static uint8_t *sp_write_n_buf;
95static uint32_t sp_write_n_bytes = 0;
96
97/* sp_streamed_* used for flow control checking */
Nico Huber519be662018-12-23 20:03:35 +010098static unsigned int sp_streamed_transmit_ops = 0;
99static unsigned int sp_streamed_transmit_bytes = 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000100
101/* sp_opbuf_usage used for counting the amount of
102 on-device operation buffer used */
103static int sp_opbuf_usage = 0;
104/* if true causes sp_docommand to automatically check
105 whether the command is supported before doing it */
106static int sp_check_avail_automatic = 0;
107
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000108#if ! IS_WINDOWS
Urja Rannikkof3196df2009-07-21 13:02:59 +0000109static int sp_opensocket(char *ip, unsigned int port)
110{
111 int flag = 1;
112 struct hostent *hostPtr = NULL;
Carl-Daniel Hailfinger6d125602009-09-05 01:10:23 +0000113 union { struct sockaddr_in si; struct sockaddr s; } sp = {};
Urja Rannikkof3196df2009-07-21 13:02:59 +0000114 int sock;
Sean Nelson74e8af52010-01-10 01:06:23 +0000115 msg_pdbg(MSGHEADER "IP %s port %d\n", ip, port);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000116 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000117 if (sock < 0) {
118 msg_perr("Error: serprog cannot open socket: %s\n", strerror(errno));
119 return -1;
120 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000121 hostPtr = gethostbyname(ip);
122 if (NULL == hostPtr) {
123 hostPtr = gethostbyaddr(ip, strlen(ip), AF_INET);
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000124 if (NULL == hostPtr) {
Stefan Reinauerb8792872014-04-26 16:12:03 +0000125 close(sock);
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000126 msg_perr("Error: cannot resolve %s\n", ip);
127 return -1;
128 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000129 }
Carl-Daniel Hailfinger6d125602009-09-05 01:10:23 +0000130 sp.si.sin_family = AF_INET;
131 sp.si.sin_port = htons(port);
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000132 (void)memcpy(&sp.si.sin_addr, hostPtr->h_addr_list[0], hostPtr->h_length);
Carl-Daniel Hailfinger6d125602009-09-05 01:10:23 +0000133 if (connect(sock, &sp.s, sizeof(sp.si)) < 0) {
Urja Rannikkof3196df2009-07-21 13:02:59 +0000134 close(sock);
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000135 msg_perr("Error: serprog cannot connect: %s\n", strerror(errno));
136 return -1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000137 }
138 /* We are latency limited, and sometimes do write-write-read *
139 * (write-n) - so enable TCP_NODELAY. */
Stefan Reinauer907c3eb2014-04-26 16:12:31 +0000140 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) {
141 close(sock);
142 msg_perr("Error: serprog cannot set socket options: %s\n", strerror(errno));
143 return -1;
144 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000145 return sock;
146}
Stefan Tauner52b6e9d2013-04-01 00:46:05 +0000147#endif
Urja Rannikkof3196df2009-07-21 13:02:59 +0000148
Uwe Hermann4e3d0b32010-03-25 23:18:41 +0000149/* Synchronize: a bit tricky algorithm that tries to (and in my tests has *
Urja Rannikkof3196df2009-07-21 13:02:59 +0000150 * always succeeded in) bring the serial protocol to known waiting-for- *
Stefan Taunerae3d8372013-04-01 00:45:45 +0000151 * command state - uses nonblocking I/O - rest of the driver uses *
Urja Rannikkof3196df2009-07-21 13:02:59 +0000152 * blocking read - TODO: add an alarm() timer for the rest of the app on *
153 * serial operations, though not such a big issue as the first thing to *
154 * do is synchronize (eg. check that device is alive). */
Niklas Söderlund7145a502012-09-07 07:07:07 +0000155static int sp_synchronize(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000156{
157 int i;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000158 unsigned char buf[8];
Urja Rannikkof3196df2009-07-21 13:02:59 +0000159 /* First sends 8 NOPs, then flushes the return data - should cause *
160 * the device serial parser to get to a sane state, unless if it *
161 * is waiting for a real long write-n. */
162 memset(buf, S_CMD_NOP, 8);
Stefan Taunerae3d8372013-04-01 00:45:45 +0000163 if (serialport_write_nonblock(buf, 8, 1, NULL) != 0) {
Niklas Söderlund7145a502012-09-07 07:07:07 +0000164 goto err_out;
165 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000166 /* A second should be enough to get all the answers to the buffer */
Stefan Tauner79587f52013-04-01 00:45:51 +0000167 internal_delay(1000 * 1000);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000168 sp_flush_incoming();
169
Cristian Măgherușan-Stanciu9932c7b2011-07-07 19:56:58 +0000170 /* Then try up to 8 times to send syncnop and get the correct special *
171 * return of NAK+ACK. Timing note: up to 10 characters, 10*50ms = *
172 * up to 500ms per try, 8*0.5s = 4s; +1s (above) = up to 5s sync *
173 * attempt, ~1s if immediate success. */
Urja Rannikkof3196df2009-07-21 13:02:59 +0000174 for (i = 0; i < 8; i++) {
175 int n;
176 unsigned char c = S_CMD_SYNCNOP;
Stefan Taunerae3d8372013-04-01 00:45:45 +0000177 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
Niklas Söderlund7145a502012-09-07 07:07:07 +0000178 goto err_out;
179 }
Sean Nelson74e8af52010-01-10 01:06:23 +0000180 msg_pdbg(".");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000181 fflush(stdout);
182 for (n = 0; n < 10; n++) {
Stefan Tauner00e16082013-04-01 00:45:38 +0000183 int ret = serialport_read_nonblock(&c, 1, 50, NULL);
Niklas Söderlund7145a502012-09-07 07:07:07 +0000184 if (ret < 0)
185 goto err_out;
186 if (ret > 0 || c != S_NAK)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000187 continue;
Stefan Tauner00e16082013-04-01 00:45:38 +0000188 ret = serialport_read_nonblock(&c, 1, 20, NULL);
Niklas Söderlund7145a502012-09-07 07:07:07 +0000189 if (ret < 0)
190 goto err_out;
191 if (ret > 0 || c != S_ACK)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000192 continue;
193 c = S_CMD_SYNCNOP;
Stefan Taunerae3d8372013-04-01 00:45:45 +0000194 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
195 goto err_out;
Niklas Söderlund7145a502012-09-07 07:07:07 +0000196 }
Stefan Tauner00e16082013-04-01 00:45:38 +0000197 ret = serialport_read_nonblock(&c, 1, 500, NULL);
Niklas Söderlund7145a502012-09-07 07:07:07 +0000198 if (ret < 0)
199 goto err_out;
200 if (ret > 0 || c != S_NAK)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000201 break; /* fail */
Stefan Tauner00e16082013-04-01 00:45:38 +0000202 ret = serialport_read_nonblock(&c, 1, 100, NULL);
Niklas Söderlund7145a502012-09-07 07:07:07 +0000203 if (ret > 0 || ret < 0)
204 goto err_out;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000205 if (c != S_ACK)
206 break; /* fail */
Sean Nelson74e8af52010-01-10 01:06:23 +0000207 msg_pdbg("\n");
Niklas Söderlund7145a502012-09-07 07:07:07 +0000208 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000209 }
210 }
Niklas Söderlund7145a502012-09-07 07:07:07 +0000211err_out:
212 msg_perr("Error: cannot synchronize protocol - check communications and reset device?\n");
213 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000214}
215
216static int sp_check_commandavail(uint8_t command)
217{
218 int byteoffs, bitoffs;
219 byteoffs = command / 8;
220 bitoffs = command % 8;
221 return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
222}
223
224static int sp_automatic_cmdcheck(uint8_t cmd)
225{
226 if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
Stefan Tauner31019d42011-10-22 21:45:27 +0000227 msg_pdbg("Warning: Automatic command availability check failed "
Stefan Taunere34e3e82013-01-01 00:06:51 +0000228 "for cmd 0x%02x - won't execute cmd\n", cmd);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000229 return 1;
230 }
231 return 0;
232}
233
234static int sp_docommand(uint8_t command, uint32_t parmlen,
Stefan Tauner31019d42011-10-22 21:45:27 +0000235 uint8_t *params, uint32_t retlen, void *retparms)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000236{
Urja Rannikkof3196df2009-07-21 13:02:59 +0000237 unsigned char c;
238 if (sp_automatic_cmdcheck(command))
239 return 1;
Stefan Tauner79587f52013-04-01 00:45:51 +0000240 if (serialport_write(&command, 1) != 0) {
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000241 msg_perr("Error: cannot write op code: %s\n", strerror(errno));
242 return 1;
243 }
Stefan Tauner79587f52013-04-01 00:45:51 +0000244 if (serialport_write(params, parmlen) != 0) {
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000245 msg_perr("Error: cannot write parameters: %s\n", strerror(errno));
246 return 1;
247 }
Stefan Tauner79587f52013-04-01 00:45:51 +0000248 if (serialport_read(&c, 1) != 0) {
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000249 msg_perr("Error: cannot read from device: %s\n", strerror(errno));
250 return 1;
251 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000252 if (c == S_NAK)
253 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000254 if (c != S_ACK) {
Stefan Tauner23e10b82016-01-23 16:16:49 +0000255 msg_perr("Error: invalid response 0x%02X from device (to command 0x%02X)\n", c, command);
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000256 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000257 }
258 if (retlen) {
Stefan Tauner79587f52013-04-01 00:45:51 +0000259 if (serialport_read(retparms, retlen) != 0) {
260 msg_perr("Error: cannot read return parameters: %s\n", strerror(errno));
261 return 1;
262 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000263 }
264 return 0;
265}
266
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000267static int sp_flush_stream(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000268{
269 if (sp_streamed_transmit_ops)
270 do {
271 unsigned char c;
Stefan Tauner79587f52013-04-01 00:45:51 +0000272 if (serialport_read(&c, 1) != 0) {
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000273 msg_perr("Error: cannot read from device (flushing stream)");
274 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000275 }
276 if (c == S_NAK) {
Sean Nelson74e8af52010-01-10 01:06:23 +0000277 msg_perr("Error: NAK to a stream buffer operation\n");
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000278 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000279 }
280 if (c != S_ACK) {
Sean Nelson74e8af52010-01-10 01:06:23 +0000281 msg_perr("Error: Invalid reply 0x%02X from device\n", c);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000282 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000283 }
284 } while (--sp_streamed_transmit_ops);
285 sp_streamed_transmit_ops = 0;
286 sp_streamed_transmit_bytes = 0;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000287 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000288}
289
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000290static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t *parms)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000291{
292 uint8_t *sp;
293 if (sp_automatic_cmdcheck(cmd))
294 return 1;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000295
Urja Rannikkof3196df2009-07-21 13:02:59 +0000296 sp = malloc(1 + parmlen);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000297 if (!sp) {
298 msg_perr("Error: cannot malloc command buffer\n");
299 return 1;
300 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000301 sp[0] = cmd;
aarya885917c2022-03-10 09:16:44 +0530302 if (parms)
303 memcpy(&(sp[1]), parms, parmlen);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000304
305 if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size)) {
306 if (sp_flush_stream() != 0) {
307 free(sp);
308 return 1;
309 }
310 }
311 if (serialport_write(sp, 1 + parmlen) != 0) {
312 msg_perr("Error: cannot write command\n");
313 free(sp);
314 return 1;
315 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000316 sp_streamed_transmit_ops += 1;
317 sp_streamed_transmit_bytes += 1 + parmlen;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000318
319 free(sp);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000320 return 0;
321}
322
Edward O'Callaghan5eca4272020-04-12 17:27:53 +1000323static int serprog_spi_send_command(const struct flashctx *flash,
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000324 unsigned int writecnt, unsigned int readcnt,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000325 const unsigned char *writearr,
326 unsigned char *readarr);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000327static struct spi_master spi_master_serprog = {
Nico Huber1cf407b2017-11-10 20:18:23 +0100328 .features = SPI_MASTER_4BA,
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000329 .max_data_read = MAX_DATA_READ_UNLIMITED,
330 .max_data_write = MAX_DATA_WRITE_UNLIMITED,
331 .command = serprog_spi_send_command,
332 .multicommand = default_spi_send_multicommand,
Urja Rannikko731316a2017-06-15 13:32:01 +0300333 .read = default_spi_read,
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000334 .write_256 = default_spi_write_256,
335};
336
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000337static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
338 chipaddr addr);
339static uint8_t serprog_chip_readb(const struct flashctx *flash,
340 const chipaddr addr);
341static void serprog_chip_readn(const struct flashctx *flash, uint8_t *buf,
342 const chipaddr addr, size_t len);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000343static const struct par_master par_master_serprog = {
Thomas Heijligen43040f22022-06-23 14:38:35 +0200344 .chip_readb = serprog_chip_readb,
345 .chip_readw = fallback_chip_readw,
346 .chip_readl = fallback_chip_readl,
347 .chip_readn = serprog_chip_readn,
348 .chip_writeb = serprog_chip_writeb,
349 .chip_writew = fallback_chip_writew,
350 .chip_writel = fallback_chip_writel,
351 .chip_writen = fallback_chip_writen,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000352};
353
354static enum chipbustype serprog_buses_supported = BUS_NONE;
355
Thomas Heijligencc853d82021-05-04 15:32:17 +0200356static int serprog_init(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000357{
358 uint16_t iface;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000359 unsigned char pgmname[17];
360 unsigned char rbuf[3];
361 unsigned char c;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000362 char *device;
Felix Singer815eb792022-08-19 01:02:42 +0200363 bool have_device = false;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000364
Stefan Tauner72587f82016-01-04 03:05:15 +0000365 /* the parameter is either of format "dev=/dev/device[:baud]" or "ip=ip:port" */
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000366 device = extract_programmer_param("dev");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000367 if (device && strlen(device)) {
Stefan Tauner72587f82016-01-04 03:05:15 +0000368 char *baud_str = strstr(device, ":");
369 if (baud_str != NULL) {
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000370 /* Split device from baudrate. */
Stefan Tauner72587f82016-01-04 03:05:15 +0000371 *baud_str = '\0';
372 baud_str++;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000373 }
Stefan Tauner72587f82016-01-04 03:05:15 +0000374 int baud;
375 /* Convert baud string to value.
376 * baud_str is either NULL (if strstr can't find the colon), points to the \0 after the colon
377 * if no characters where given after the colon, or a string to convert... */
378 if (baud_str == NULL || *baud_str == '\0') {
379 baud = -1;
380 msg_pdbg("No baudrate specified, using the hardware's defaults.\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000381 } else {
Stefan Tauner72587f82016-01-04 03:05:15 +0000382 baud = atoi(baud_str); // FIXME: replace atoi with strtoul
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000383 }
Stefan Tauner72587f82016-01-04 03:05:15 +0000384 if (strlen(device) > 0) {
385 sp_fd = sp_openserport(device, baud);
Stefan Tauneracfc4c62012-11-30 16:46:45 +0000386 if (sp_fd == SER_INV_FD) {
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000387 free(device);
388 return 1;
389 }
Felix Singer815eb792022-08-19 01:02:42 +0200390 have_device = true;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000391 }
392 }
Urja Rannikko27b431b2016-01-04 03:05:23 +0000393
394#if !IS_WINDOWS
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000395 if (device && !strlen(device)) {
396 msg_perr("Error: No device specified.\n"
Stefan Tauner72587f82016-01-04 03:05:15 +0000397 "Use flashrom -p serprog:dev=/dev/device[:baud]\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000398 free(device);
399 return 1;
400 }
401 free(device);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000402
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000403 device = extract_programmer_param("ip");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000404 if (have_device && device) {
405 msg_perr("Error: Both host and device specified.\n"
406 "Please use either dev= or ip= but not both.\n");
407 free(device);
408 return 1;
409 }
410 if (device && strlen(device)) {
Stefan Tauner72587f82016-01-04 03:05:15 +0000411 char *port = strstr(device, ":");
412 if (port != NULL) {
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000413 /* Split host from port. */
Stefan Tauner72587f82016-01-04 03:05:15 +0000414 *port = '\0';
415 port++;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000416 }
Stefan Tauner72587f82016-01-04 03:05:15 +0000417 if (!port || !strlen(port)) {
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000418 msg_perr("Error: No port specified.\n"
419 "Use flashrom -p serprog:ip=ipaddr:port\n");
420 free(device);
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000421 return 1;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000422 }
423 if (strlen(device)) {
Stefan Tauner72587f82016-01-04 03:05:15 +0000424 sp_fd = sp_opensocket(device, atoi(port)); // FIXME: replace atoi with strtoul
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000425 if (sp_fd < 0) {
426 free(device);
427 return 1;
428 }
Felix Singer815eb792022-08-19 01:02:42 +0200429 have_device = true;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000430 }
431 }
432 if (device && !strlen(device)) {
433 msg_perr("Error: No host specified.\n"
434 "Use flashrom -p serprog:ip=ipaddr:port\n");
435 free(device);
436 return 1;
437 }
Urja Rannikko27b431b2016-01-04 03:05:23 +0000438#endif
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000439 free(device);
440
441 if (!have_device) {
Urja Rannikko27b431b2016-01-04 03:05:23 +0000442#if IS_WINDOWS
443 msg_perr("Error: No device specified.\n"
444 "Use flashrom -p serprog:dev=comN[:baud]\n");
445#else
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000446 msg_perr("Error: Neither host nor device specified.\n"
447 "Use flashrom -p serprog:dev=/dev/device:baud or "
448 "flashrom -p serprog:ip=ipaddr:port\n");
Urja Rannikko27b431b2016-01-04 03:05:23 +0000449#endif
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000450 return 1;
451 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000452
Sean Nelson74e8af52010-01-10 01:06:23 +0000453 msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000454
455 sp_check_avail_automatic = 0;
456
Niklas Söderlund7145a502012-09-07 07:07:07 +0000457 if (sp_synchronize())
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000458 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000459
Sean Nelson74e8af52010-01-10 01:06:23 +0000460 msg_pdbg(MSGHEADER "Synchronized\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000461
462 if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
Stefan Tauner31019d42011-10-22 21:45:27 +0000463 msg_perr("Error: NAK to query interface version\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000464 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000465 }
466
467 if (iface != 1) {
Stefan Tauner31019d42011-10-22 21:45:27 +0000468 msg_perr("Error: Unknown interface version: %d\n", iface);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000469 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000470 }
471
Sean Nelson74e8af52010-01-10 01:06:23 +0000472 msg_pdbg(MSGHEADER "Interface version ok.\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000473
474 if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
Sean Nelson74e8af52010-01-10 01:06:23 +0000475 msg_perr("Error: query command map not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000476 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000477 }
478
479 sp_check_avail_automatic = 1;
480
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000481 /* FIXME: This assumes that serprog device bustypes are always
482 * identical with flashrom bustype enums and that they all fit
483 * in a single byte.
484 */
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000485 if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000486 msg_pwarn("Warning: NAK to query supported buses\n");
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000487 c = BUS_NONSPI; /* A reasonable default for now. */
Urja Rannikkof3196df2009-07-21 13:02:59 +0000488 }
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000489 serprog_buses_supported = c;
490
Stefan Tauner31019d42011-10-22 21:45:27 +0000491 msg_pdbg(MSGHEADER "Bus support: parallel=%s, LPC=%s, FWH=%s, SPI=%s\n",
492 (c & BUS_PARALLEL) ? "on" : "off",
493 (c & BUS_LPC) ? "on" : "off",
494 (c & BUS_FWH) ? "on" : "off",
495 (c & BUS_SPI) ? "on" : "off");
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000496 /* Check for the minimum operational set of commands. */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000497 if (serprog_buses_supported & BUS_SPI) {
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000498 uint8_t bt = BUS_SPI;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000499 char *spispeed;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000500 if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
501 msg_perr("Error: SPI operation not supported while the "
502 "bustype is SPI\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000503 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000504 }
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000505 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000506 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000507 /* Success of any of these commands is optional. We don't need
508 the programmer to tell us its limits, but if it doesn't, we
509 will assume stuff, so it's in the programmers best interest
510 to tell us. */
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000511 if (!sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
512 uint32_t v;
513 v = ((unsigned int)(rbuf[0]) << 0);
514 v |= ((unsigned int)(rbuf[1]) << 8);
515 v |= ((unsigned int)(rbuf[2]) << 16);
516 if (v == 0)
517 v = (1 << 24) - 1; /* SPI-op maximum. */
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000518 spi_master_serprog.max_data_write = v;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000519 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n", v);
520 }
521 if (!sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf)) {
522 uint32_t v;
523 v = ((unsigned int)(rbuf[0]) << 0);
524 v |= ((unsigned int)(rbuf[1]) << 8);
525 v |= ((unsigned int)(rbuf[2]) << 16);
526 if (v == 0)
527 v = (1 << 24) - 1; /* SPI-op maximum. */
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000528 spi_master_serprog.max_data_read = v;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000529 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n", v);
530 }
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000531 spispeed = extract_programmer_param("spispeed");
532 if (spispeed && strlen(spispeed)) {
533 uint32_t f_spi_req, f_spi;
534 uint8_t buf[4];
535 char *f_spi_suffix;
536
537 errno = 0;
538 f_spi_req = strtol(spispeed, &f_spi_suffix, 0);
539 if (errno != 0 || spispeed == f_spi_suffix) {
540 msg_perr("Error: Could not convert 'spispeed'.\n");
Stefan Taunere34e3e82013-01-01 00:06:51 +0000541 free(spispeed);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000542 goto init_err_cleanup_exit;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000543 }
544 if (strlen(f_spi_suffix) == 1) {
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000545 if (!strcasecmp(f_spi_suffix, "M")) {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000546 f_spi_req *= 1000000;
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000547 } else if (!strcasecmp(f_spi_suffix, "k")) {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000548 f_spi_req *= 1000;
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000549 } else {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000550 msg_perr("Error: Garbage following 'spispeed' value.\n");
Stefan Taunere34e3e82013-01-01 00:06:51 +0000551 free(spispeed);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000552 goto init_err_cleanup_exit;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000553 }
554 } else if (strlen(f_spi_suffix) > 1) {
555 msg_perr("Error: Garbage following 'spispeed' value.\n");
Stefan Taunere34e3e82013-01-01 00:06:51 +0000556 free(spispeed);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000557 goto init_err_cleanup_exit;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000558 }
559
560 buf[0] = (f_spi_req >> (0 * 8)) & 0xFF;
561 buf[1] = (f_spi_req >> (1 * 8)) & 0xFF;
562 buf[2] = (f_spi_req >> (2 * 8)) & 0xFF;
563 buf[3] = (f_spi_req >> (3 * 8)) & 0xFF;
564
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000565 if (sp_check_commandavail(S_CMD_S_SPI_FREQ) == 0) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000566 msg_pwarn(MSGHEADER "Warning: Setting the SPI clock rate is not supported!\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000567 } else if (sp_docommand(S_CMD_S_SPI_FREQ, 4, buf, 4, buf) == 0) {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000568 f_spi = buf[0];
569 f_spi |= buf[1] << (1 * 8);
570 f_spi |= buf[2] << (2 * 8);
571 f_spi |= buf[3] << (3 * 8);
572 msg_pdbg(MSGHEADER "Requested to set SPI clock frequency to %u Hz. "
573 "It was actually set to %u Hz\n", f_spi_req, f_spi);
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000574 } else {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000575 msg_pwarn(MSGHEADER "Setting SPI clock rate to %u Hz failed!\n", f_spi_req);
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000576 }
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000577 }
578 free(spispeed);
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000579 bt = serprog_buses_supported;
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000580 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000581 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000582 }
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000583
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000584 if (serprog_buses_supported & BUS_NONSPI) {
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000585 if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
586 msg_perr("Error: Initialize operation buffer "
587 "not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000588 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000589 }
590
591 if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
592 msg_perr("Error: Write to opbuf: "
593 "delay not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000594 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000595 }
596
597 /* S_CMD_O_EXEC availability checked later. */
598
599 if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
600 msg_perr("Error: Single byte read not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000601 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000602 }
603 /* This could be translated to single byte reads (if missing),
604 * but now we don't support that. */
605 if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
606 msg_perr("Error: Read n bytes not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000607 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000608 }
609 if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
610 msg_perr("Error: Write to opbuf: "
611 "write byte not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000612 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000613 }
614
615 if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
616 msg_pdbg(MSGHEADER "Write-n not supported");
617 sp_max_write_n = 0;
618 } else {
619 sp_max_write_n = ((unsigned int)(rbuf[0]) << 0);
620 sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8);
621 sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16);
622 if (!sp_max_write_n) {
623 sp_max_write_n = (1 << 24);
624 }
625 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n",
626 sp_max_write_n);
627 sp_write_n_buf = malloc(sp_max_write_n);
628 if (!sp_write_n_buf) {
629 msg_perr("Error: cannot allocate memory for "
630 "Write-n buffer\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000631 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000632 }
633 sp_write_n_bytes = 0;
634 }
635
636 if (sp_check_commandavail(S_CMD_Q_RDNMAXLEN) &&
637 (sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf) == 0)) {
638 sp_max_read_n = ((unsigned int)(rbuf[0]) << 0);
639 sp_max_read_n |= ((unsigned int)(rbuf[1]) << 8);
640 sp_max_read_n |= ((unsigned int)(rbuf[2]) << 16);
641 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n",
642 sp_max_read_n ? sp_max_read_n : (1 << 24));
643 } else {
644 msg_pdbg(MSGHEADER "Maximum read-n length "
645 "not reported\n");
646 sp_max_read_n = 0;
647 }
648
Urja Rannikkof3196df2009-07-21 13:02:59 +0000649 }
650
651 if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000652 msg_pwarn("Warning: NAK to query programmer name\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000653 strcpy((char *)pgmname, "(unknown)");
654 }
655 pgmname[16] = 0;
Stefan Tauner31019d42011-10-22 21:45:27 +0000656 msg_pinfo(MSGHEADER "Programmer name is \"%s\"\n", pgmname);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000657
658 if (sp_docommand(S_CMD_Q_SERBUF, 0, NULL, 2, &sp_device_serbuf_size)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000659 msg_pwarn("Warning: NAK to query serial buffer size\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000660 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000661 msg_pdbg(MSGHEADER "Serial buffer size is %d\n",
Urja Rannikkof3196df2009-07-21 13:02:59 +0000662 sp_device_serbuf_size);
663
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000664 if (sp_check_commandavail(S_CMD_O_INIT)) {
665 /* This would be inconsistent. */
666 if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
667 msg_perr("Error: Execute operation buffer not "
668 "supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000669 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000670 }
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000671
672 if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
673 msg_perr("Error: NAK to initialize operation buffer\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000674 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000675 }
676
677 if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2,
678 &sp_device_opbuf_size)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000679 msg_pwarn("Warning: NAK to query operation buffer size\n");
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000680 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000681 msg_pdbg(MSGHEADER "operation buffer size is %d\n",
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000682 sp_device_opbuf_size);
Elyes HAOUAS124ef382018-03-27 12:15:09 +0200683 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000684
Stefan Tauner92fefc92012-10-27 00:34:23 +0000685 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
686 uint8_t en = 1;
687 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) {
688 msg_perr("Error: could not enable output buffers\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000689 goto init_err_cleanup_exit;
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000690 } else {
Stefan Tauner92fefc92012-10-27 00:34:23 +0000691 msg_pdbg(MSGHEADER "Output drivers enabled\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000692 }
693 } else {
Stefan Tauner92fefc92012-10-27 00:34:23 +0000694 msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000695 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000696 sp_prev_was_write = 0;
697 sp_streamed_transmit_ops = 0;
698 sp_streamed_transmit_bytes = 0;
699 sp_opbuf_usage = 0;
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000700
701 if (register_shutdown(serprog_shutdown, NULL))
702 goto init_err_cleanup_exit;
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000703 if (serprog_buses_supported & BUS_SPI)
Nico Huber5e08e3e2021-05-11 17:38:14 +0200704 register_spi_master(&spi_master_serprog, NULL);
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000705 if (serprog_buses_supported & BUS_NONSPI)
Anastasia Klimchukb91a2032021-05-21 09:40:58 +1000706 register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI, NULL);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000707 return 0;
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000708
709init_err_cleanup_exit:
710 serprog_shutdown(NULL);
711 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000712}
713
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000714/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */
715static int sp_pass_writen(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000716{
717 unsigned char header[7];
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000718 msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr);
719 if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) {
720 if (sp_flush_stream() != 0) {
721 return 1;
722 }
723 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000724 /* In case it's just a single byte send it as a single write. */
725 if (sp_write_n_bytes == 1) {
726 sp_write_n_bytes = 0;
727 header[0] = (sp_write_n_addr >> 0) & 0xFF;
728 header[1] = (sp_write_n_addr >> 8) & 0xFF;
729 header[2] = (sp_write_n_addr >> 16) & 0xFF;
730 header[3] = sp_write_n_buf[0];
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000731 if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0)
732 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000733 sp_opbuf_usage += 5;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000734 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000735 }
736 header[0] = S_CMD_O_WRITEN;
737 header[1] = (sp_write_n_bytes >> 0) & 0xFF;
738 header[2] = (sp_write_n_bytes >> 8) & 0xFF;
739 header[3] = (sp_write_n_bytes >> 16) & 0xFF;
740 header[4] = (sp_write_n_addr >> 0) & 0xFF;
741 header[5] = (sp_write_n_addr >> 8) & 0xFF;
742 header[6] = (sp_write_n_addr >> 16) & 0xFF;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000743 if (serialport_write(header, 7) != 0) {
744 msg_perr(MSGHEADER "Error: cannot write write-n command\n");
745 return 1;
746 }
747 if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) {
748 msg_perr(MSGHEADER "Error: cannot write write-n data");
749 return 1;
750 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000751 sp_streamed_transmit_bytes += 7 + sp_write_n_bytes;
752 sp_streamed_transmit_ops += 1;
753 sp_opbuf_usage += 7 + sp_write_n_bytes;
754 sp_write_n_bytes = 0;
755 sp_prev_was_write = 0;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000756 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000757}
758
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000759static int sp_execute_opbuf_noflush(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000760{
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000761 if ((sp_max_write_n) && (sp_write_n_bytes)) {
762 if (sp_pass_writen() != 0) {
763 msg_perr("Error: could not transfer write buffer\n");
764 return 1;
765 }
766 }
767 if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) {
768 msg_perr("Error: could not execute command buffer\n");
769 return 1;
770 }
771 msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000772 sp_opbuf_usage = 0;
773 sp_prev_was_write = 0;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000774 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000775}
776
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000777static int sp_execute_opbuf(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000778{
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000779 if (sp_execute_opbuf_noflush() != 0)
780 return 1;
781 if (sp_flush_stream() != 0)
782 return 1;
783
784 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000785}
786
David Hendricks8bb20212011-06-14 01:35:36 +0000787static int serprog_shutdown(void *data)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000788{
Urja Rannikkof3196df2009-07-21 13:02:59 +0000789 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000790 if (sp_execute_opbuf() != 0)
791 msg_pwarn("Could not flush command buffer.\n");
Stefan Tauner92fefc92012-10-27 00:34:23 +0000792 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
793 uint8_t dis = 0;
794 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0)
795 msg_pdbg(MSGHEADER "Output drivers disabled\n");
796 else
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000797 msg_pwarn(MSGHEADER "%s: Warning: could not disable output buffers\n", __func__);
Stefan Tauner92fefc92012-10-27 00:34:23 +0000798 }
Niklas Söderlund7145a502012-09-07 07:07:07 +0000799 /* FIXME: fix sockets on windows(?), especially closing */
800 serialport_shutdown(&sp_fd);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000801 if (sp_max_write_n)
802 free(sp_write_n_buf);
803 return 0;
804}
805
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000806static int sp_check_opbuf_usage(int bytes_to_be_added)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000807{
808 if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) {
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000809 /* If this happens in the middle of a page load the page load will probably fail. */
810 msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n");
811 if (sp_execute_opbuf() != 0)
812 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000813 }
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000814 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000815}
816
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000817static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
818 chipaddr addr)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000819{
Sean Nelson74e8af52010-01-10 01:06:23 +0000820 msg_pspew("%s\n", __func__);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000821 if (sp_max_write_n) {
822 if ((sp_prev_was_write)
823 && (addr == (sp_write_n_addr + sp_write_n_bytes))) {
824 sp_write_n_buf[sp_write_n_bytes++] = val;
825 } else {
826 if ((sp_prev_was_write) && (sp_write_n_bytes))
827 sp_pass_writen();
828 sp_prev_was_write = 1;
829 sp_write_n_addr = addr;
830 sp_write_n_bytes = 1;
831 sp_write_n_buf[0] = val;
832 }
833 sp_check_opbuf_usage(7 + sp_write_n_bytes);
834 if (sp_write_n_bytes >= sp_max_write_n)
835 sp_pass_writen();
836 } else {
837 /* We will have to do single writeb ops. */
838 unsigned char writeb_parm[4];
839 sp_check_opbuf_usage(6);
840 writeb_parm[0] = (addr >> 0) & 0xFF;
841 writeb_parm[1] = (addr >> 8) & 0xFF;
842 writeb_parm[2] = (addr >> 16) & 0xFF;
843 writeb_parm[3] = val;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000844 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error
Urja Rannikkof3196df2009-07-21 13:02:59 +0000845 sp_opbuf_usage += 5;
846 }
847}
848
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000849static uint8_t serprog_chip_readb(const struct flashctx *flash,
850 const chipaddr addr)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000851{
852 unsigned char c;
853 unsigned char buf[3];
854 /* Will stream the read operation - eg. add it to the stream buffer, *
855 * then flush the buffer, then read the read answer. */
856 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
857 sp_execute_opbuf_noflush();
858 buf[0] = ((addr >> 0) & 0xFF);
859 buf[1] = ((addr >> 8) & 0xFF);
860 buf[2] = ((addr >> 16) & 0xFF);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000861 sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error
862 sp_flush_stream(); // FIXME: return error
Stefan Tauner79587f52013-04-01 00:45:51 +0000863 if (serialport_read(&c, 1) != 0)
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000864 msg_perr(MSGHEADER "readb byteread"); // FIXME: return error
Stefan Taunerc2333752013-07-13 23:31:37 +0000865 msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000866 return c;
867}
868
Uwe Hermann4e3d0b32010-03-25 23:18:41 +0000869/* Local version that really does the job, doesn't care of max_read_n. */
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000870static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000871{
Urja Rannikkof3196df2009-07-21 13:02:59 +0000872 unsigned char sbuf[6];
Stefan Tauner0554ca52013-07-25 22:54:25 +0000873 msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000874 /* Stream the read-n -- as above. */
875 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
876 sp_execute_opbuf_noflush();
877 sbuf[0] = ((addr >> 0) & 0xFF);
878 sbuf[1] = ((addr >> 8) & 0xFF);
879 sbuf[2] = ((addr >> 16) & 0xFF);
880 sbuf[3] = ((len >> 0) & 0xFF);
881 sbuf[4] = ((len >> 8) & 0xFF);
882 sbuf[5] = ((len >> 16) & 0xFF);
883 sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000884 if (sp_flush_stream() != 0)
885 return 1;
886 if (serialport_read(buf, len) != 0) {
887 msg_perr(MSGHEADER "Error: cannot read read-n data");
888 return 1;
889 }
890 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000891}
892
893/* The externally called version that makes sure that max_read_n is obeyed. */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000894static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf,
895 const chipaddr addr, size_t len)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000896{
897 size_t lenm = len;
898 chipaddr addrm = addr;
Stefan Tauner31019d42011-10-22 21:45:27 +0000899 while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) {
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000900 sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error
Urja Rannikkof3196df2009-07-21 13:02:59 +0000901 addrm += sp_max_read_n;
902 lenm -= sp_max_read_n;
903 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000904 if (lenm)
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000905 sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error
Urja Rannikkof3196df2009-07-21 13:02:59 +0000906}
907
Thomas Heijligencc853d82021-05-04 15:32:17 +0200908static void serprog_delay(unsigned int usecs)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000909{
910 unsigned char buf[4];
Stefan Tauner31019d42011-10-22 21:45:27 +0000911 msg_pspew("%s usecs=%d\n", __func__, usecs);
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000912 if (!sp_check_commandavail(S_CMD_O_DELAY)) {
Stefan Taunerd7d423b2012-10-20 09:13:16 +0000913 msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n");
Stefan Tauner31019d42011-10-22 21:45:27 +0000914 internal_delay(usecs);
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000915 return;
916 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000917 if ((sp_max_write_n) && (sp_write_n_bytes))
918 sp_pass_writen();
919 sp_check_opbuf_usage(5);
Stefan Tauner31019d42011-10-22 21:45:27 +0000920 buf[0] = ((usecs >> 0) & 0xFF);
921 buf[1] = ((usecs >> 8) & 0xFF);
922 buf[2] = ((usecs >> 16) & 0xFF);
923 buf[3] = ((usecs >> 24) & 0xFF);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000924 sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf);
925 sp_opbuf_usage += 5;
926 sp_prev_was_write = 0;
927}
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000928
Edward O'Callaghan5eca4272020-04-12 17:27:53 +1000929static int serprog_spi_send_command(const struct flashctx *flash,
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000930 unsigned int writecnt, unsigned int readcnt,
931 const unsigned char *writearr,
932 unsigned char *readarr)
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000933{
934 unsigned char *parmbuf;
935 int ret;
936 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000937 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) {
938 if (sp_execute_opbuf() != 0) {
939 msg_perr("Error: could not execute command buffer before sending SPI commands.\n");
940 return 1;
941 }
942 }
943
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000944 parmbuf = malloc(writecnt + 6);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000945 if (!parmbuf) {
946 msg_perr("Error: could not allocate SPI send param buffer.\n");
947 return 1;
948 }
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000949 parmbuf[0] = (writecnt >> 0) & 0xFF;
950 parmbuf[1] = (writecnt >> 8) & 0xFF;
951 parmbuf[2] = (writecnt >> 16) & 0xFF;
952 parmbuf[3] = (readcnt >> 0) & 0xFF;
953 parmbuf[4] = (readcnt >> 8) & 0xFF;
954 parmbuf[5] = (readcnt >> 16) & 0xFF;
955 memcpy(parmbuf + 6, writearr, writecnt);
956 ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt,
957 readarr);
958 free(parmbuf);
959 return ret;
960}
961
Thomas Heijligencc853d82021-05-04 15:32:17 +0200962static void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len)
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000963{
964 /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits
965 * correctly (usually setting them to one either in software (for FWH/LPC) or relying on the fact that
966 * the hardware observes a subset of the address bits only). Combined with the standard mapping of
967 * flashrom this creates a 16 MB-wide window just below the 4 GB boundary where serprog can operate (as
968 * needed for non-SPI chips). Below we make sure that the requested range is within this window. */
969 if ((phys_addr & 0xFF000000) == 0xFF000000) {
970 return (void*)phys_addr;
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000971 }
Elyes HAOUASec819d62019-06-09 17:50:51 +0200972 msg_pwarn(MSGHEADER "requested mapping %s is incompatible: 0x%zx bytes at 0x%0*" PRIxPTR ".\n",
973 descr, len, PRIxPTR_WIDTH, phys_addr);
974 return NULL;
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000975}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200976
977const struct programmer_entry programmer_serprog = {
978 .name = "serprog",
979 .type = OTHER,
980 /* FIXME */
981 .devs.note = "All programmer devices speaking the serprog protocol\n",
982 .init = serprog_init,
983 .map_flash_region = serprog_map,
Thomas Heijligencc853d82021-05-04 15:32:17 +0200984 .delay = serprog_delay,
985};