blob: f8f8308365969bf203b1645b4d658cc10992ec42 [file] [log] [blame]
hailfinger37b4fbf2009-06-23 11:33:43 +00001/*
2 * This file is part of the flashrom project.
3 *
stefanct69965b62011-09-15 23:38:14 +00004 * Copyright (C) 2009, 2011 Urja Rannikko <urjaman@gmail.com>
hailfinger37b4fbf2009-06-23 11:33:43 +00005 * Copyright (C) 2009 Carl-Daniel Hailfinger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
hailfinger37b4fbf2009-06-23 11:33:43 +000016 */
17
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110018#include "platform.h"
19
hailfinger4f45a4f2009-08-12 13:32:56 +000020#include <stdio.h>
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110021#if ! IS_WINDOWS /* stuff (presumably) needed for sockets only */
hailfinger37b4fbf2009-06-23 11:33:43 +000022#include <stdlib.h>
hailfinger4f45a4f2009-08-12 13:32:56 +000023#include <unistd.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000024#include <fcntl.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000025#include <sys/socket.h>
26#include <arpa/inet.h>
27#include <netinet/in.h>
28#include <netinet/tcp.h>
29#include <netdb.h>
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110030#endif
31#if IS_WINDOWS
32#include <conio.h>
33#else
34#include <termios.h>
35#endif
36#include <string.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000037#include <errno.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000038#include <inttypes.h>
hailfinger428f6852010-07-27 22:41:39 +000039#include "flash.h"
40#include "programmer.h"
stefanct69965b62011-09-15 23:38:14 +000041#include "chipdrivers.h"
Patrick Georgib9fe7f12017-04-11 20:35:19 +020042#include "serprog.h"
hailfingerbacbc8b2009-07-21 13:02:59 +000043
stefanctd9ac2212011-10-22 21:45:27 +000044#define MSGHEADER "serprog: "
hailfingerbacbc8b2009-07-21 13:02:59 +000045
dhendrix0ffc2eb2011-06-14 01:35:36 +000046/*
47 * FIXME: This prototype was added to help reduce diffs for the shutdown
48 * registration patch, which shifted many lines of code to place
49 * serprog_shutdown() before serprog_init(). It should be removed soon.
50 */
David Hendricks93784b42016-08-09 17:00:38 -070051static int serprog_shutdown(void *data);
dhendrix0ffc2eb2011-06-14 01:35:36 +000052
hailfingerbacbc8b2009-07-21 13:02:59 +000053static uint16_t sp_device_serbuf_size = 16;
54static uint16_t sp_device_opbuf_size = 300;
55/* Bitmap of supported commands */
56static uint8_t sp_cmdmap[32];
57
uwe3a3ab2f2010-03-25 23:18:41 +000058/* sp_prev_was_write used to detect writes with contiguous addresses
hailfingerbacbc8b2009-07-21 13:02:59 +000059 and combine them to write-n's */
60static int sp_prev_was_write = 0;
61/* sp_write_n_addr used as the starting addr of the currently
62 combined write-n operation */
63static uint32_t sp_write_n_addr;
64/* The maximum length of an write_n operation; 0 = write-n not supported */
65static uint32_t sp_max_write_n = 0;
66/* The maximum length of a read_n operation; 0 = 2^24 */
67static uint32_t sp_max_read_n = 0;
68
69/* A malloc'd buffer for combining the operation's data
70 and a counter that tells how much data is there. */
71static uint8_t *sp_write_n_buf;
72static uint32_t sp_write_n_bytes = 0;
73
74/* sp_streamed_* used for flow control checking */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110075static unsigned int sp_streamed_transmit_ops = 0;
76static unsigned int sp_streamed_transmit_bytes = 0;
hailfingerbacbc8b2009-07-21 13:02:59 +000077
78/* sp_opbuf_usage used for counting the amount of
79 on-device operation buffer used */
80static int sp_opbuf_usage = 0;
81/* if true causes sp_docommand to automatically check
82 whether the command is supported before doing it */
83static int sp_check_avail_automatic = 0;
84
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110085#if ! IS_WINDOWS
hailfingerbacbc8b2009-07-21 13:02:59 +000086static int sp_opensocket(char *ip, unsigned int port)
87{
88 int flag = 1;
89 struct hostent *hostPtr = NULL;
hailfinger3e454f32009-09-05 01:10:23 +000090 union { struct sockaddr_in si; struct sockaddr s; } sp = {};
hailfingerbacbc8b2009-07-21 13:02:59 +000091 int sock;
snelson0afd28b2010-01-10 01:06:23 +000092 msg_pdbg(MSGHEADER "IP %s port %d\n", ip, port);
hailfingerbacbc8b2009-07-21 13:02:59 +000093 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110094 if (sock < 0) {
95 msg_perr("Error: serprog cannot open socket: %s\n", strerror(errno));
96 return -1;
97 }
hailfingerbacbc8b2009-07-21 13:02:59 +000098 hostPtr = gethostbyname(ip);
99 if (NULL == hostPtr) {
100 hostPtr = gethostbyaddr(ip, strlen(ip), AF_INET);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100101 if (NULL == hostPtr) {
102 close(sock);
103 msg_perr("Error: cannot resolve %s\n", ip);
104 return -1;
105 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000106 }
hailfinger3e454f32009-09-05 01:10:23 +0000107 sp.si.sin_family = AF_INET;
108 sp.si.sin_port = htons(port);
Edward O'Callaghan9987ad42019-09-03 15:58:56 +1000109 (void)memcpy(&sp.si.sin_addr, hostPtr->h_addr_list[0], hostPtr->h_length);
hailfinger3e454f32009-09-05 01:10:23 +0000110 if (connect(sock, &sp.s, sizeof(sp.si)) < 0) {
hailfingerbacbc8b2009-07-21 13:02:59 +0000111 close(sock);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100112 msg_perr("Error: serprog cannot connect: %s\n", strerror(errno));
113 return -1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000114 }
115 /* We are latency limited, and sometimes do write-write-read *
116 * (write-n) - so enable TCP_NODELAY. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100117 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) {
118 close(sock);
119 msg_perr("Error: serprog cannot set socket options: %s\n", strerror(errno));
120 return -1;
121 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000122 return sock;
123}
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100124#endif
hailfingerbacbc8b2009-07-21 13:02:59 +0000125
uwe3a3ab2f2010-03-25 23:18:41 +0000126/* Synchronize: a bit tricky algorithm that tries to (and in my tests has *
hailfingerbacbc8b2009-07-21 13:02:59 +0000127 * always succeeded in) bring the serial protocol to known waiting-for- *
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100128 * command state - uses nonblocking I/O - rest of the driver uses *
hailfingerbacbc8b2009-07-21 13:02:59 +0000129 * blocking read - TODO: add an alarm() timer for the rest of the app on *
130 * serial operations, though not such a big issue as the first thing to *
131 * do is synchronize (eg. check that device is alive). */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100132static int sp_synchronize(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000133{
134 int i;
hailfingerbacbc8b2009-07-21 13:02:59 +0000135 unsigned char buf[8];
hailfingerbacbc8b2009-07-21 13:02:59 +0000136 /* First sends 8 NOPs, then flushes the return data - should cause *
137 * the device serial parser to get to a sane state, unless if it *
138 * is waiting for a real long write-n. */
139 memset(buf, S_CMD_NOP, 8);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100140 if (serialport_write_nonblock(buf, 8, 1, NULL) != 0) {
141 goto err_out;
142 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000143 /* A second should be enough to get all the answers to the buffer */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100144 internal_delay(1000 * 1000);
hailfingerbacbc8b2009-07-21 13:02:59 +0000145 sp_flush_incoming();
146
stefanct371e7e82011-07-07 19:56:58 +0000147 /* Then try up to 8 times to send syncnop and get the correct special *
148 * return of NAK+ACK. Timing note: up to 10 characters, 10*50ms = *
149 * up to 500ms per try, 8*0.5s = 4s; +1s (above) = up to 5s sync *
150 * attempt, ~1s if immediate success. */
hailfingerbacbc8b2009-07-21 13:02:59 +0000151 for (i = 0; i < 8; i++) {
152 int n;
153 unsigned char c = S_CMD_SYNCNOP;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100154 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
155 goto err_out;
156 }
snelson0afd28b2010-01-10 01:06:23 +0000157 msg_pdbg(".");
hailfingerbacbc8b2009-07-21 13:02:59 +0000158 fflush(stdout);
159 for (n = 0; n < 10; n++) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100160 int ret = serialport_read_nonblock(&c, 1, 50, NULL);
161 if (ret < 0)
162 goto err_out;
163 if (ret > 0 || c != S_NAK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000164 continue;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100165 ret = serialport_read_nonblock(&c, 1, 20, NULL);
166 if (ret < 0)
167 goto err_out;
168 if (ret > 0 || c != S_ACK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000169 continue;
170 c = S_CMD_SYNCNOP;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100171 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
172 goto err_out;
173 }
174 ret = serialport_read_nonblock(&c, 1, 500, NULL);
175 if (ret < 0)
176 goto err_out;
177 if (ret > 0 || c != S_NAK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000178 break; /* fail */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100179 ret = serialport_read_nonblock(&c, 1, 100, NULL);
180 if (ret > 0 || ret < 0)
181 goto err_out;
hailfingerbacbc8b2009-07-21 13:02:59 +0000182 if (c != S_ACK)
183 break; /* fail */
snelson0afd28b2010-01-10 01:06:23 +0000184 msg_pdbg("\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100185 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000186 }
187 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100188err_out:
189 msg_perr("Error: cannot synchronize protocol - check communications and reset device?\n");
190 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000191}
192
193static int sp_check_commandavail(uint8_t command)
194{
195 int byteoffs, bitoffs;
196 byteoffs = command / 8;
197 bitoffs = command % 8;
198 return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
199}
200
201static int sp_automatic_cmdcheck(uint8_t cmd)
202{
203 if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
stefanctd9ac2212011-10-22 21:45:27 +0000204 msg_pdbg("Warning: Automatic command availability check failed "
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100205 "for cmd 0x%02x - won't execute cmd\n", cmd);
hailfingerbacbc8b2009-07-21 13:02:59 +0000206 return 1;
207 }
208 return 0;
209}
210
211static int sp_docommand(uint8_t command, uint32_t parmlen,
stefanctd9ac2212011-10-22 21:45:27 +0000212 uint8_t *params, uint32_t retlen, void *retparms)
hailfingerbacbc8b2009-07-21 13:02:59 +0000213{
hailfingerbacbc8b2009-07-21 13:02:59 +0000214 unsigned char c;
215 if (sp_automatic_cmdcheck(command))
216 return 1;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100217 if (serialport_write(&command, 1) != 0) {
218 msg_perr("Error: cannot write op code: %s\n", strerror(errno));
219 return 1;
220 }
221 if (serialport_write(params, parmlen) != 0) {
222 msg_perr("Error: cannot write parameters: %s\n", strerror(errno));
223 return 1;
224 }
225 if (serialport_read(&c, 1) != 0) {
226 msg_perr("Error: cannot read from device: %s\n", strerror(errno));
227 return 1;
228 }
stefanctd9ac2212011-10-22 21:45:27 +0000229 if (c == S_NAK)
230 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000231 if (c != S_ACK) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100232 msg_perr("Error: invalid response 0x%02X from device (to command 0x%02X)\n", c, command);
233 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000234 }
235 if (retlen) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100236 if (serialport_read(retparms, retlen) != 0) {
237 msg_perr("Error: cannot read return parameters: %s\n", strerror(errno));
238 return 1;
239 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000240 }
241 return 0;
242}
243
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100244static int sp_flush_stream(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000245{
246 if (sp_streamed_transmit_ops)
247 do {
248 unsigned char c;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100249 if (serialport_read(&c, 1) != 0) {
250 msg_perr("Error: cannot read from device (flushing stream)");
251 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000252 }
253 if (c == S_NAK) {
snelson0afd28b2010-01-10 01:06:23 +0000254 msg_perr("Error: NAK to a stream buffer operation\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100255 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000256 }
257 if (c != S_ACK) {
snelson0afd28b2010-01-10 01:06:23 +0000258 msg_perr("Error: Invalid reply 0x%02X from device\n", c);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100259 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000260 }
261 } while (--sp_streamed_transmit_ops);
262 sp_streamed_transmit_ops = 0;
263 sp_streamed_transmit_bytes = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100264 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000265}
266
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100267static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t *parms)
hailfingerbacbc8b2009-07-21 13:02:59 +0000268{
269 uint8_t *sp;
270 if (sp_automatic_cmdcheck(cmd))
271 return 1;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100272
hailfingerbacbc8b2009-07-21 13:02:59 +0000273 sp = malloc(1 + parmlen);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100274 if (!sp) {
275 msg_perr("Error: cannot malloc command buffer\n");
276 return 1;
277 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000278 sp[0] = cmd;
279 memcpy(&(sp[1]), parms, parmlen);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100280
281 if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size)) {
282 if (sp_flush_stream() != 0) {
283 free(sp);
284 return 1;
285 }
286 }
287 if (serialport_write(sp, 1 + parmlen) != 0) {
288 msg_perr("Error: cannot write command\n");
289 free(sp);
290 return 1;
291 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000292 sp_streamed_transmit_ops += 1;
293 sp_streamed_transmit_bytes += 1 + parmlen;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100294
295 free(sp);
hailfingerbacbc8b2009-07-21 13:02:59 +0000296 return 0;
297}
298
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100299static int serprog_spi_send_command(const struct flashctx *flash,
300 unsigned int writecnt, unsigned int readcnt,
hailfinger76bb7e92011-11-09 23:40:00 +0000301 const unsigned char *writearr,
302 unsigned char *readarr);
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100303static struct spi_master spi_master_serprog = {
stefanct69965b62011-09-15 23:38:14 +0000304 .type = SPI_CONTROLLER_SERPROG,
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000305 .features = SPI_MASTER_4BA,
stefanct69965b62011-09-15 23:38:14 +0000306 .max_data_read = MAX_DATA_READ_UNLIMITED,
307 .max_data_write = MAX_DATA_WRITE_UNLIMITED,
308 .command = serprog_spi_send_command,
309 .multicommand = default_spi_send_multicommand,
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000310 .read = default_spi_read,
stefanct69965b62011-09-15 23:38:14 +0000311 .write_256 = default_spi_write_256,
312};
313
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700314static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
315 chipaddr addr);
316static uint8_t serprog_chip_readb(const struct flashctx *flash,
317 const chipaddr addr);
318static void serprog_chip_readn(const struct flashctx *flash, uint8_t *buf,
319 const chipaddr addr, size_t len);
Patrick Georgi0a9533a2017-02-03 19:28:38 +0100320static const struct par_master par_master_serprog = {
hailfinger76bb7e92011-11-09 23:40:00 +0000321 .chip_readb = serprog_chip_readb,
322 .chip_readw = fallback_chip_readw,
323 .chip_readl = fallback_chip_readl,
324 .chip_readn = serprog_chip_readn,
325 .chip_writeb = serprog_chip_writeb,
326 .chip_writew = fallback_chip_writew,
327 .chip_writel = fallback_chip_writel,
328 .chip_writen = fallback_chip_writen,
329};
330
331static enum chipbustype serprog_buses_supported = BUS_NONE;
332
David Hendricksac1d25c2016-08-09 17:00:58 -0700333int serprog_init(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000334{
335 uint16_t iface;
hailfingerbacbc8b2009-07-21 13:02:59 +0000336 unsigned char pgmname[17];
337 unsigned char rbuf[3];
338 unsigned char c;
hailfinger1ef766d2010-07-06 09:55:48 +0000339 char *device;
hailfinger1ef766d2010-07-06 09:55:48 +0000340 int have_device = 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000341
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100342 /* the parameter is either of format "dev=/dev/device[:baud]" or "ip=ip:port" */
hailfingerddeb4ac2010-07-08 10:13:37 +0000343 device = extract_programmer_param("dev");
hailfinger1ef766d2010-07-06 09:55:48 +0000344 if (device && strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100345 char *baud_str = strstr(device, ":");
346 if (baud_str != NULL) {
hailfinger1ef766d2010-07-06 09:55:48 +0000347 /* Split device from baudrate. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100348 *baud_str = '\0';
349 baud_str++;
hailfinger1ef766d2010-07-06 09:55:48 +0000350 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100351 int baud;
352 /* Convert baud string to value.
353 * baud_str is either NULL (if strstr can't find the colon), points to the \0 after the colon
354 * if no characters where given after the colon, or a string to convert... */
355 if (baud_str == NULL || *baud_str == '\0') {
356 baud = -1;
357 msg_pdbg("No baudrate specified, using the hardware's defaults.\n");
358 } else
359 baud = atoi(baud_str); // FIXME: replace atoi with strtoul
360 if (strlen(device) > 0) {
361 sp_fd = sp_openserport(device, baud);
362 if (sp_fd == SER_INV_FD) {
363 free(device);
364 return 1;
365 }
hailfinger1ef766d2010-07-06 09:55:48 +0000366 have_device++;
367 }
368 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100369
370#if !IS_WINDOWS
hailfinger1ef766d2010-07-06 09:55:48 +0000371 if (device && !strlen(device)) {
372 msg_perr("Error: No device specified.\n"
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100373 "Use flashrom -p serprog:dev=/dev/device[:baud]\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000374 free(device);
375 return 1;
376 }
377 free(device);
hailfingerbacbc8b2009-07-21 13:02:59 +0000378
hailfingerddeb4ac2010-07-08 10:13:37 +0000379 device = extract_programmer_param("ip");
hailfinger1ef766d2010-07-06 09:55:48 +0000380 if (have_device && device) {
381 msg_perr("Error: Both host and device specified.\n"
382 "Please use either dev= or ip= but not both.\n");
383 free(device);
384 return 1;
385 }
386 if (device && strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100387 char *port = strstr(device, ":");
388 if (port != NULL) {
hailfinger1ef766d2010-07-06 09:55:48 +0000389 /* Split host from port. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100390 *port = '\0';
391 port++;
hailfinger1ef766d2010-07-06 09:55:48 +0000392 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100393 if (!port || !strlen(port)) {
hailfinger1ef766d2010-07-06 09:55:48 +0000394 msg_perr("Error: No port specified.\n"
395 "Use flashrom -p serprog:ip=ipaddr:port\n");
396 free(device);
stefanct69965b62011-09-15 23:38:14 +0000397 return 1;
hailfinger1ef766d2010-07-06 09:55:48 +0000398 }
399 if (strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100400 sp_fd = sp_opensocket(device, atoi(port)); // FIXME: replace atoi with strtoul
401 if (sp_fd < 0) {
402 free(device);
403 return 1;
404 }
hailfinger1ef766d2010-07-06 09:55:48 +0000405 have_device++;
406 }
407 }
408 if (device && !strlen(device)) {
409 msg_perr("Error: No host specified.\n"
410 "Use flashrom -p serprog:ip=ipaddr:port\n");
411 free(device);
412 return 1;
413 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100414#endif
hailfinger1ef766d2010-07-06 09:55:48 +0000415 free(device);
416
417 if (!have_device) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100418#if IS_WINDOWS
419 msg_perr("Error: No device specified.\n"
420 "Use flashrom -p serprog:dev=comN[:baud]\n");
421#else
hailfinger1ef766d2010-07-06 09:55:48 +0000422 msg_perr("Error: Neither host nor device specified.\n"
423 "Use flashrom -p serprog:dev=/dev/device:baud or "
424 "flashrom -p serprog:ip=ipaddr:port\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100425#endif
hailfinger1ef766d2010-07-06 09:55:48 +0000426 return 1;
427 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000428
dhendrix0ffc2eb2011-06-14 01:35:36 +0000429 if (register_shutdown(serprog_shutdown, NULL))
430 return 1;
431
snelson0afd28b2010-01-10 01:06:23 +0000432 msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000433
434 sp_check_avail_automatic = 0;
435
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100436 if (sp_synchronize())
437 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000438
snelson0afd28b2010-01-10 01:06:23 +0000439 msg_pdbg(MSGHEADER "Synchronized\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000440
441 if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
stefanctd9ac2212011-10-22 21:45:27 +0000442 msg_perr("Error: NAK to query interface version\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000443 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000444 }
445
446 if (iface != 1) {
stefanctd9ac2212011-10-22 21:45:27 +0000447 msg_perr("Error: Unknown interface version: %d\n", iface);
hailfinger76bb7e92011-11-09 23:40:00 +0000448 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000449 }
450
snelson0afd28b2010-01-10 01:06:23 +0000451 msg_pdbg(MSGHEADER "Interface version ok.\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000452
453 if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
snelson0afd28b2010-01-10 01:06:23 +0000454 msg_perr("Error: query command map not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000455 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000456 }
457
458 sp_check_avail_automatic = 1;
459
hailfinger76bb7e92011-11-09 23:40:00 +0000460 /* FIXME: This assumes that serprog device bustypes are always
461 * identical with flashrom bustype enums and that they all fit
462 * in a single byte.
463 */
stefanct69965b62011-09-15 23:38:14 +0000464 if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100465 msg_pwarn("Warning: NAK to query supported buses\n");
stefanct69965b62011-09-15 23:38:14 +0000466 c = BUS_NONSPI; /* A reasonable default for now. */
hailfingerbacbc8b2009-07-21 13:02:59 +0000467 }
hailfinger76bb7e92011-11-09 23:40:00 +0000468 serprog_buses_supported = c;
469
stefanctd9ac2212011-10-22 21:45:27 +0000470 msg_pdbg(MSGHEADER "Bus support: parallel=%s, LPC=%s, FWH=%s, SPI=%s\n",
471 (c & BUS_PARALLEL) ? "on" : "off",
472 (c & BUS_LPC) ? "on" : "off",
473 (c & BUS_FWH) ? "on" : "off",
474 (c & BUS_SPI) ? "on" : "off");
stefanct69965b62011-09-15 23:38:14 +0000475 /* Check for the minimum operational set of commands. */
hailfinger76bb7e92011-11-09 23:40:00 +0000476 if (serprog_buses_supported & BUS_SPI) {
stefanct69965b62011-09-15 23:38:14 +0000477 uint8_t bt = BUS_SPI;
478 if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
479 msg_perr("Error: SPI operation not supported while the "
480 "bustype is SPI\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000481 return 1;
stefanct69965b62011-09-15 23:38:14 +0000482 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100483 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
484 return 1;
stefanct69965b62011-09-15 23:38:14 +0000485 /* Success of any of these commands is optional. We don't need
486 the programmer to tell us its limits, but if it doesn't, we
487 will assume stuff, so it's in the programmers best interest
488 to tell us. */
stefanct69965b62011-09-15 23:38:14 +0000489 if (!sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
490 uint32_t v;
491 v = ((unsigned int)(rbuf[0]) << 0);
492 v |= ((unsigned int)(rbuf[1]) << 8);
493 v |= ((unsigned int)(rbuf[2]) << 16);
494 if (v == 0)
495 v = (1 << 24) - 1; /* SPI-op maximum. */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100496 spi_master_serprog.max_data_write = v;
stefanct69965b62011-09-15 23:38:14 +0000497 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n", v);
498 }
499 if (!sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf)) {
500 uint32_t v;
501 v = ((unsigned int)(rbuf[0]) << 0);
502 v |= ((unsigned int)(rbuf[1]) << 8);
503 v |= ((unsigned int)(rbuf[2]) << 16);
504 if (v == 0)
505 v = (1 << 24) - 1; /* SPI-op maximum. */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100506 spi_master_serprog.max_data_read = v;
stefanct69965b62011-09-15 23:38:14 +0000507 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n", v);
508 }
hailfinger76bb7e92011-11-09 23:40:00 +0000509 bt = serprog_buses_supported;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100510 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
511 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000512 }
stefanct69965b62011-09-15 23:38:14 +0000513
hailfinger76bb7e92011-11-09 23:40:00 +0000514 if (serprog_buses_supported & BUS_NONSPI) {
stefanct69965b62011-09-15 23:38:14 +0000515 if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
516 msg_perr("Error: Initialize operation buffer "
517 "not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000518 return 1;
stefanct69965b62011-09-15 23:38:14 +0000519 }
520
521 if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
522 msg_perr("Error: Write to opbuf: "
523 "delay not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000524 return 1;
stefanct69965b62011-09-15 23:38:14 +0000525 }
526
527 /* S_CMD_O_EXEC availability checked later. */
528
529 if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
530 msg_perr("Error: Single byte read not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000531 return 1;
stefanct69965b62011-09-15 23:38:14 +0000532 }
533 /* This could be translated to single byte reads (if missing),
534 * but now we don't support that. */
535 if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
536 msg_perr("Error: Read n bytes not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000537 return 1;
stefanct69965b62011-09-15 23:38:14 +0000538 }
539 if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
540 msg_perr("Error: Write to opbuf: "
541 "write byte not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000542 return 1;
stefanct69965b62011-09-15 23:38:14 +0000543 }
544
545 if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
546 msg_pdbg(MSGHEADER "Write-n not supported");
547 sp_max_write_n = 0;
548 } else {
549 sp_max_write_n = ((unsigned int)(rbuf[0]) << 0);
550 sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8);
551 sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16);
552 if (!sp_max_write_n) {
553 sp_max_write_n = (1 << 24);
554 }
555 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n",
556 sp_max_write_n);
557 sp_write_n_buf = malloc(sp_max_write_n);
558 if (!sp_write_n_buf) {
559 msg_perr("Error: cannot allocate memory for "
560 "Write-n buffer\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000561 return 1;
stefanct69965b62011-09-15 23:38:14 +0000562 }
563 sp_write_n_bytes = 0;
564 }
565
566 if (sp_check_commandavail(S_CMD_Q_RDNMAXLEN) &&
567 (sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf) == 0)) {
568 sp_max_read_n = ((unsigned int)(rbuf[0]) << 0);
569 sp_max_read_n |= ((unsigned int)(rbuf[1]) << 8);
570 sp_max_read_n |= ((unsigned int)(rbuf[2]) << 16);
571 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n",
572 sp_max_read_n ? sp_max_read_n : (1 << 24));
573 } else {
574 msg_pdbg(MSGHEADER "Maximum read-n length "
575 "not reported\n");
576 sp_max_read_n = 0;
577 }
578
hailfingerbacbc8b2009-07-21 13:02:59 +0000579 }
580
581 if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100582 msg_pwarn("Warning: NAK to query programmer name\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000583 strcpy((char *)pgmname, "(unknown)");
584 }
585 pgmname[16] = 0;
stefanctd9ac2212011-10-22 21:45:27 +0000586 msg_pinfo(MSGHEADER "Programmer name is \"%s\"\n", pgmname);
hailfingerbacbc8b2009-07-21 13:02:59 +0000587
588 if (sp_docommand(S_CMD_Q_SERBUF, 0, NULL, 2, &sp_device_serbuf_size)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100589 msg_pwarn("Warning: NAK to query serial buffer size\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000590 }
stefanctd9ac2212011-10-22 21:45:27 +0000591 msg_pdbg(MSGHEADER "Serial buffer size is %d\n",
hailfingerbacbc8b2009-07-21 13:02:59 +0000592 sp_device_serbuf_size);
593
stefanct69965b62011-09-15 23:38:14 +0000594 if (sp_check_commandavail(S_CMD_O_INIT)) {
595 /* This would be inconsistent. */
596 if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
597 msg_perr("Error: Execute operation buffer not "
598 "supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000599 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000600 }
stefanct69965b62011-09-15 23:38:14 +0000601
602 if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
603 msg_perr("Error: NAK to initialize operation buffer\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000604 return 1;
stefanct69965b62011-09-15 23:38:14 +0000605 }
606
607 if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2,
608 &sp_device_opbuf_size)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100609 msg_pwarn("Warning: NAK to query operation buffer size\n");
stefanct69965b62011-09-15 23:38:14 +0000610 }
stefanctd9ac2212011-10-22 21:45:27 +0000611 msg_pdbg(MSGHEADER "operation buffer size is %d\n",
stefanct69965b62011-09-15 23:38:14 +0000612 sp_device_opbuf_size);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100613 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000614
615 sp_prev_was_write = 0;
616 sp_streamed_transmit_ops = 0;
617 sp_streamed_transmit_bytes = 0;
618 sp_opbuf_usage = 0;
hailfinger76bb7e92011-11-09 23:40:00 +0000619 if (serprog_buses_supported & BUS_SPI)
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100620 register_spi_master(&spi_master_serprog);
hailfinger76bb7e92011-11-09 23:40:00 +0000621 if (serprog_buses_supported & BUS_NONSPI)
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100622 register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI);
hailfingerbacbc8b2009-07-21 13:02:59 +0000623 return 0;
624}
625
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100626/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */
627static int sp_pass_writen(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000628{
629 unsigned char header[7];
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100630 msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr);
631 if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) {
632 if (sp_flush_stream() != 0) {
633 return 1;
634 }
635 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000636 /* In case it's just a single byte send it as a single write. */
637 if (sp_write_n_bytes == 1) {
638 sp_write_n_bytes = 0;
639 header[0] = (sp_write_n_addr >> 0) & 0xFF;
640 header[1] = (sp_write_n_addr >> 8) & 0xFF;
641 header[2] = (sp_write_n_addr >> 16) & 0xFF;
642 header[3] = sp_write_n_buf[0];
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100643 if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0)
644 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000645 sp_opbuf_usage += 5;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100646 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000647 }
648 header[0] = S_CMD_O_WRITEN;
649 header[1] = (sp_write_n_bytes >> 0) & 0xFF;
650 header[2] = (sp_write_n_bytes >> 8) & 0xFF;
651 header[3] = (sp_write_n_bytes >> 16) & 0xFF;
652 header[4] = (sp_write_n_addr >> 0) & 0xFF;
653 header[5] = (sp_write_n_addr >> 8) & 0xFF;
654 header[6] = (sp_write_n_addr >> 16) & 0xFF;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100655 if (serialport_write(header, 7) != 0) {
656 msg_perr(MSGHEADER "Error: cannot write write-n command\n");
657 return 1;
658 }
659 if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) {
660 msg_perr(MSGHEADER "Error: cannot write write-n data");
661 return 1;
662 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000663 sp_streamed_transmit_bytes += 7 + sp_write_n_bytes;
664 sp_streamed_transmit_ops += 1;
665 sp_opbuf_usage += 7 + sp_write_n_bytes;
666 sp_write_n_bytes = 0;
667 sp_prev_was_write = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100668 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000669}
670
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100671static int sp_execute_opbuf_noflush(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000672{
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100673 if ((sp_max_write_n) && (sp_write_n_bytes)) {
674 if (sp_pass_writen() != 0) {
675 msg_perr("Error: could not transfer write buffer\n");
676 return 1;
677 }
678 }
679 if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) {
680 msg_perr("Error: could not execute command buffer\n");
681 return 1;
682 }
683 msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage);
hailfingerbacbc8b2009-07-21 13:02:59 +0000684 sp_opbuf_usage = 0;
685 sp_prev_was_write = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100686 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000687}
688
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100689static int sp_execute_opbuf(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000690{
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100691 if (sp_execute_opbuf_noflush() != 0)
692 return 1;
693 if (sp_flush_stream() != 0)
694 return 1;
695
696 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000697}
698
David Hendricks93784b42016-08-09 17:00:38 -0700699static int serprog_shutdown(void *data)
hailfingerbacbc8b2009-07-21 13:02:59 +0000700{
hailfingerbacbc8b2009-07-21 13:02:59 +0000701 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100702 if (sp_execute_opbuf() != 0)
703 msg_pwarn("Could not flush command buffer.\n");
704 /* FIXME: fix sockets on windows(?), especially closing */
705 serialport_shutdown(&sp_fd);
hailfingerbacbc8b2009-07-21 13:02:59 +0000706 if (sp_max_write_n)
707 free(sp_write_n_buf);
708 return 0;
709}
710
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100711static int sp_check_opbuf_usage(int bytes_to_be_added)
hailfingerbacbc8b2009-07-21 13:02:59 +0000712{
713 if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100714 /* If this happens in the middle of a page load the page load will probably fail. */
715 msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n");
716 if (sp_execute_opbuf() != 0)
717 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000718 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100719 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000720}
721
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100722static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
723 chipaddr addr)
hailfingerbacbc8b2009-07-21 13:02:59 +0000724{
snelson0afd28b2010-01-10 01:06:23 +0000725 msg_pspew("%s\n", __func__);
hailfingerbacbc8b2009-07-21 13:02:59 +0000726 if (sp_max_write_n) {
727 if ((sp_prev_was_write)
728 && (addr == (sp_write_n_addr + sp_write_n_bytes))) {
729 sp_write_n_buf[sp_write_n_bytes++] = val;
730 } else {
731 if ((sp_prev_was_write) && (sp_write_n_bytes))
732 sp_pass_writen();
733 sp_prev_was_write = 1;
734 sp_write_n_addr = addr;
735 sp_write_n_bytes = 1;
736 sp_write_n_buf[0] = val;
737 }
738 sp_check_opbuf_usage(7 + sp_write_n_bytes);
739 if (sp_write_n_bytes >= sp_max_write_n)
740 sp_pass_writen();
741 } else {
742 /* We will have to do single writeb ops. */
743 unsigned char writeb_parm[4];
744 sp_check_opbuf_usage(6);
745 writeb_parm[0] = (addr >> 0) & 0xFF;
746 writeb_parm[1] = (addr >> 8) & 0xFF;
747 writeb_parm[2] = (addr >> 16) & 0xFF;
748 writeb_parm[3] = val;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100749 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error
hailfingerbacbc8b2009-07-21 13:02:59 +0000750 sp_opbuf_usage += 5;
751 }
752}
753
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100754static uint8_t serprog_chip_readb(const struct flashctx *flash,
755 const chipaddr addr)
hailfingerbacbc8b2009-07-21 13:02:59 +0000756{
757 unsigned char c;
758 unsigned char buf[3];
759 /* Will stream the read operation - eg. add it to the stream buffer, *
760 * then flush the buffer, then read the read answer. */
761 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
762 sp_execute_opbuf_noflush();
763 buf[0] = ((addr >> 0) & 0xFF);
764 buf[1] = ((addr >> 8) & 0xFF);
765 buf[2] = ((addr >> 16) & 0xFF);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100766 sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error
767 sp_flush_stream(); // FIXME: return error
768 if (serialport_read(&c, 1) != 0)
769 msg_perr(MSGHEADER "readb byteread"); // FIXME: return error
Kangheui Won4974cc12019-10-18 12:59:01 +1100770 msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c);
hailfingerbacbc8b2009-07-21 13:02:59 +0000771 return c;
772}
773
uwe3a3ab2f2010-03-25 23:18:41 +0000774/* Local version that really does the job, doesn't care of max_read_n. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100775static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len)
hailfingerbacbc8b2009-07-21 13:02:59 +0000776{
hailfingerbacbc8b2009-07-21 13:02:59 +0000777 unsigned char sbuf[6];
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100778 msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len);
hailfingerbacbc8b2009-07-21 13:02:59 +0000779 /* Stream the read-n -- as above. */
780 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
781 sp_execute_opbuf_noflush();
782 sbuf[0] = ((addr >> 0) & 0xFF);
783 sbuf[1] = ((addr >> 8) & 0xFF);
784 sbuf[2] = ((addr >> 16) & 0xFF);
785 sbuf[3] = ((len >> 0) & 0xFF);
786 sbuf[4] = ((len >> 8) & 0xFF);
787 sbuf[5] = ((len >> 16) & 0xFF);
788 sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100789 if (sp_flush_stream() != 0)
790 return 1;
791 if (serialport_read(buf, len) != 0) {
792 msg_perr(MSGHEADER "Error: cannot read read-n data");
793 return 1;
794 }
795 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000796}
797
798/* The externally called version that makes sure that max_read_n is obeyed. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100799static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf,
800 const chipaddr addr, size_t len)
hailfingerbacbc8b2009-07-21 13:02:59 +0000801{
802 size_t lenm = len;
803 chipaddr addrm = addr;
stefanctd9ac2212011-10-22 21:45:27 +0000804 while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100805 sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error
hailfingerbacbc8b2009-07-21 13:02:59 +0000806 addrm += sp_max_read_n;
807 lenm -= sp_max_read_n;
808 }
stefanctd9ac2212011-10-22 21:45:27 +0000809 if (lenm)
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100810 sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error
hailfingerbacbc8b2009-07-21 13:02:59 +0000811}
812
Edward O'Callaghan8ebbd502019-09-03 15:11:02 +1000813void serprog_delay(unsigned int usecs)
hailfingerbacbc8b2009-07-21 13:02:59 +0000814{
815 unsigned char buf[4];
stefanctd9ac2212011-10-22 21:45:27 +0000816 msg_pspew("%s usecs=%d\n", __func__, usecs);
stefanct69965b62011-09-15 23:38:14 +0000817 if (!sp_check_commandavail(S_CMD_O_DELAY)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100818 msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n");
stefanctd9ac2212011-10-22 21:45:27 +0000819 internal_delay(usecs);
stefanct69965b62011-09-15 23:38:14 +0000820 return;
821 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000822 if ((sp_max_write_n) && (sp_write_n_bytes))
823 sp_pass_writen();
824 sp_check_opbuf_usage(5);
stefanctd9ac2212011-10-22 21:45:27 +0000825 buf[0] = ((usecs >> 0) & 0xFF);
826 buf[1] = ((usecs >> 8) & 0xFF);
827 buf[2] = ((usecs >> 16) & 0xFF);
828 buf[3] = ((usecs >> 24) & 0xFF);
hailfingerbacbc8b2009-07-21 13:02:59 +0000829 sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf);
830 sp_opbuf_usage += 5;
831 sp_prev_was_write = 0;
832}
stefanct69965b62011-09-15 23:38:14 +0000833
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100834static int serprog_spi_send_command(const struct flashctx *flash,
835 unsigned int writecnt, unsigned int readcnt,
836 const unsigned char *writearr,
837 unsigned char *readarr)
stefanct69965b62011-09-15 23:38:14 +0000838{
839 unsigned char *parmbuf;
840 int ret;
841 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100842 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) {
843 if (sp_execute_opbuf() != 0) {
844 msg_perr("Error: could not execute command buffer before sending SPI commands.\n");
845 return 1;
846 }
847 }
848
stefanct69965b62011-09-15 23:38:14 +0000849 parmbuf = malloc(writecnt + 6);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100850 if (!parmbuf) {
851 msg_perr("Error: could not allocate SPI send param buffer.\n");
852 return 1;
853 }
stefanct69965b62011-09-15 23:38:14 +0000854 parmbuf[0] = (writecnt >> 0) & 0xFF;
855 parmbuf[1] = (writecnt >> 8) & 0xFF;
856 parmbuf[2] = (writecnt >> 16) & 0xFF;
857 parmbuf[3] = (readcnt >> 0) & 0xFF;
858 parmbuf[4] = (readcnt >> 8) & 0xFF;
859 parmbuf[5] = (readcnt >> 16) & 0xFF;
860 memcpy(parmbuf + 6, writearr, writecnt);
861 ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt,
862 readarr);
863 free(parmbuf);
864 return ret;
865}