blob: 056d8d1aa6e54ee5fe4388f1ed36f3e239768af8 [file] [log] [blame]
hailfinger37b4fbf2009-06-23 11:33:43 +00001/*
2 * This file is part of the flashrom project.
3 *
stefanct69965b62011-09-15 23:38:14 +00004 * Copyright (C) 2009, 2011 Urja Rannikko <urjaman@gmail.com>
hailfinger37b4fbf2009-06-23 11:33:43 +00005 * Copyright (C) 2009 Carl-Daniel Hailfinger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
hailfinger37b4fbf2009-06-23 11:33:43 +000016 */
17
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110018#include "platform.h"
19
hailfinger4f45a4f2009-08-12 13:32:56 +000020#include <stdio.h>
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110021#if ! IS_WINDOWS /* stuff (presumably) needed for sockets only */
hailfinger37b4fbf2009-06-23 11:33:43 +000022#include <stdlib.h>
hailfinger4f45a4f2009-08-12 13:32:56 +000023#include <unistd.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000024#include <fcntl.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000025#include <sys/socket.h>
26#include <arpa/inet.h>
27#include <netinet/in.h>
28#include <netinet/tcp.h>
29#include <netdb.h>
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110030#endif
31#if IS_WINDOWS
32#include <conio.h>
33#else
34#include <termios.h>
35#endif
36#include <string.h>
hailfinger37b4fbf2009-06-23 11:33:43 +000037#include <errno.h>
hailfinger428f6852010-07-27 22:41:39 +000038#include "flash.h"
39#include "programmer.h"
stefanct69965b62011-09-15 23:38:14 +000040#include "chipdrivers.h"
Patrick Georgib9fe7f12017-04-11 20:35:19 +020041#include "serprog.h"
hailfingerbacbc8b2009-07-21 13:02:59 +000042
stefanctd9ac2212011-10-22 21:45:27 +000043#define MSGHEADER "serprog: "
hailfingerbacbc8b2009-07-21 13:02:59 +000044
hailfingerbacbc8b2009-07-21 13:02:59 +000045static uint16_t sp_device_serbuf_size = 16;
46static uint16_t sp_device_opbuf_size = 300;
47/* Bitmap of supported commands */
48static uint8_t sp_cmdmap[32];
49
uwe3a3ab2f2010-03-25 23:18:41 +000050/* sp_prev_was_write used to detect writes with contiguous addresses
hailfingerbacbc8b2009-07-21 13:02:59 +000051 and combine them to write-n's */
52static int sp_prev_was_write = 0;
53/* sp_write_n_addr used as the starting addr of the currently
54 combined write-n operation */
55static uint32_t sp_write_n_addr;
56/* The maximum length of an write_n operation; 0 = write-n not supported */
57static uint32_t sp_max_write_n = 0;
58/* The maximum length of a read_n operation; 0 = 2^24 */
59static uint32_t sp_max_read_n = 0;
60
61/* A malloc'd buffer for combining the operation's data
62 and a counter that tells how much data is there. */
63static uint8_t *sp_write_n_buf;
64static uint32_t sp_write_n_bytes = 0;
65
66/* sp_streamed_* used for flow control checking */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110067static unsigned int sp_streamed_transmit_ops = 0;
68static unsigned int sp_streamed_transmit_bytes = 0;
hailfingerbacbc8b2009-07-21 13:02:59 +000069
70/* sp_opbuf_usage used for counting the amount of
71 on-device operation buffer used */
72static int sp_opbuf_usage = 0;
73/* if true causes sp_docommand to automatically check
74 whether the command is supported before doing it */
75static int sp_check_avail_automatic = 0;
76
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110077#if ! IS_WINDOWS
hailfingerbacbc8b2009-07-21 13:02:59 +000078static int sp_opensocket(char *ip, unsigned int port)
79{
80 int flag = 1;
81 struct hostent *hostPtr = NULL;
hailfinger3e454f32009-09-05 01:10:23 +000082 union { struct sockaddr_in si; struct sockaddr s; } sp = {};
hailfingerbacbc8b2009-07-21 13:02:59 +000083 int sock;
snelson0afd28b2010-01-10 01:06:23 +000084 msg_pdbg(MSGHEADER "IP %s port %d\n", ip, port);
hailfingerbacbc8b2009-07-21 13:02:59 +000085 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110086 if (sock < 0) {
87 msg_perr("Error: serprog cannot open socket: %s\n", strerror(errno));
88 return -1;
89 }
hailfingerbacbc8b2009-07-21 13:02:59 +000090 hostPtr = gethostbyname(ip);
91 if (NULL == hostPtr) {
92 hostPtr = gethostbyaddr(ip, strlen(ip), AF_INET);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +110093 if (NULL == hostPtr) {
94 close(sock);
95 msg_perr("Error: cannot resolve %s\n", ip);
96 return -1;
97 }
hailfingerbacbc8b2009-07-21 13:02:59 +000098 }
hailfinger3e454f32009-09-05 01:10:23 +000099 sp.si.sin_family = AF_INET;
100 sp.si.sin_port = htons(port);
Edward O'Callaghan9987ad42019-09-03 15:58:56 +1000101 (void)memcpy(&sp.si.sin_addr, hostPtr->h_addr_list[0], hostPtr->h_length);
hailfinger3e454f32009-09-05 01:10:23 +0000102 if (connect(sock, &sp.s, sizeof(sp.si)) < 0) {
hailfingerbacbc8b2009-07-21 13:02:59 +0000103 close(sock);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100104 msg_perr("Error: serprog cannot connect: %s\n", strerror(errno));
105 return -1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000106 }
107 /* We are latency limited, and sometimes do write-write-read *
108 * (write-n) - so enable TCP_NODELAY. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100109 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) {
110 close(sock);
111 msg_perr("Error: serprog cannot set socket options: %s\n", strerror(errno));
112 return -1;
113 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000114 return sock;
115}
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100116#endif
hailfingerbacbc8b2009-07-21 13:02:59 +0000117
uwe3a3ab2f2010-03-25 23:18:41 +0000118/* Synchronize: a bit tricky algorithm that tries to (and in my tests has *
hailfingerbacbc8b2009-07-21 13:02:59 +0000119 * always succeeded in) bring the serial protocol to known waiting-for- *
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100120 * command state - uses nonblocking I/O - rest of the driver uses *
hailfingerbacbc8b2009-07-21 13:02:59 +0000121 * blocking read - TODO: add an alarm() timer for the rest of the app on *
122 * serial operations, though not such a big issue as the first thing to *
123 * do is synchronize (eg. check that device is alive). */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100124static int sp_synchronize(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000125{
126 int i;
hailfingerbacbc8b2009-07-21 13:02:59 +0000127 unsigned char buf[8];
hailfingerbacbc8b2009-07-21 13:02:59 +0000128 /* First sends 8 NOPs, then flushes the return data - should cause *
129 * the device serial parser to get to a sane state, unless if it *
130 * is waiting for a real long write-n. */
131 memset(buf, S_CMD_NOP, 8);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100132 if (serialport_write_nonblock(buf, 8, 1, NULL) != 0) {
133 goto err_out;
134 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000135 /* A second should be enough to get all the answers to the buffer */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100136 internal_delay(1000 * 1000);
hailfingerbacbc8b2009-07-21 13:02:59 +0000137 sp_flush_incoming();
138
stefanct371e7e82011-07-07 19:56:58 +0000139 /* Then try up to 8 times to send syncnop and get the correct special *
140 * return of NAK+ACK. Timing note: up to 10 characters, 10*50ms = *
141 * up to 500ms per try, 8*0.5s = 4s; +1s (above) = up to 5s sync *
142 * attempt, ~1s if immediate success. */
hailfingerbacbc8b2009-07-21 13:02:59 +0000143 for (i = 0; i < 8; i++) {
144 int n;
145 unsigned char c = S_CMD_SYNCNOP;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100146 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
147 goto err_out;
148 }
snelson0afd28b2010-01-10 01:06:23 +0000149 msg_pdbg(".");
hailfingerbacbc8b2009-07-21 13:02:59 +0000150 fflush(stdout);
151 for (n = 0; n < 10; n++) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100152 int ret = serialport_read_nonblock(&c, 1, 50, NULL);
153 if (ret < 0)
154 goto err_out;
155 if (ret > 0 || c != S_NAK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000156 continue;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100157 ret = serialport_read_nonblock(&c, 1, 20, NULL);
158 if (ret < 0)
159 goto err_out;
160 if (ret > 0 || c != S_ACK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000161 continue;
162 c = S_CMD_SYNCNOP;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100163 if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
164 goto err_out;
165 }
166 ret = serialport_read_nonblock(&c, 1, 500, NULL);
167 if (ret < 0)
168 goto err_out;
169 if (ret > 0 || c != S_NAK)
hailfingerbacbc8b2009-07-21 13:02:59 +0000170 break; /* fail */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100171 ret = serialport_read_nonblock(&c, 1, 100, NULL);
172 if (ret > 0 || ret < 0)
173 goto err_out;
hailfingerbacbc8b2009-07-21 13:02:59 +0000174 if (c != S_ACK)
175 break; /* fail */
snelson0afd28b2010-01-10 01:06:23 +0000176 msg_pdbg("\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100177 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000178 }
179 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100180err_out:
181 msg_perr("Error: cannot synchronize protocol - check communications and reset device?\n");
182 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000183}
184
185static int sp_check_commandavail(uint8_t command)
186{
187 int byteoffs, bitoffs;
188 byteoffs = command / 8;
189 bitoffs = command % 8;
190 return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
191}
192
193static int sp_automatic_cmdcheck(uint8_t cmd)
194{
195 if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
stefanctd9ac2212011-10-22 21:45:27 +0000196 msg_pdbg("Warning: Automatic command availability check failed "
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100197 "for cmd 0x%02x - won't execute cmd\n", cmd);
hailfingerbacbc8b2009-07-21 13:02:59 +0000198 return 1;
199 }
200 return 0;
201}
202
203static int sp_docommand(uint8_t command, uint32_t parmlen,
stefanctd9ac2212011-10-22 21:45:27 +0000204 uint8_t *params, uint32_t retlen, void *retparms)
hailfingerbacbc8b2009-07-21 13:02:59 +0000205{
hailfingerbacbc8b2009-07-21 13:02:59 +0000206 unsigned char c;
207 if (sp_automatic_cmdcheck(command))
208 return 1;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100209 if (serialport_write(&command, 1) != 0) {
210 msg_perr("Error: cannot write op code: %s\n", strerror(errno));
211 return 1;
212 }
213 if (serialport_write(params, parmlen) != 0) {
214 msg_perr("Error: cannot write parameters: %s\n", strerror(errno));
215 return 1;
216 }
217 if (serialport_read(&c, 1) != 0) {
218 msg_perr("Error: cannot read from device: %s\n", strerror(errno));
219 return 1;
220 }
stefanctd9ac2212011-10-22 21:45:27 +0000221 if (c == S_NAK)
222 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000223 if (c != S_ACK) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100224 msg_perr("Error: invalid response 0x%02X from device (to command 0x%02X)\n", c, command);
225 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000226 }
227 if (retlen) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100228 if (serialport_read(retparms, retlen) != 0) {
229 msg_perr("Error: cannot read return parameters: %s\n", strerror(errno));
230 return 1;
231 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000232 }
233 return 0;
234}
235
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100236static int sp_flush_stream(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000237{
238 if (sp_streamed_transmit_ops)
239 do {
240 unsigned char c;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100241 if (serialport_read(&c, 1) != 0) {
242 msg_perr("Error: cannot read from device (flushing stream)");
243 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000244 }
245 if (c == S_NAK) {
snelson0afd28b2010-01-10 01:06:23 +0000246 msg_perr("Error: NAK to a stream buffer operation\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100247 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000248 }
249 if (c != S_ACK) {
snelson0afd28b2010-01-10 01:06:23 +0000250 msg_perr("Error: Invalid reply 0x%02X from device\n", c);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100251 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000252 }
253 } while (--sp_streamed_transmit_ops);
254 sp_streamed_transmit_ops = 0;
255 sp_streamed_transmit_bytes = 0;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100256 return 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000257}
258
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100259static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t *parms)
hailfingerbacbc8b2009-07-21 13:02:59 +0000260{
261 uint8_t *sp;
262 if (sp_automatic_cmdcheck(cmd))
263 return 1;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100264
hailfingerbacbc8b2009-07-21 13:02:59 +0000265 sp = malloc(1 + parmlen);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100266 if (!sp) {
267 msg_perr("Error: cannot malloc command buffer\n");
268 return 1;
269 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000270 sp[0] = cmd;
271 memcpy(&(sp[1]), parms, parmlen);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100272
273 if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size)) {
274 if (sp_flush_stream() != 0) {
275 free(sp);
276 return 1;
277 }
278 }
279 if (serialport_write(sp, 1 + parmlen) != 0) {
280 msg_perr("Error: cannot write command\n");
281 free(sp);
282 return 1;
283 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000284 sp_streamed_transmit_ops += 1;
285 sp_streamed_transmit_bytes += 1 + parmlen;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100286
287 free(sp);
hailfingerbacbc8b2009-07-21 13:02:59 +0000288 return 0;
289}
290
Anastasia Klimchuka7d0e7b2021-02-15 15:02:00 +1100291/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */
292static int sp_pass_writen(void)
293{
294 unsigned char header[7];
295 msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr);
296 if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) {
297 if (sp_flush_stream() != 0) {
298 return 1;
299 }
300 }
301 /* In case it's just a single byte send it as a single write. */
302 if (sp_write_n_bytes == 1) {
303 sp_write_n_bytes = 0;
304 header[0] = (sp_write_n_addr >> 0) & 0xFF;
305 header[1] = (sp_write_n_addr >> 8) & 0xFF;
306 header[2] = (sp_write_n_addr >> 16) & 0xFF;
307 header[3] = sp_write_n_buf[0];
308 if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0)
309 return 1;
310 sp_opbuf_usage += 5;
311 return 0;
312 }
313 header[0] = S_CMD_O_WRITEN;
314 header[1] = (sp_write_n_bytes >> 0) & 0xFF;
315 header[2] = (sp_write_n_bytes >> 8) & 0xFF;
316 header[3] = (sp_write_n_bytes >> 16) & 0xFF;
317 header[4] = (sp_write_n_addr >> 0) & 0xFF;
318 header[5] = (sp_write_n_addr >> 8) & 0xFF;
319 header[6] = (sp_write_n_addr >> 16) & 0xFF;
320 if (serialport_write(header, 7) != 0) {
321 msg_perr(MSGHEADER "Error: cannot write write-n command\n");
322 return 1;
323 }
324 if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) {
325 msg_perr(MSGHEADER "Error: cannot write write-n data");
326 return 1;
327 }
328 sp_streamed_transmit_bytes += 7 + sp_write_n_bytes;
329 sp_streamed_transmit_ops += 1;
330 sp_opbuf_usage += 7 + sp_write_n_bytes;
331 sp_write_n_bytes = 0;
332 sp_prev_was_write = 0;
333 return 0;
334}
335
336static int sp_execute_opbuf_noflush(void)
337{
338 if ((sp_max_write_n) && (sp_write_n_bytes)) {
339 if (sp_pass_writen() != 0) {
340 msg_perr("Error: could not transfer write buffer\n");
341 return 1;
342 }
343 }
344 if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) {
345 msg_perr("Error: could not execute command buffer\n");
346 return 1;
347 }
348 msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage);
349 sp_opbuf_usage = 0;
350 sp_prev_was_write = 0;
351 return 0;
352}
353
354static int sp_execute_opbuf(void)
355{
356 if (sp_execute_opbuf_noflush() != 0)
357 return 1;
358 if (sp_flush_stream() != 0)
359 return 1;
360
361 return 0;
362}
363
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100364static int serprog_spi_send_command(const struct flashctx *flash,
365 unsigned int writecnt, unsigned int readcnt,
hailfinger76bb7e92011-11-09 23:40:00 +0000366 const unsigned char *writearr,
Anastasia Klimchuka7d0e7b2021-02-15 15:02:00 +1100367 unsigned char *readarr)
368{
369 unsigned char *parmbuf;
370 int ret;
371 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
372 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) {
373 if (sp_execute_opbuf() != 0) {
374 msg_perr("Error: could not execute command buffer before sending SPI commands.\n");
375 return 1;
376 }
377 }
378
379 parmbuf = malloc(writecnt + 6);
380 if (!parmbuf) {
381 msg_perr("Error: could not allocate SPI send param buffer.\n");
382 return 1;
383 }
384 parmbuf[0] = (writecnt >> 0) & 0xFF;
385 parmbuf[1] = (writecnt >> 8) & 0xFF;
386 parmbuf[2] = (writecnt >> 16) & 0xFF;
387 parmbuf[3] = (readcnt >> 0) & 0xFF;
388 parmbuf[4] = (readcnt >> 8) & 0xFF;
389 parmbuf[5] = (readcnt >> 16) & 0xFF;
390 memcpy(parmbuf + 6, writearr, writecnt);
391 ret = sp_docommand(S_CMD_O_SPIOP, writecnt + 6, parmbuf, readcnt,
392 readarr);
393 free(parmbuf);
394 return ret;
395}
396
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100397static struct spi_master spi_master_serprog = {
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000398 .features = SPI_MASTER_4BA,
stefanct69965b62011-09-15 23:38:14 +0000399 .max_data_read = MAX_DATA_READ_UNLIMITED,
400 .max_data_write = MAX_DATA_WRITE_UNLIMITED,
401 .command = serprog_spi_send_command,
402 .multicommand = default_spi_send_multicommand,
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000403 .read = default_spi_read,
stefanct69965b62011-09-15 23:38:14 +0000404 .write_256 = default_spi_write_256,
Edward O'Callaghaneeaac6b2020-10-12 19:51:56 +1100405 .write_aai = default_spi_write_aai,
stefanct69965b62011-09-15 23:38:14 +0000406};
407
Anastasia Klimchuka7d0e7b2021-02-15 15:02:00 +1100408static int sp_check_opbuf_usage(int bytes_to_be_added)
409{
410 if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) {
411 /* If this happens in the middle of a page load the page load will probably fail. */
412 msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n");
413 if (sp_execute_opbuf() != 0)
414 return 1;
415 }
416 return 0;
417}
418
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700419static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
Anastasia Klimchuka7d0e7b2021-02-15 15:02:00 +1100420 chipaddr addr)
421{
422 msg_pspew("%s\n", __func__);
423 if (sp_max_write_n) {
424 if ((sp_prev_was_write)
425 && (addr == (sp_write_n_addr + sp_write_n_bytes))) {
426 sp_write_n_buf[sp_write_n_bytes++] = val;
427 } else {
428 if ((sp_prev_was_write) && (sp_write_n_bytes))
429 sp_pass_writen();
430 sp_prev_was_write = 1;
431 sp_write_n_addr = addr;
432 sp_write_n_bytes = 1;
433 sp_write_n_buf[0] = val;
434 }
435 sp_check_opbuf_usage(7 + sp_write_n_bytes);
436 if (sp_write_n_bytes >= sp_max_write_n)
437 sp_pass_writen();
438 } else {
439 /* We will have to do single writeb ops. */
440 unsigned char writeb_parm[4];
441 sp_check_opbuf_usage(6);
442 writeb_parm[0] = (addr >> 0) & 0xFF;
443 writeb_parm[1] = (addr >> 8) & 0xFF;
444 writeb_parm[2] = (addr >> 16) & 0xFF;
445 writeb_parm[3] = val;
446 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error
447 sp_opbuf_usage += 5;
448 }
449}
450
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700451static uint8_t serprog_chip_readb(const struct flashctx *flash,
Anastasia Klimchuka7d0e7b2021-02-15 15:02:00 +1100452 const chipaddr addr)
453{
454 unsigned char c;
455 unsigned char buf[3];
456 /* Will stream the read operation - eg. add it to the stream buffer, *
457 * then flush the buffer, then read the read answer. */
458 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
459 sp_execute_opbuf_noflush();
460 buf[0] = ((addr >> 0) & 0xFF);
461 buf[1] = ((addr >> 8) & 0xFF);
462 buf[2] = ((addr >> 16) & 0xFF);
463 sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error
464 sp_flush_stream(); // FIXME: return error
465 if (serialport_read(&c, 1) != 0)
466 msg_perr(MSGHEADER "readb byteread"); // FIXME: return error
467 msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c);
468 return c;
469}
470
471/* Local version that really does the job, doesn't care of max_read_n. */
472static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len)
473{
474 unsigned char sbuf[6];
475 msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len);
476 /* Stream the read-n -- as above. */
477 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
478 sp_execute_opbuf_noflush();
479 sbuf[0] = ((addr >> 0) & 0xFF);
480 sbuf[1] = ((addr >> 8) & 0xFF);
481 sbuf[2] = ((addr >> 16) & 0xFF);
482 sbuf[3] = ((len >> 0) & 0xFF);
483 sbuf[4] = ((len >> 8) & 0xFF);
484 sbuf[5] = ((len >> 16) & 0xFF);
485 sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf);
486 if (sp_flush_stream() != 0)
487 return 1;
488 if (serialport_read(buf, len) != 0) {
489 msg_perr(MSGHEADER "Error: cannot read read-n data");
490 return 1;
491 }
492 return 0;
493}
494
495/* The externally called version that makes sure that max_read_n is obeyed. */
496static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf,
497 const chipaddr addr, size_t len)
498{
499 size_t lenm = len;
500 chipaddr addrm = addr;
501 while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) {
502 sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error
503 addrm += sp_max_read_n;
504 lenm -= sp_max_read_n;
505 }
506 if (lenm)
507 sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error
508}
509
Patrick Georgi0a9533a2017-02-03 19:28:38 +0100510static const struct par_master par_master_serprog = {
hailfinger76bb7e92011-11-09 23:40:00 +0000511 .chip_readb = serprog_chip_readb,
512 .chip_readw = fallback_chip_readw,
513 .chip_readl = fallback_chip_readl,
514 .chip_readn = serprog_chip_readn,
515 .chip_writeb = serprog_chip_writeb,
516 .chip_writew = fallback_chip_writew,
517 .chip_writel = fallback_chip_writel,
518 .chip_writen = fallback_chip_writen,
519};
520
Anastasia Klimchuka7d0e7b2021-02-15 15:02:00 +1100521static int serprog_shutdown(void *data)
522{
523 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
524 if (sp_execute_opbuf() != 0)
525 msg_pwarn("Could not flush command buffer.\n");
526 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
527 uint8_t dis = 0;
528 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0)
529 msg_pdbg(MSGHEADER "Output drivers disabled\n");
530 else
531 msg_pwarn(MSGHEADER "%s: Warning: could not disable output buffers\n", __func__);
532 }
533 /* FIXME: fix sockets on windows(?), especially closing */
534 serialport_shutdown(&sp_fd);
535 if (sp_max_write_n)
536 free(sp_write_n_buf);
537 return 0;
538}
539
hailfinger76bb7e92011-11-09 23:40:00 +0000540static enum chipbustype serprog_buses_supported = BUS_NONE;
541
David Hendricksac1d25c2016-08-09 17:00:58 -0700542int serprog_init(void)
hailfingerbacbc8b2009-07-21 13:02:59 +0000543{
544 uint16_t iface;
hailfingerbacbc8b2009-07-21 13:02:59 +0000545 unsigned char pgmname[17];
546 unsigned char rbuf[3];
547 unsigned char c;
hailfinger1ef766d2010-07-06 09:55:48 +0000548 char *device;
hailfinger1ef766d2010-07-06 09:55:48 +0000549 int have_device = 0;
hailfingerbacbc8b2009-07-21 13:02:59 +0000550
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100551 /* the parameter is either of format "dev=/dev/device[:baud]" or "ip=ip:port" */
hailfingerddeb4ac2010-07-08 10:13:37 +0000552 device = extract_programmer_param("dev");
hailfinger1ef766d2010-07-06 09:55:48 +0000553 if (device && strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100554 char *baud_str = strstr(device, ":");
555 if (baud_str != NULL) {
hailfinger1ef766d2010-07-06 09:55:48 +0000556 /* Split device from baudrate. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100557 *baud_str = '\0';
558 baud_str++;
hailfinger1ef766d2010-07-06 09:55:48 +0000559 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100560 int baud;
561 /* Convert baud string to value.
562 * baud_str is either NULL (if strstr can't find the colon), points to the \0 after the colon
563 * if no characters where given after the colon, or a string to convert... */
564 if (baud_str == NULL || *baud_str == '\0') {
565 baud = -1;
566 msg_pdbg("No baudrate specified, using the hardware's defaults.\n");
567 } else
568 baud = atoi(baud_str); // FIXME: replace atoi with strtoul
569 if (strlen(device) > 0) {
570 sp_fd = sp_openserport(device, baud);
571 if (sp_fd == SER_INV_FD) {
572 free(device);
573 return 1;
574 }
hailfinger1ef766d2010-07-06 09:55:48 +0000575 have_device++;
576 }
577 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100578
579#if !IS_WINDOWS
hailfinger1ef766d2010-07-06 09:55:48 +0000580 if (device && !strlen(device)) {
581 msg_perr("Error: No device specified.\n"
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100582 "Use flashrom -p serprog:dev=/dev/device[:baud]\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000583 free(device);
584 return 1;
585 }
586 free(device);
hailfingerbacbc8b2009-07-21 13:02:59 +0000587
hailfingerddeb4ac2010-07-08 10:13:37 +0000588 device = extract_programmer_param("ip");
hailfinger1ef766d2010-07-06 09:55:48 +0000589 if (have_device && device) {
590 msg_perr("Error: Both host and device specified.\n"
591 "Please use either dev= or ip= but not both.\n");
592 free(device);
593 return 1;
594 }
595 if (device && strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100596 char *port = strstr(device, ":");
597 if (port != NULL) {
hailfinger1ef766d2010-07-06 09:55:48 +0000598 /* Split host from port. */
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100599 *port = '\0';
600 port++;
hailfinger1ef766d2010-07-06 09:55:48 +0000601 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100602 if (!port || !strlen(port)) {
hailfinger1ef766d2010-07-06 09:55:48 +0000603 msg_perr("Error: No port specified.\n"
604 "Use flashrom -p serprog:ip=ipaddr:port\n");
605 free(device);
stefanct69965b62011-09-15 23:38:14 +0000606 return 1;
hailfinger1ef766d2010-07-06 09:55:48 +0000607 }
608 if (strlen(device)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100609 sp_fd = sp_opensocket(device, atoi(port)); // FIXME: replace atoi with strtoul
610 if (sp_fd < 0) {
611 free(device);
612 return 1;
613 }
hailfinger1ef766d2010-07-06 09:55:48 +0000614 have_device++;
615 }
616 }
617 if (device && !strlen(device)) {
618 msg_perr("Error: No host specified.\n"
619 "Use flashrom -p serprog:ip=ipaddr:port\n");
620 free(device);
621 return 1;
622 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100623#endif
hailfinger1ef766d2010-07-06 09:55:48 +0000624 free(device);
625
626 if (!have_device) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100627#if IS_WINDOWS
628 msg_perr("Error: No device specified.\n"
629 "Use flashrom -p serprog:dev=comN[:baud]\n");
630#else
hailfinger1ef766d2010-07-06 09:55:48 +0000631 msg_perr("Error: Neither host nor device specified.\n"
632 "Use flashrom -p serprog:dev=/dev/device:baud or "
633 "flashrom -p serprog:ip=ipaddr:port\n");
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100634#endif
hailfinger1ef766d2010-07-06 09:55:48 +0000635 return 1;
636 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000637
dhendrix0ffc2eb2011-06-14 01:35:36 +0000638 if (register_shutdown(serprog_shutdown, NULL))
639 return 1;
640
snelson0afd28b2010-01-10 01:06:23 +0000641 msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000642
643 sp_check_avail_automatic = 0;
644
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100645 if (sp_synchronize())
646 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000647
snelson0afd28b2010-01-10 01:06:23 +0000648 msg_pdbg(MSGHEADER "Synchronized\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000649
650 if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
stefanctd9ac2212011-10-22 21:45:27 +0000651 msg_perr("Error: NAK to query interface version\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000652 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000653 }
654
655 if (iface != 1) {
stefanctd9ac2212011-10-22 21:45:27 +0000656 msg_perr("Error: Unknown interface version: %d\n", iface);
hailfinger76bb7e92011-11-09 23:40:00 +0000657 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000658 }
659
snelson0afd28b2010-01-10 01:06:23 +0000660 msg_pdbg(MSGHEADER "Interface version ok.\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000661
662 if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
snelson0afd28b2010-01-10 01:06:23 +0000663 msg_perr("Error: query command map not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000664 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000665 }
666
667 sp_check_avail_automatic = 1;
668
hailfinger76bb7e92011-11-09 23:40:00 +0000669 /* FIXME: This assumes that serprog device bustypes are always
670 * identical with flashrom bustype enums and that they all fit
671 * in a single byte.
672 */
stefanct69965b62011-09-15 23:38:14 +0000673 if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100674 msg_pwarn("Warning: NAK to query supported buses\n");
stefanct69965b62011-09-15 23:38:14 +0000675 c = BUS_NONSPI; /* A reasonable default for now. */
hailfingerbacbc8b2009-07-21 13:02:59 +0000676 }
hailfinger76bb7e92011-11-09 23:40:00 +0000677 serprog_buses_supported = c;
678
stefanctd9ac2212011-10-22 21:45:27 +0000679 msg_pdbg(MSGHEADER "Bus support: parallel=%s, LPC=%s, FWH=%s, SPI=%s\n",
680 (c & BUS_PARALLEL) ? "on" : "off",
681 (c & BUS_LPC) ? "on" : "off",
682 (c & BUS_FWH) ? "on" : "off",
683 (c & BUS_SPI) ? "on" : "off");
stefanct69965b62011-09-15 23:38:14 +0000684 /* Check for the minimum operational set of commands. */
hailfinger76bb7e92011-11-09 23:40:00 +0000685 if (serprog_buses_supported & BUS_SPI) {
stefanct69965b62011-09-15 23:38:14 +0000686 uint8_t bt = BUS_SPI;
Edward O'Callaghan62018182020-10-03 00:16:48 +1000687 char *spispeed;
stefanct69965b62011-09-15 23:38:14 +0000688 if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
689 msg_perr("Error: SPI operation not supported while the "
690 "bustype is SPI\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000691 return 1;
stefanct69965b62011-09-15 23:38:14 +0000692 }
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100693 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
694 return 1;
stefanct69965b62011-09-15 23:38:14 +0000695 /* Success of any of these commands is optional. We don't need
696 the programmer to tell us its limits, but if it doesn't, we
697 will assume stuff, so it's in the programmers best interest
698 to tell us. */
stefanct69965b62011-09-15 23:38:14 +0000699 if (!sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
700 uint32_t v;
701 v = ((unsigned int)(rbuf[0]) << 0);
702 v |= ((unsigned int)(rbuf[1]) << 8);
703 v |= ((unsigned int)(rbuf[2]) << 16);
704 if (v == 0)
705 v = (1 << 24) - 1; /* SPI-op maximum. */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100706 spi_master_serprog.max_data_write = v;
stefanct69965b62011-09-15 23:38:14 +0000707 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n", v);
708 }
709 if (!sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf)) {
710 uint32_t v;
711 v = ((unsigned int)(rbuf[0]) << 0);
712 v |= ((unsigned int)(rbuf[1]) << 8);
713 v |= ((unsigned int)(rbuf[2]) << 16);
714 if (v == 0)
715 v = (1 << 24) - 1; /* SPI-op maximum. */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100716 spi_master_serprog.max_data_read = v;
stefanct69965b62011-09-15 23:38:14 +0000717 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n", v);
718 }
Edward O'Callaghan62018182020-10-03 00:16:48 +1000719 spispeed = extract_programmer_param("spispeed");
720 if (spispeed && strlen(spispeed)) {
721 uint32_t f_spi_req, f_spi;
722 uint8_t buf[4];
723 char *f_spi_suffix;
724
725 errno = 0;
726 f_spi_req = strtol(spispeed, &f_spi_suffix, 0);
727 if (errno != 0 || spispeed == f_spi_suffix) {
728 msg_perr("Error: Could not convert 'spispeed'.\n");
729 free(spispeed);
730 return 1;
731 }
732 if (strlen(f_spi_suffix) == 1) {
733 if (!strcasecmp(f_spi_suffix, "M"))
734 f_spi_req *= 1000000;
735 else if (!strcasecmp(f_spi_suffix, "k"))
736 f_spi_req *= 1000;
737 else {
738 msg_perr("Error: Garbage following 'spispeed' value.\n");
739 free(spispeed);
740 return 1;
741 }
742 } else if (strlen(f_spi_suffix) > 1) {
743 msg_perr("Error: Garbage following 'spispeed' value.\n");
744 free(spispeed);
745 return 1;
746 }
747
748 buf[0] = (f_spi_req >> (0 * 8)) & 0xFF;
749 buf[1] = (f_spi_req >> (1 * 8)) & 0xFF;
750 buf[2] = (f_spi_req >> (2 * 8)) & 0xFF;
751 buf[3] = (f_spi_req >> (3 * 8)) & 0xFF;
752
753 if (sp_check_commandavail(S_CMD_S_SPI_FREQ) == 0)
754 msg_pwarn(MSGHEADER "Warning: Setting the SPI clock rate is not supported!\n");
755 else if (sp_docommand(S_CMD_S_SPI_FREQ, 4, buf, 4, buf) == 0) {
756 f_spi = buf[0];
757 f_spi |= buf[1] << (1 * 8);
758 f_spi |= buf[2] << (2 * 8);
759 f_spi |= buf[3] << (3 * 8);
760 msg_pdbg(MSGHEADER "Requested to set SPI clock frequency to %u Hz. "
761 "It was actually set to %u Hz\n", f_spi_req, f_spi);
762 } else
763 msg_pwarn(MSGHEADER "Setting SPI clock rate to %u Hz failed!\n", f_spi_req);
764 }
765 free(spispeed);
hailfinger76bb7e92011-11-09 23:40:00 +0000766 bt = serprog_buses_supported;
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100767 if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
768 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000769 }
stefanct69965b62011-09-15 23:38:14 +0000770
hailfinger76bb7e92011-11-09 23:40:00 +0000771 if (serprog_buses_supported & BUS_NONSPI) {
stefanct69965b62011-09-15 23:38:14 +0000772 if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
773 msg_perr("Error: Initialize operation buffer "
774 "not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000775 return 1;
stefanct69965b62011-09-15 23:38:14 +0000776 }
777
778 if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
779 msg_perr("Error: Write to opbuf: "
780 "delay not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000781 return 1;
stefanct69965b62011-09-15 23:38:14 +0000782 }
783
784 /* S_CMD_O_EXEC availability checked later. */
785
786 if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
787 msg_perr("Error: Single byte read not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000788 return 1;
stefanct69965b62011-09-15 23:38:14 +0000789 }
790 /* This could be translated to single byte reads (if missing),
791 * but now we don't support that. */
792 if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
793 msg_perr("Error: Read n bytes not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000794 return 1;
stefanct69965b62011-09-15 23:38:14 +0000795 }
796 if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
797 msg_perr("Error: Write to opbuf: "
798 "write byte not supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000799 return 1;
stefanct69965b62011-09-15 23:38:14 +0000800 }
801
802 if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
803 msg_pdbg(MSGHEADER "Write-n not supported");
804 sp_max_write_n = 0;
805 } else {
806 sp_max_write_n = ((unsigned int)(rbuf[0]) << 0);
807 sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8);
808 sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16);
809 if (!sp_max_write_n) {
810 sp_max_write_n = (1 << 24);
811 }
812 msg_pdbg(MSGHEADER "Maximum write-n length is %d\n",
813 sp_max_write_n);
814 sp_write_n_buf = malloc(sp_max_write_n);
815 if (!sp_write_n_buf) {
816 msg_perr("Error: cannot allocate memory for "
817 "Write-n buffer\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000818 return 1;
stefanct69965b62011-09-15 23:38:14 +0000819 }
820 sp_write_n_bytes = 0;
821 }
822
823 if (sp_check_commandavail(S_CMD_Q_RDNMAXLEN) &&
824 (sp_docommand(S_CMD_Q_RDNMAXLEN, 0, NULL, 3, rbuf) == 0)) {
825 sp_max_read_n = ((unsigned int)(rbuf[0]) << 0);
826 sp_max_read_n |= ((unsigned int)(rbuf[1]) << 8);
827 sp_max_read_n |= ((unsigned int)(rbuf[2]) << 16);
828 msg_pdbg(MSGHEADER "Maximum read-n length is %d\n",
829 sp_max_read_n ? sp_max_read_n : (1 << 24));
830 } else {
831 msg_pdbg(MSGHEADER "Maximum read-n length "
832 "not reported\n");
833 sp_max_read_n = 0;
834 }
835
hailfingerbacbc8b2009-07-21 13:02:59 +0000836 }
837
838 if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100839 msg_pwarn("Warning: NAK to query programmer name\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000840 strcpy((char *)pgmname, "(unknown)");
841 }
842 pgmname[16] = 0;
stefanctd9ac2212011-10-22 21:45:27 +0000843 msg_pinfo(MSGHEADER "Programmer name is \"%s\"\n", pgmname);
hailfingerbacbc8b2009-07-21 13:02:59 +0000844
845 if (sp_docommand(S_CMD_Q_SERBUF, 0, NULL, 2, &sp_device_serbuf_size)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100846 msg_pwarn("Warning: NAK to query serial buffer size\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000847 }
stefanctd9ac2212011-10-22 21:45:27 +0000848 msg_pdbg(MSGHEADER "Serial buffer size is %d\n",
hailfingerbacbc8b2009-07-21 13:02:59 +0000849 sp_device_serbuf_size);
850
stefanct69965b62011-09-15 23:38:14 +0000851 if (sp_check_commandavail(S_CMD_O_INIT)) {
852 /* This would be inconsistent. */
853 if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
854 msg_perr("Error: Execute operation buffer not "
855 "supported\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000856 return 1;
hailfingerbacbc8b2009-07-21 13:02:59 +0000857 }
stefanct69965b62011-09-15 23:38:14 +0000858
859 if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
860 msg_perr("Error: NAK to initialize operation buffer\n");
hailfinger76bb7e92011-11-09 23:40:00 +0000861 return 1;
stefanct69965b62011-09-15 23:38:14 +0000862 }
863
864 if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2,
865 &sp_device_opbuf_size)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100866 msg_pwarn("Warning: NAK to query operation buffer size\n");
stefanct69965b62011-09-15 23:38:14 +0000867 }
stefanctd9ac2212011-10-22 21:45:27 +0000868 msg_pdbg(MSGHEADER "operation buffer size is %d\n",
stefanct69965b62011-09-15 23:38:14 +0000869 sp_device_opbuf_size);
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100870 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000871
Edward O'Callaghan62018182020-10-03 00:16:48 +1000872 if (sp_check_commandavail(S_CMD_S_PIN_STATE)) {
873 uint8_t en = 1;
874 if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) {
875 msg_perr("Error: could not enable output buffers\n");
876 return 1;
877 } else
878 msg_pdbg(MSGHEADER "Output drivers enabled\n");
879 } else
880 msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n");
hailfingerbacbc8b2009-07-21 13:02:59 +0000881 sp_prev_was_write = 0;
882 sp_streamed_transmit_ops = 0;
883 sp_streamed_transmit_bytes = 0;
884 sp_opbuf_usage = 0;
hailfinger76bb7e92011-11-09 23:40:00 +0000885 if (serprog_buses_supported & BUS_SPI)
Nico Huberf1eeda62021-05-11 17:38:14 +0200886 register_spi_master(&spi_master_serprog, NULL);
hailfinger76bb7e92011-11-09 23:40:00 +0000887 if (serprog_buses_supported & BUS_NONSPI)
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100888 register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI);
hailfingerbacbc8b2009-07-21 13:02:59 +0000889 return 0;
890}
891
Edward O'Callaghan8ebbd502019-09-03 15:11:02 +1000892void serprog_delay(unsigned int usecs)
hailfingerbacbc8b2009-07-21 13:02:59 +0000893{
894 unsigned char buf[4];
stefanctd9ac2212011-10-22 21:45:27 +0000895 msg_pspew("%s usecs=%d\n", __func__, usecs);
stefanct69965b62011-09-15 23:38:14 +0000896 if (!sp_check_commandavail(S_CMD_O_DELAY)) {
Kangheui Wonb1e8c3b2019-10-20 16:07:32 +1100897 msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n");
stefanctd9ac2212011-10-22 21:45:27 +0000898 internal_delay(usecs);
stefanct69965b62011-09-15 23:38:14 +0000899 return;
900 }
hailfingerbacbc8b2009-07-21 13:02:59 +0000901 if ((sp_max_write_n) && (sp_write_n_bytes))
902 sp_pass_writen();
903 sp_check_opbuf_usage(5);
stefanctd9ac2212011-10-22 21:45:27 +0000904 buf[0] = ((usecs >> 0) & 0xFF);
905 buf[1] = ((usecs >> 8) & 0xFF);
906 buf[2] = ((usecs >> 16) & 0xFF);
907 buf[3] = ((usecs >> 24) & 0xFF);
hailfingerbacbc8b2009-07-21 13:02:59 +0000908 sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf);
909 sp_opbuf_usage += 5;
910 sp_prev_was_write = 0;
911}
stefanct69965b62011-09-15 23:38:14 +0000912
Edward O'Callaghan62018182020-10-03 00:16:48 +1000913void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len)
914{
915 /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits
916 * correctly (usually setting them to one either in software (for FWH/LPC) or relying on the fact that
917 * the hardware observes a subset of the address bits only). Combined with the standard mapping of
918 * flashrom this creates a 16 MB-wide window just below the 4 GB boundary where serprog can operate (as
919 * needed for non-SPI chips). Below we make sure that the requested range is within this window. */
920 if ((phys_addr & 0xFF000000) == 0xFF000000) {
921 return (void*)phys_addr;
922 }
923 msg_pwarn(MSGHEADER "requested mapping %s is incompatible: 0x%zx bytes at 0x%0*" PRIxPTR ".\n",
924 descr, len, PRIxPTR_WIDTH, phys_addr);
925 return NULL;
926}