1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <stdint.h>
22 #include <fcntl.h>
23 #include <malloc.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <stdbool.h>
27 #include <time.h>
28 #include <errno.h>
29
30 #include "stm32_bl.h"
31 #include "stm32f4_crc.h"
32 #include "i2c.h"
33 #include "spi.h"
34 #include "uart.h"
35
36 enum USE_INTERFACE {
37 USE_SPI,
38 USE_I2C,
39 USE_UART,
40 };
41
pad(ssize_t length)42 static inline size_t pad(ssize_t length)
43 {
44 return (length + 3) & ~3;
45 }
46
tot_len(ssize_t length)47 static inline size_t tot_len(ssize_t length)
48 {
49 // [TYPE:1] [LENGTH:3] [DATA] [PAD:0-3] [CRC:4]
50 return sizeof(uint32_t) + pad(length) + sizeof(uint32_t);
51 }
52
write_byte(int fd,uint8_t byte)53 ssize_t write_byte(int fd, uint8_t byte)
54 {
55 ssize_t ret;
56
57 do {
58 ret = write(fd, &byte, 1);
59 } while (ret == 0 || (ret == -1 && errno == EINTR));
60
61 return ret;
62 }
63
main(int argc,char * argv[])64 int main(int argc, char *argv[])
65 {
66 uint8_t addr = 0x39;
67 char device[] = "/dev/spidev7.0";
68 int gpio_nreset = 59;
69 char gpio_dev[30];
70 struct stat buf;
71 uint8_t *buffer;
72 uint32_t crc;
73 i2c_handle_t i2c_handle;
74 spi_handle_t spi_handle;
75 uart_handle_t uart_handle;
76 handle_t *handle;
77 char options[] = "d:e:w:a:t:r:l:g:csiu";
78 char *dev = device;
79 int opt;
80 uint32_t address = 0x08000000;
81 char *write_filename = NULL;
82 char *read_filename = NULL;
83 int sector = -1;
84 int do_crc = 0;
85 uint8_t type = 0x11;
86 ssize_t length = 0;
87 uint8_t ret;
88 int use_iface = USE_SPI;
89 int fd;
90 int gpio;
91 FILE *file;
92 int val;
93 struct timespec ts;
94
95 if (argc == 1) {
96 printf("Usage: %s\n", argv[0]);
97 printf(" -s (use spi. default)\n");
98 printf(" -i (use i2c)\n");
99 printf(" -u (use uart)\n");
100 printf(" -g <gpio> (reset gpio. default: %d)\n", gpio_nreset);
101 printf(" -d <device> (device. default: %s)\n", device);
102 printf(" -e <sector> (sector to erase)\n");
103 printf(" -w <filename> (filename to write to flash)\n");
104 printf(" -r <filename> (filename to read from flash)\n");
105 printf(" -l <length> (length to read/write)\n");
106 printf(" -a <address> (address to write filename to. default: 0x%08x)\n",
107 address);
108 printf(" -c (add type, length, file contents, and CRC)\n");
109 printf(" -t <type> (type value for -c option. default: %d)\n", type);
110 return 0;
111 }
112
113 while ((opt = getopt(argc, argv, options)) != -1) {
114 switch (opt) {
115 case 'd':
116 dev = optarg;
117 break;
118 case 'e':
119 sector = strtol(optarg, NULL, 0);
120 break;
121 case 'w':
122 write_filename = optarg;
123 break;
124 case 'r':
125 read_filename = optarg;
126 break;
127 case 'l':
128 length = strtol(optarg, NULL, 0);
129 break;
130 case 'a':
131 address = strtol(optarg, NULL, 0);
132 break;
133 case 'c':
134 do_crc = 1;
135 break;
136 case 't':
137 type = strtol(optarg, NULL, 0);
138 break;
139 case 's':
140 use_iface = USE_SPI;
141 break;
142 case 'i':
143 use_iface = USE_I2C;
144 break;
145 case 'u':
146 use_iface = USE_UART;
147 break;
148 case 'g':
149 gpio_nreset = strtol(optarg, NULL, 0);
150 break;
151 }
152 }
153
154 if (use_iface == USE_UART)
155 fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
156 else
157 fd = open(dev, O_RDWR);
158 if (fd < 0) {
159 perror("Error opening dev");
160 return -1;
161 }
162
163 snprintf(gpio_dev, sizeof(gpio_dev), "/sys/class/gpio/gpio%d/value", gpio_nreset);
164 gpio = open(gpio_dev, O_WRONLY);
165 if (gpio < 0) {
166 perror("Error opening nreset gpio");
167 } else {
168 if (write_byte(gpio, '1') < 0)
169 perror("Failed to set gpio to 1");
170 close(gpio);
171 ts.tv_sec = 0;
172 ts.tv_nsec = 200000000;
173 nanosleep(&ts, NULL);
174 }
175
176 if (use_iface == USE_SPI) {
177 handle = &spi_handle.handle;
178 spi_handle.fd = fd;
179
180 val = spi_init(handle);
181 } else if (use_iface == USE_UART) {
182 handle = &uart_handle.handle;
183 uart_handle.fd = fd;
184
185 val = uart_init(handle);
186 } else {
187 handle = &i2c_handle.handle;
188 i2c_handle.fd = fd;
189 i2c_handle.addr = addr;
190
191 val = i2c_init(handle);
192 }
193
194 if (val < 0) {
195 printf("Init failed\n");
196 return val;
197 }
198
199 if (sector >= 0) {
200 printf("Erasing sector %d\n", sector);
201 ret = erase_sector(handle, sector);
202 if (ret == CMD_ACK)
203 printf("Erase succeeded\n");
204 else
205 printf("Erase failed\n");
206 }
207
208 if (write_filename != NULL) {
209 file = fopen(write_filename, "r");
210 if (!file) {
211 perror("Error opening input file");
212 return -1;
213 }
214
215 if (fstat(fileno(file), &buf) < 0) {
216 perror("error stating file");
217 return -1;
218 }
219
220 /*
221 * For CRC: (when writing to eedata/shared)
222 * [TYPE:1] [LENGTH:3] [DATA] [PAD:0-3] [CRC:4]
223 * Otherwise:
224 * [DATA]
225 */
226 buffer = calloc(tot_len(buf.st_size), 1);
227 if (length == 0 || length > buf.st_size)
228 length = buf.st_size;
229
230 if (fread(&buffer[sizeof(uint32_t)], 1, length, file) < (size_t)length) {
231 perror("Error reading input file");
232 free(buffer);
233 fclose(file);
234 return -1;
235 }
236
237 printf("Writing %zd bytes from %s to 0x%08x\n", length,
238 write_filename, address);
239
240 if (do_crc) {
241 /* Populate TYPE, LENGTH, and CRC */
242 buffer[0] = type;
243 buffer[1] = (length >> 16) & 0xFF;
244 buffer[2] = (length >> 8) & 0xFF;
245 buffer[3] = (length ) & 0xFF;
246 crc = ~stm32f4_crc32(buffer, sizeof(uint32_t) + length);
247
248 memcpy(&buffer[sizeof(uint32_t) + pad(length)],
249 &crc, sizeof(uint32_t));
250
251 ret = write_memory(handle, address,
252 tot_len(length), buffer);
253 } else {
254 /* Skip over space reserved for TYPE and LENGTH */
255 ret = write_memory(handle, address,
256 length, &buffer[sizeof(uint32_t)]);
257 }
258
259 if (ret == CMD_ACK)
260 printf("Write succeeded\n");
261 else
262 printf("Write failed\n");
263
264 free(buffer);
265 fclose(file);
266 }
267
268 if (read_filename != NULL) {
269 file = fopen(read_filename, "w");
270 if (!file) {
271 perror("Error opening output file");
272 return -1;
273 }
274
275 if (length > 0) {
276 /* If passed in a length, just read that many bytes */
277 buffer = calloc(length, 1);
278
279 ret = read_memory(handle, address, length, buffer);
280 if (ret == CMD_ACK) {
281 if (fwrite(buffer, 1, length, file) < (size_t)length)
282 perror("Failed to write all read bytes to file");
283
284 printf("Read %zd bytes from %s @ 0x%08x\n",
285 length, read_filename, address);
286 } else {
287 printf("Read failed\n");
288 }
289 free(buffer);
290 } else if (do_crc) {
291 /* otherwise if crc specified, read type, length, data, and crc */
292 uint8_t tmp_buf[sizeof(uint32_t)];
293 ret = read_memory(handle, address, sizeof(uint32_t), tmp_buf);
294 if (ret == CMD_ACK) {
295 type = tmp_buf[0];
296 length = ((tmp_buf[1] << 16) & 0x00FF0000) |
297 ((tmp_buf[2] << 8) & 0x0000FF00) |
298 ((tmp_buf[3] ) & 0x000000FF);
299
300 if (type != 0xFF) {
301 buffer = calloc(tot_len(length), 1);
302 ret = read_memory(handle, address,
303 tot_len(length), buffer);
304 if (ret == CMD_ACK) {
305 crc = stm32f4_crc32(buffer, tot_len(length));
306 if (fwrite(buffer, 1, tot_len(length), file) < tot_len(length))
307 perror("Failed to write all read bytes to file");
308
309 printf("Read %zd bytes from %s @ 0x%08x (type %02x, crc %s)\n",
310 length, read_filename, address, type,
311 crc == STM32F4_CRC_RESIDUE ? "good" : "bad");
312 } else {
313 printf("Read of payload failed\n");
314 }
315 free(buffer);
316 } else {
317 printf("Read invalid type: 0xFF\n");
318 }
319 } else {
320 printf("Read of header failed\n");
321 }
322 } else {
323 printf("No length or crc specified for read\n");
324 }
325 fclose(file);
326 }
327
328 gpio = open(gpio_dev, O_WRONLY);
329 if (gpio < 0) {
330 perror("Error opening nreset gpio");
331 } else {
332 if (write_byte(gpio, '0') < 0)
333 perror("Failed to set gpio to 0");
334 close(gpio);
335 }
336
337 close(fd);
338
339 return 0;
340 }
341