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
pad(ssize_t length)35 static inline size_t pad(ssize_t length)
36 {
37 return (length + 3) & ~3;
38 }
39
tot_len(ssize_t length)40 static inline size_t tot_len(ssize_t length)
41 {
42 // [TYPE:1] [LENGTH:3] [DATA] [PAD:0-3] [CRC:4]
43 return sizeof(uint32_t) + pad(length) + sizeof(uint32_t);
44 }
45
write_byte(int fd,uint8_t byte)46 ssize_t write_byte(int fd, uint8_t byte)
47 {
48 ssize_t ret;
49
50 do {
51 ret = write(fd, &byte, 1);
52 } while (ret == 0 || (ret == -1 && errno == EINTR));
53
54 return ret;
55 }
56
main(int argc,char * argv[])57 int main(int argc, char *argv[])
58 {
59 uint8_t addr = 0x39;
60 char device[] = "/dev/spidev7.0";
61 int gpio_nreset = 59;
62 char gpio_dev[30];
63 struct stat buf;
64 uint8_t *buffer;
65 uint32_t crc;
66 i2c_handle_t i2c_handle;
67 spi_handle_t spi_handle;
68 handle_t *handle;
69 char options[] = "d:e:w:a:t:r:l:g:csi";
70 char *dev = device;
71 int opt;
72 uint32_t address = 0x08000000;
73 char *write_filename = NULL;
74 char *read_filename = NULL;
75 int sector = -1;
76 int do_crc = 0;
77 uint8_t type = 0x11;
78 ssize_t length = 0;
79 uint8_t ret;
80 bool use_spi = true;
81 int fd;
82 int gpio;
83 FILE *file;
84 int val;
85 struct timespec ts;
86
87 if (argc == 1) {
88 printf("Usage: %s\n", argv[0]);
89 printf(" -s (use spi. default)\n");
90 printf(" -i (use i2c)\n");
91 printf(" -g <gpio> (reset gpio. default: %d)\n", gpio_nreset);
92 printf(" -d <device> (device. default: %s)\n", device);
93 printf(" -e <sector> (sector to erase)\n");
94 printf(" -w <filename> (filename to write to flash)\n");
95 printf(" -r <filename> (filename to read from flash)\n");
96 printf(" -l <length> (length to read/write)\n");
97 printf(" -a <address> (address to write filename to. default: 0x%08x)\n",
98 address);
99 printf(" -c (add type, length, file contents, and CRC)\n");
100 printf(" -t <type> (type value for -c option. default: %d)\n", type);
101 return 0;
102 }
103
104 while ((opt = getopt(argc, argv, options)) != -1) {
105 switch (opt) {
106 case 'd':
107 dev = optarg;
108 break;
109 case 'e':
110 sector = strtol(optarg, NULL, 0);
111 break;
112 case 'w':
113 write_filename = optarg;
114 break;
115 case 'r':
116 read_filename = optarg;
117 break;
118 case 'l':
119 length = strtol(optarg, NULL, 0);
120 break;
121 case 'a':
122 address = strtol(optarg, NULL, 0);
123 break;
124 case 'c':
125 do_crc = 1;
126 break;
127 case 't':
128 type = strtol(optarg, NULL, 0);
129 break;
130 case 's':
131 use_spi = true;
132 break;
133 case 'i':
134 use_spi = false;
135 break;
136 case 'g':
137 gpio_nreset = strtol(optarg, NULL, 0);
138 break;
139 }
140 }
141
142 fd = open(dev, O_RDWR);
143 if (fd < 0) {
144 perror("Error opening dev");
145 return -1;
146 }
147
148 snprintf(gpio_dev, sizeof(gpio_dev), "/sys/class/gpio/gpio%d/value", gpio_nreset);
149 gpio = open(gpio_dev, O_WRONLY);
150 if (gpio < 0) {
151 perror("Error opening nreset gpio");
152 } else {
153 if (write_byte(gpio, '1') < 0)
154 perror("Failed to set gpio to 1");
155 close(gpio);
156 ts.tv_sec = 0;
157 ts.tv_nsec = 5000000;
158 nanosleep(&ts, NULL);
159 }
160
161 if (use_spi) {
162 handle = &spi_handle.handle;
163 spi_handle.fd = fd;
164
165 val = spi_init(handle);
166 } else {
167 handle = &i2c_handle.handle;
168 i2c_handle.fd = fd;
169 i2c_handle.addr = addr;
170
171 val = i2c_init(handle);
172 }
173
174 if (val < 0)
175 return val;
176
177 if (sector >= 0) {
178 printf("Erasing sector %d\n", sector);
179 ret = erase_sector(handle, sector);
180 if (ret == CMD_ACK)
181 printf("Erase succeeded\n");
182 else
183 printf("Erase failed\n");
184 }
185
186 if (write_filename != NULL) {
187 file = fopen(write_filename, "r");
188 if (!file) {
189 perror("Error opening input file");
190 return -1;
191 }
192
193 if (fstat(fileno(file), &buf) < 0) {
194 perror("error stating file");
195 return -1;
196 }
197
198 /*
199 * For CRC: (when writing to eedata/shared)
200 * [TYPE:1] [LENGTH:3] [DATA] [PAD:0-3] [CRC:4]
201 * Otherwise:
202 * [DATA]
203 */
204 buffer = calloc(tot_len(buf.st_size), 1);
205 if (length == 0 || length > buf.st_size)
206 length = buf.st_size;
207
208 if (fread(&buffer[sizeof(uint32_t)], 1, length, file) < (size_t)length) {
209 perror("Error reading input file");
210 return -1;
211 }
212
213 printf("Writing %zd bytes from %s to 0x%08x\n", length,
214 write_filename, address);
215
216 if (do_crc) {
217 /* Populate TYPE, LENGTH, and CRC */
218 buffer[0] = type;
219 buffer[1] = (length >> 16) & 0xFF;
220 buffer[2] = (length >> 8) & 0xFF;
221 buffer[3] = (length ) & 0xFF;
222 crc = ~stm32f4_crc32(buffer, sizeof(uint32_t) + length);
223
224 memcpy(&buffer[sizeof(uint32_t) + pad(length)],
225 &crc, sizeof(uint32_t));
226
227 ret = write_memory(handle, address,
228 tot_len(length), buffer);
229 } else {
230 /* Skip over space reserved for TYPE and LENGTH */
231 ret = write_memory(handle, address,
232 length, &buffer[sizeof(uint32_t)]);
233 }
234
235 if (ret == CMD_ACK)
236 printf("Write succeeded\n");
237 else
238 printf("Write failed\n");
239
240 free(buffer);
241 fclose(file);
242 }
243
244 if (read_filename != NULL) {
245 file = fopen(read_filename, "w");
246 if (!file) {
247 perror("Error opening output file");
248 return -1;
249 }
250
251 if (length > 0) {
252 /* If passed in a length, just read that many bytes */
253 buffer = calloc(length, 1);
254
255 ret = read_memory(handle, address, length, buffer);
256 if (ret == CMD_ACK) {
257 if (fwrite(buffer, 1, length, file) < (size_t)length)
258 perror("Failed to write all read bytes to file");
259
260 printf("Read %zd bytes from %s @ 0x%08x\n",
261 length, read_filename, address);
262 } else {
263 printf("Read failed\n");
264 }
265 free(buffer);
266 } else if (do_crc) {
267 /* otherwise if crc specified, read type, length, data, and crc */
268 uint8_t tmp_buf[sizeof(uint32_t)];
269 ret = read_memory(handle, address, sizeof(uint32_t), tmp_buf);
270 if (ret == CMD_ACK) {
271 type = tmp_buf[0];
272 length = ((tmp_buf[1] << 16) & 0x00FF0000) |
273 ((tmp_buf[2] << 8) & 0x0000FF00) |
274 ((tmp_buf[3] ) & 0x000000FF);
275
276 if (type != 0xFF) {
277 buffer = calloc(tot_len(length), 1);
278 ret = read_memory(handle, address,
279 tot_len(length), buffer);
280 if (ret == CMD_ACK) {
281 crc = stm32f4_crc32(buffer, tot_len(length));
282 if (fwrite(buffer, 1, tot_len(length), file) < tot_len(length))
283 perror("Failed to write all read bytes to file");
284
285 printf("Read %zd bytes from %s @ 0x%08x (type %02x, crc %s)\n",
286 length, read_filename, address, type,
287 crc == STM32F4_CRC_RESIDUE ? "good" : "bad");
288 } else {
289 printf("Read of payload failed\n");
290 }
291 free(buffer);
292 } else {
293 printf("Read invalid type: 0xFF\n");
294 }
295 } else {
296 printf("Read of header failed\n");
297 }
298 } else {
299 printf("No length or crc specified for read\n");
300 }
301 fclose(file);
302 }
303
304 gpio = open(gpio_dev, O_WRONLY);
305 if (gpio < 0) {
306 perror("Error opening nreset gpio");
307 } else {
308 if (write_byte(gpio, '0') < 0)
309 perror("Failed to set gpio to 0");
310 close(gpio);
311 }
312
313 close(fd);
314
315 return 0;
316 }
317