blob: 041657063a312aeb1ec0290570ed5b0e069e1440 [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,
Aarya Chaumal0cea7532022-07-04 18:21:50 +0530335 .probe_opcode = default_spi_probe_opcode,
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000336};
337
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000338static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
339 chipaddr addr);
340static uint8_t serprog_chip_readb(const struct flashctx *flash,
341 const chipaddr addr);
342static void serprog_chip_readn(const struct flashctx *flash, uint8_t *buf,
343 const chipaddr addr, size_t len);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000344static const struct par_master par_master_serprog = {
Thomas Heijligen43040f22022-06-23 14:38:35 +0200345 .chip_readb = serprog_chip_readb,
346 .chip_readw = fallback_chip_readw,
347 .chip_readl = fallback_chip_readl,
348 .chip_readn = serprog_chip_readn,
349 .chip_writeb = serprog_chip_writeb,
350 .chip_writew = fallback_chip_writew,
351 .chip_writel = fallback_chip_writel,
352 .chip_writen = fallback_chip_writen,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000353};
354
355static enum chipbustype serprog_buses_supported = BUS_NONE;
356
Thomas Heijligencc853d82021-05-04 15:32:17 +0200357static int serprog_init(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000358{
359 uint16_t iface;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000360 unsigned char pgmname[17];
361 unsigned char rbuf[3];
362 unsigned char c;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000363 char *device;
Felix Singer815eb792022-08-19 01:02:42 +0200364 bool have_device = false;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000365
Stefan Tauner72587f82016-01-04 03:05:15 +0000366 /* the parameter is either of format "dev=/dev/device[:baud]" or "ip=ip:port" */
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000367 device = extract_programmer_param("dev");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000368 if (device && strlen(device)) {
Stefan Tauner72587f82016-01-04 03:05:15 +0000369 char *baud_str = strstr(device, ":");
370 if (baud_str != NULL) {
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000371 /* Split device from baudrate. */
Stefan Tauner72587f82016-01-04 03:05:15 +0000372 *baud_str = '\0';
373 baud_str++;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000374 }
Stefan Tauner72587f82016-01-04 03:05:15 +0000375 int baud;
376 /* Convert baud string to value.
377 * baud_str is either NULL (if strstr can't find the colon), points to the \0 after the colon
378 * if no characters where given after the colon, or a string to convert... */
379 if (baud_str == NULL || *baud_str == '\0') {
380 baud = -1;
381 msg_pdbg("No baudrate specified, using the hardware's defaults.\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000382 } else {
Stefan Tauner72587f82016-01-04 03:05:15 +0000383 baud = atoi(baud_str); // FIXME: replace atoi with strtoul
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000384 }
Stefan Tauner72587f82016-01-04 03:05:15 +0000385 if (strlen(device) > 0) {
386 sp_fd = sp_openserport(device, baud);
Stefan Tauneracfc4c62012-11-30 16:46:45 +0000387 if (sp_fd == SER_INV_FD) {
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000388 free(device);
389 return 1;
390 }
Felix Singer815eb792022-08-19 01:02:42 +0200391 have_device = true;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000392 }
393 }
Urja Rannikko27b431b2016-01-04 03:05:23 +0000394
395#if !IS_WINDOWS
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000396 if (device && !strlen(device)) {
397 msg_perr("Error: No device specified.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200398 "Use flashprog -p serprog:dev=/dev/device[:baud]\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000399 free(device);
400 return 1;
401 }
402 free(device);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000403
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000404 device = extract_programmer_param("ip");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000405 if (have_device && device) {
406 msg_perr("Error: Both host and device specified.\n"
407 "Please use either dev= or ip= but not both.\n");
408 free(device);
409 return 1;
410 }
411 if (device && strlen(device)) {
Stefan Tauner72587f82016-01-04 03:05:15 +0000412 char *port = strstr(device, ":");
413 if (port != NULL) {
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000414 /* Split host from port. */
Stefan Tauner72587f82016-01-04 03:05:15 +0000415 *port = '\0';
416 port++;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000417 }
Stefan Tauner72587f82016-01-04 03:05:15 +0000418 if (!port || !strlen(port)) {
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000419 msg_perr("Error: No port specified.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200420 "Use flashprog -p serprog:ip=ipaddr:port\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000421 free(device);
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000422 return 1;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000423 }
424 if (strlen(device)) {
Stefan Tauner72587f82016-01-04 03:05:15 +0000425 sp_fd = sp_opensocket(device, atoi(port)); // FIXME: replace atoi with strtoul
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000426 if (sp_fd < 0) {
427 free(device);
428 return 1;
429 }
Felix Singer815eb792022-08-19 01:02:42 +0200430 have_device = true;
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000431 }
432 }
433 if (device && !strlen(device)) {
434 msg_perr("Error: No host specified.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200435 "Use flashprog -p serprog:ip=ipaddr:port\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000436 free(device);
437 return 1;
438 }
Urja Rannikko27b431b2016-01-04 03:05:23 +0000439#endif
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000440 free(device);
441
442 if (!have_device) {
Urja Rannikko27b431b2016-01-04 03:05:23 +0000443#if IS_WINDOWS
444 msg_perr("Error: No device specified.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200445 "Use flashprog -p serprog:dev=comN[:baud]\n");
Urja Rannikko27b431b2016-01-04 03:05:23 +0000446#else
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000447 msg_perr("Error: Neither host nor device specified.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200448 "Use flashprog -p serprog:dev=/dev/device:baud or "
449 "flashprog -p serprog:ip=ipaddr:port\n");
Urja Rannikko27b431b2016-01-04 03:05:23 +0000450#endif
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000451 return 1;
452 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000453
Sean Nelson74e8af52010-01-10 01:06:23 +0000454 msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000455
456 sp_check_avail_automatic = 0;
457
Niklas Söderlund7145a502012-09-07 07:07:07 +0000458 if (sp_synchronize())
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000459 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000460
Sean Nelson74e8af52010-01-10 01:06:23 +0000461 msg_pdbg(MSGHEADER "Synchronized\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000462
463 if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
Stefan Tauner31019d42011-10-22 21:45:27 +0000464 msg_perr("Error: NAK to query interface version\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000465 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000466 }
467
468 if (iface != 1) {
Stefan Tauner31019d42011-10-22 21:45:27 +0000469 msg_perr("Error: Unknown interface version: %d\n", iface);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000470 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000471 }
472
Sean Nelson74e8af52010-01-10 01:06:23 +0000473 msg_pdbg(MSGHEADER "Interface version ok.\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000474
475 if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
Sean Nelson74e8af52010-01-10 01:06:23 +0000476 msg_perr("Error: query command map not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000477 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000478 }
479
480 sp_check_avail_automatic = 1;
481
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000482 /* FIXME: This assumes that serprog device bustypes are always
Nico Huberc3b02dc2023-08-12 01:13:45 +0200483 * identical with flashprog bustype enums and that they all fit
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000484 * in a single byte.
485 */
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000486 if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000487 msg_pwarn("Warning: NAK to query supported buses\n");
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000488 c = BUS_NONSPI; /* A reasonable default for now. */
Urja Rannikkof3196df2009-07-21 13:02:59 +0000489 }
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000490 serprog_buses_supported = c;
491
Stefan Tauner31019d42011-10-22 21:45:27 +0000492 msg_pdbg(MSGHEADER "Bus support: parallel=%s, LPC=%s, FWH=%s, SPI=%s\n",
493 (c & BUS_PARALLEL) ? "on" : "off",
494 (c & BUS_LPC) ? "on" : "off",
495 (c & BUS_FWH) ? "on" : "off",
496 (c & BUS_SPI) ? "on" : "off");
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000497 /* Check for the minimum operational set of commands. */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000498 if (serprog_buses_supported & BUS_SPI) {
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000499 uint8_t bt = BUS_SPI;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000500 char *spispeed;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000501 if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
502 msg_perr("Error: SPI operation not supported while the "
503 "bustype is SPI\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000504 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000505 }
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000506 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000507 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000508 /* Success of any of these commands is optional. We don't need
509 the programmer to tell us its limits, but if it doesn't, we
510 will assume stuff, so it's in the programmers best interest
511 to tell us. */
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000512 if (!sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
513 uint32_t v;
514 v = ((unsigned int)(rbuf[0]) << 0);
515 v |= ((unsigned int)(rbuf[1]) << 8);
516 v |= ((unsigned int)(rbuf[2]) << 16);
517 if (v == 0)
518 v = (1 << 24) - 1; /* SPI-op maximum. */
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000519 spi_master_serprog.max_data_write = v;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000520 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n", v);
521 }
522 if (!sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf)) {
523 uint32_t v;
524 v = ((unsigned int)(rbuf[0]) << 0);
525 v |= ((unsigned int)(rbuf[1]) << 8);
526 v |= ((unsigned int)(rbuf[2]) << 16);
527 if (v == 0)
528 v = (1 << 24) - 1; /* SPI-op maximum. */
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000529 spi_master_serprog.max_data_read = v;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000530 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n", v);
531 }
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000532 spispeed = extract_programmer_param("spispeed");
533 if (spispeed && strlen(spispeed)) {
534 uint32_t f_spi_req, f_spi;
535 uint8_t buf[4];
536 char *f_spi_suffix;
537
538 errno = 0;
539 f_spi_req = strtol(spispeed, &f_spi_suffix, 0);
540 if (errno != 0 || spispeed == f_spi_suffix) {
541 msg_perr("Error: Could not convert 'spispeed'.\n");
Stefan Taunere34e3e82013-01-01 00:06:51 +0000542 free(spispeed);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000543 goto init_err_cleanup_exit;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000544 }
545 if (strlen(f_spi_suffix) == 1) {
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000546 if (!strcasecmp(f_spi_suffix, "M")) {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000547 f_spi_req *= 1000000;
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000548 } else if (!strcasecmp(f_spi_suffix, "k")) {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000549 f_spi_req *= 1000;
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000550 } else {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000551 msg_perr("Error: Garbage following 'spispeed' value.\n");
Stefan Taunere34e3e82013-01-01 00:06:51 +0000552 free(spispeed);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000553 goto init_err_cleanup_exit;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000554 }
555 } else if (strlen(f_spi_suffix) > 1) {
556 msg_perr("Error: Garbage following 'spispeed' value.\n");
Stefan Taunere34e3e82013-01-01 00:06:51 +0000557 free(spispeed);
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000558 goto init_err_cleanup_exit;
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000559 }
560
561 buf[0] = (f_spi_req >> (0 * 8)) & 0xFF;
562 buf[1] = (f_spi_req >> (1 * 8)) & 0xFF;
563 buf[2] = (f_spi_req >> (2 * 8)) & 0xFF;
564 buf[3] = (f_spi_req >> (3 * 8)) & 0xFF;
565
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000566 if (sp_check_commandavail(S_CMD_S_SPI_FREQ) == 0) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000567 msg_pwarn(MSGHEADER "Warning: Setting the SPI clock rate is not supported!\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000568 } else if (sp_docommand(S_CMD_S_SPI_FREQ, 4, buf, 4, buf) == 0) {
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000569 f_spi = buf[0];
570 f_spi |= buf[1] << (1 * 8);
571 f_spi |= buf[2] << (2 * 8);
572 f_spi |= buf[3] << (3 * 8);
573 msg_pdbg(MSGHEADER "Requested to set SPI clock frequency to %u Hz. "
574 "It was actually set to %u Hz\n", f_spi_req, f_spi);
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000575 } else {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000576 msg_pwarn(MSGHEADER "Setting SPI clock rate to %u Hz failed!\n", f_spi_req);
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000577 }
Stefan Taunerb98f6eb2012-08-13 16:33:04 +0000578 }
579 free(spispeed);
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000580 bt = serprog_buses_supported;
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000581 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000582 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000583 }
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000584
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000585 if (serprog_buses_supported & BUS_NONSPI) {
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000586 if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
587 msg_perr("Error: Initialize operation buffer "
588 "not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000589 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000590 }
591
592 if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
593 msg_perr("Error: Write to opbuf: "
594 "delay not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000595 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000596 }
597
598 /* S_CMD_O_EXEC availability checked later. */
599
600 if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
601 msg_perr("Error: Single byte read not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000602 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000603 }
604 /* This could be translated to single byte reads (if missing),
605 * but now we don't support that. */
606 if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
607 msg_perr("Error: Read n bytes not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000608 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000609 }
610 if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
611 msg_perr("Error: Write to opbuf: "
612 "write byte not supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000613 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000614 }
615
616 if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
617 msg_pdbg(MSGHEADER "Write-n not supported");
618 sp_max_write_n = 0;
619 } else {
620 sp_max_write_n = ((unsigned int)(rbuf[0]) << 0);
621 sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8);
622 sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16);
623 if (!sp_max_write_n) {
624 sp_max_write_n = (1 << 24);
625 }
626 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n",
627 sp_max_write_n);
628 sp_write_n_buf = malloc(sp_max_write_n);
629 if (!sp_write_n_buf) {
630 msg_perr("Error: cannot allocate memory for "
631 "Write-n buffer\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000632 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000633 }
634 sp_write_n_bytes = 0;
635 }
636
637 if (sp_check_commandavail(S_CMD_Q_RDNMAXLEN) &&
638 (sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf) == 0)) {
639 sp_max_read_n = ((unsigned int)(rbuf[0]) << 0);
640 sp_max_read_n |= ((unsigned int)(rbuf[1]) << 8);
641 sp_max_read_n |= ((unsigned int)(rbuf[2]) << 16);
642 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n",
643 sp_max_read_n ? sp_max_read_n : (1 << 24));
644 } else {
645 msg_pdbg(MSGHEADER "Maximum read-n length "
646 "not reported\n");
647 sp_max_read_n = 0;
648 }
649
Urja Rannikkof3196df2009-07-21 13:02:59 +0000650 }
651
652 if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000653 msg_pwarn("Warning: NAK to query programmer name\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000654 strcpy((char *)pgmname, "(unknown)");
655 }
656 pgmname[16] = 0;
Stefan Tauner31019d42011-10-22 21:45:27 +0000657 msg_pinfo(MSGHEADER "Programmer name is \"%s\"\n", pgmname);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000658
659 if (sp_docommand(S_CMD_Q_SERBUF, 0, NULL, 2, &sp_device_serbuf_size)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000660 msg_pwarn("Warning: NAK to query serial buffer size\n");
Urja Rannikkof3196df2009-07-21 13:02:59 +0000661 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000662 msg_pdbg(MSGHEADER "Serial buffer size is %d\n",
Urja Rannikkof3196df2009-07-21 13:02:59 +0000663 sp_device_serbuf_size);
664
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000665 if (sp_check_commandavail(S_CMD_O_INIT)) {
666 /* This would be inconsistent. */
667 if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
668 msg_perr("Error: Execute operation buffer not "
669 "supported\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000670 goto init_err_cleanup_exit;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000671 }
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000672
673 if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
674 msg_perr("Error: NAK to initialize operation buffer\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000675 goto init_err_cleanup_exit;
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000676 }
677
678 if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2,
679 &sp_device_opbuf_size)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000680 msg_pwarn("Warning: NAK to query operation buffer size\n");
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000681 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000682 msg_pdbg(MSGHEADER "operation buffer size is %d\n",
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000683 sp_device_opbuf_size);
Elyes HAOUAS124ef382018-03-27 12:15:09 +0200684 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000685
Stefan Tauner92fefc92012-10-27 00:34:23 +0000686 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
687 uint8_t en = 1;
688 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) {
689 msg_perr("Error: could not enable output buffers\n");
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000690 goto init_err_cleanup_exit;
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000691 } else {
Stefan Tauner92fefc92012-10-27 00:34:23 +0000692 msg_pdbg(MSGHEADER "Output drivers enabled\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000693 }
694 } else {
Stefan Tauner92fefc92012-10-27 00:34:23 +0000695 msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n");
Anastasia Klimchukf02db802021-05-24 10:07:56 +1000696 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000697 sp_prev_was_write = 0;
698 sp_streamed_transmit_ops = 0;
699 sp_streamed_transmit_bytes = 0;
700 sp_opbuf_usage = 0;
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000701
702 if (register_shutdown(serprog_shutdown, NULL))
703 goto init_err_cleanup_exit;
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000704 if (serprog_buses_supported & BUS_SPI)
Nico Huber5e08e3e2021-05-11 17:38:14 +0200705 register_spi_master(&spi_master_serprog, NULL);
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000706 if (serprog_buses_supported & BUS_NONSPI)
Anastasia Klimchukb91a2032021-05-21 09:40:58 +1000707 register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI, NULL);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000708 return 0;
Anastasia Klimchukc6ff17b2021-05-24 09:55:03 +1000709
710init_err_cleanup_exit:
711 serprog_shutdown(NULL);
712 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000713}
714
Nico Huberc3b02dc2023-08-12 01:13:45 +0200715/* Move an in flashprog buffer existing write-n operation to the on-device operation buffer. */
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000716static int sp_pass_writen(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000717{
718 unsigned char header[7];
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000719 msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr);
720 if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) {
721 if (sp_flush_stream() != 0) {
722 return 1;
723 }
724 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000725 /* In case it's just a single byte send it as a single write. */
726 if (sp_write_n_bytes == 1) {
727 sp_write_n_bytes = 0;
728 header[0] = (sp_write_n_addr >> 0) & 0xFF;
729 header[1] = (sp_write_n_addr >> 8) & 0xFF;
730 header[2] = (sp_write_n_addr >> 16) & 0xFF;
731 header[3] = sp_write_n_buf[0];
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000732 if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0)
733 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000734 sp_opbuf_usage += 5;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000735 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000736 }
737 header[0] = S_CMD_O_WRITEN;
738 header[1] = (sp_write_n_bytes >> 0) & 0xFF;
739 header[2] = (sp_write_n_bytes >> 8) & 0xFF;
740 header[3] = (sp_write_n_bytes >> 16) & 0xFF;
741 header[4] = (sp_write_n_addr >> 0) & 0xFF;
742 header[5] = (sp_write_n_addr >> 8) & 0xFF;
743 header[6] = (sp_write_n_addr >> 16) & 0xFF;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000744 if (serialport_write(header, 7) != 0) {
745 msg_perr(MSGHEADER "Error: cannot write write-n command\n");
746 return 1;
747 }
748 if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) {
749 msg_perr(MSGHEADER "Error: cannot write write-n data");
750 return 1;
751 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000752 sp_streamed_transmit_bytes += 7 + sp_write_n_bytes;
753 sp_streamed_transmit_ops += 1;
754 sp_opbuf_usage += 7 + sp_write_n_bytes;
755 sp_write_n_bytes = 0;
756 sp_prev_was_write = 0;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000757 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000758}
759
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000760static int sp_execute_opbuf_noflush(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000761{
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000762 if ((sp_max_write_n) && (sp_write_n_bytes)) {
763 if (sp_pass_writen() != 0) {
764 msg_perr("Error: could not transfer write buffer\n");
765 return 1;
766 }
767 }
768 if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) {
769 msg_perr("Error: could not execute command buffer\n");
770 return 1;
771 }
772 msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000773 sp_opbuf_usage = 0;
774 sp_prev_was_write = 0;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000775 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000776}
777
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000778static int sp_execute_opbuf(void)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000779{
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000780 if (sp_execute_opbuf_noflush() != 0)
781 return 1;
782 if (sp_flush_stream() != 0)
783 return 1;
784
785 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000786}
787
David Hendricks8bb20212011-06-14 01:35:36 +0000788static int serprog_shutdown(void *data)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000789{
Urja Rannikkof3196df2009-07-21 13:02:59 +0000790 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000791 if (sp_execute_opbuf() != 0)
792 msg_pwarn("Could not flush command buffer.\n");
Stefan Tauner92fefc92012-10-27 00:34:23 +0000793 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
794 uint8_t dis = 0;
795 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0)
796 msg_pdbg(MSGHEADER "Output drivers disabled\n");
797 else
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000798 msg_pwarn(MSGHEADER "%s: Warning: could not disable output buffers\n", __func__);
Stefan Tauner92fefc92012-10-27 00:34:23 +0000799 }
Niklas Söderlund7145a502012-09-07 07:07:07 +0000800 /* FIXME: fix sockets on windows(?), especially closing */
801 serialport_shutdown(&sp_fd);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000802 if (sp_max_write_n)
803 free(sp_write_n_buf);
804 return 0;
805}
806
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000807static int sp_check_opbuf_usage(int bytes_to_be_added)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000808{
809 if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) {
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000810 /* If this happens in the middle of a page load the page load will probably fail. */
811 msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n");
812 if (sp_execute_opbuf() != 0)
813 return 1;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000814 }
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000815 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000816}
817
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000818static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
819 chipaddr addr)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000820{
Sean Nelson74e8af52010-01-10 01:06:23 +0000821 msg_pspew("%s\n", __func__);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000822 if (sp_max_write_n) {
823 if ((sp_prev_was_write)
824 && (addr == (sp_write_n_addr + sp_write_n_bytes))) {
825 sp_write_n_buf[sp_write_n_bytes++] = val;
826 } else {
827 if ((sp_prev_was_write) && (sp_write_n_bytes))
828 sp_pass_writen();
829 sp_prev_was_write = 1;
830 sp_write_n_addr = addr;
831 sp_write_n_bytes = 1;
832 sp_write_n_buf[0] = val;
833 }
834 sp_check_opbuf_usage(7 + sp_write_n_bytes);
835 if (sp_write_n_bytes >= sp_max_write_n)
836 sp_pass_writen();
837 } else {
838 /* We will have to do single writeb ops. */
839 unsigned char writeb_parm[4];
840 sp_check_opbuf_usage(6);
841 writeb_parm[0] = (addr >> 0) & 0xFF;
842 writeb_parm[1] = (addr >> 8) & 0xFF;
843 writeb_parm[2] = (addr >> 16) & 0xFF;
844 writeb_parm[3] = val;
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000845 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error
Urja Rannikkof3196df2009-07-21 13:02:59 +0000846 sp_opbuf_usage += 5;
847 }
848}
849
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000850static uint8_t serprog_chip_readb(const struct flashctx *flash,
851 const chipaddr addr)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000852{
853 unsigned char c;
854 unsigned char buf[3];
855 /* Will stream the read operation - eg. add it to the stream buffer, *
856 * then flush the buffer, then read the read answer. */
857 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
858 sp_execute_opbuf_noflush();
859 buf[0] = ((addr >> 0) & 0xFF);
860 buf[1] = ((addr >> 8) & 0xFF);
861 buf[2] = ((addr >> 16) & 0xFF);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000862 sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error
863 sp_flush_stream(); // FIXME: return error
Stefan Tauner79587f52013-04-01 00:45:51 +0000864 if (serialport_read(&c, 1) != 0)
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000865 msg_perr(MSGHEADER "readb byteread"); // FIXME: return error
Stefan Taunerc2333752013-07-13 23:31:37 +0000866 msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000867 return c;
868}
869
Uwe Hermann4e3d0b32010-03-25 23:18:41 +0000870/* Local version that really does the job, doesn't care of max_read_n. */
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000871static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000872{
Urja Rannikkof3196df2009-07-21 13:02:59 +0000873 unsigned char sbuf[6];
Stefan Tauner0554ca52013-07-25 22:54:25 +0000874 msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000875 /* Stream the read-n -- as above. */
876 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
877 sp_execute_opbuf_noflush();
878 sbuf[0] = ((addr >> 0) & 0xFF);
879 sbuf[1] = ((addr >> 8) & 0xFF);
880 sbuf[2] = ((addr >> 16) & 0xFF);
881 sbuf[3] = ((len >> 0) & 0xFF);
882 sbuf[4] = ((len >> 8) & 0xFF);
883 sbuf[5] = ((len >> 16) & 0xFF);
884 sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000885 if (sp_flush_stream() != 0)
886 return 1;
887 if (serialport_read(buf, len) != 0) {
888 msg_perr(MSGHEADER "Error: cannot read read-n data");
889 return 1;
890 }
891 return 0;
Urja Rannikkof3196df2009-07-21 13:02:59 +0000892}
893
894/* The externally called version that makes sure that max_read_n is obeyed. */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000895static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf,
896 const chipaddr addr, size_t len)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000897{
898 size_t lenm = len;
899 chipaddr addrm = addr;
Stefan Tauner31019d42011-10-22 21:45:27 +0000900 while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) {
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000901 sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error
Urja Rannikkof3196df2009-07-21 13:02:59 +0000902 addrm += sp_max_read_n;
903 lenm -= sp_max_read_n;
904 }
Stefan Tauner31019d42011-10-22 21:45:27 +0000905 if (lenm)
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000906 sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error
Urja Rannikkof3196df2009-07-21 13:02:59 +0000907}
908
Thomas Heijligencc853d82021-05-04 15:32:17 +0200909static void serprog_delay(unsigned int usecs)
Urja Rannikkof3196df2009-07-21 13:02:59 +0000910{
911 unsigned char buf[4];
Stefan Tauner31019d42011-10-22 21:45:27 +0000912 msg_pspew("%s usecs=%d\n", __func__, usecs);
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000913 if (!sp_check_commandavail(S_CMD_O_DELAY)) {
Stefan Taunerd7d423b2012-10-20 09:13:16 +0000914 msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n");
Stefan Tauner31019d42011-10-22 21:45:27 +0000915 internal_delay(usecs);
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000916 return;
917 }
Urja Rannikkof3196df2009-07-21 13:02:59 +0000918 if ((sp_max_write_n) && (sp_write_n_bytes))
919 sp_pass_writen();
920 sp_check_opbuf_usage(5);
Stefan Tauner31019d42011-10-22 21:45:27 +0000921 buf[0] = ((usecs >> 0) & 0xFF);
922 buf[1] = ((usecs >> 8) & 0xFF);
923 buf[2] = ((usecs >> 16) & 0xFF);
924 buf[3] = ((usecs >> 24) & 0xFF);
Urja Rannikkof3196df2009-07-21 13:02:59 +0000925 sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf);
926 sp_opbuf_usage += 5;
927 sp_prev_was_write = 0;
928}
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000929
Edward O'Callaghan5eca4272020-04-12 17:27:53 +1000930static int serprog_spi_send_command(const struct flashctx *flash,
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000931 unsigned int writecnt, unsigned int readcnt,
932 const unsigned char *writearr,
933 unsigned char *readarr)
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000934{
935 unsigned char *parmbuf;
936 int ret;
937 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000938 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) {
939 if (sp_execute_opbuf() != 0) {
940 msg_perr("Error: could not execute command buffer before sending SPI commands.\n");
941 return 1;
942 }
943 }
944
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000945 parmbuf = malloc(writecnt + 6);
Stefan Taunerbdead0d2013-08-24 02:10:18 +0000946 if (!parmbuf) {
947 msg_perr("Error: could not allocate SPI send param buffer.\n");
948 return 1;
949 }
Urja Rannikkoc93f5f12011-09-15 23:38:14 +0000950 parmbuf[0] = (writecnt >> 0) & 0xFF;
951 parmbuf[1] = (writecnt >> 8) & 0xFF;
952 parmbuf[2] = (writecnt >> 16) & 0xFF;
953 parmbuf[3] = (readcnt >> 0) & 0xFF;
954 parmbuf[4] = (readcnt >> 8) & 0xFF;
955 parmbuf[5] = (readcnt >> 16) & 0xFF;
956 memcpy(parmbuf + 6, writearr, writecnt);
957 ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt,
958 readarr);
959 free(parmbuf);
960 return ret;
961}
962
Thomas Heijligencc853d82021-05-04 15:32:17 +0200963static void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len)
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000964{
965 /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits
966 * correctly (usually setting them to one either in software (for FWH/LPC) or relying on the fact that
967 * the hardware observes a subset of the address bits only). Combined with the standard mapping of
Nico Huberc3b02dc2023-08-12 01:13:45 +0200968 * flashprog this creates a 16 MB-wide window just below the 4 GB boundary where serprog can operate (as
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000969 * needed for non-SPI chips). Below we make sure that the requested range is within this window. */
970 if ((phys_addr & 0xFF000000) == 0xFF000000) {
971 return (void*)phys_addr;
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000972 }
Elyes HAOUASec819d62019-06-09 17:50:51 +0200973 msg_pwarn(MSGHEADER "requested mapping %s is incompatible: 0x%zx bytes at 0x%0*" PRIxPTR ".\n",
974 descr, len, PRIxPTR_WIDTH, phys_addr);
975 return NULL;
Urja Rannikko0b4ffd52015-06-29 23:24:23 +0000976}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200977
978const struct programmer_entry programmer_serprog = {
979 .name = "serprog",
980 .type = OTHER,
981 /* FIXME */
982 .devs.note = "All programmer devices speaking the serprog protocol\n",
983 .init = serprog_init,
984 .map_flash_region = serprog_map,
Thomas Heijligencc853d82021-05-04 15:32:17 +0200985 .delay = serprog_delay,
986};