• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             free(buffer);
211             fclose(file);
212             return -1;
213         }
214 
215         printf("Writing %zd bytes from %s to 0x%08x\n", length,
216                write_filename, address);
217 
218         if (do_crc) {
219             /* Populate TYPE, LENGTH, and CRC */
220             buffer[0] = type;
221             buffer[1] = (length >> 16) & 0xFF;
222             buffer[2] = (length >>  8) & 0xFF;
223             buffer[3] = (length      ) & 0xFF;
224             crc = ~stm32f4_crc32(buffer, sizeof(uint32_t) + length);
225 
226             memcpy(&buffer[sizeof(uint32_t) + pad(length)],
227                    &crc, sizeof(uint32_t));
228 
229             ret = write_memory(handle, address,
230                                tot_len(length), buffer);
231         } else {
232             /* Skip over space reserved for TYPE and LENGTH */
233             ret = write_memory(handle, address,
234                                length, &buffer[sizeof(uint32_t)]);
235         }
236 
237         if (ret == CMD_ACK)
238             printf("Write succeeded\n");
239         else
240             printf("Write failed\n");
241 
242         free(buffer);
243         fclose(file);
244     }
245 
246     if (read_filename != NULL) {
247         file = fopen(read_filename, "w");
248         if (!file) {
249             perror("Error opening output file");
250             return -1;
251         }
252 
253         if (length > 0) {
254             /* If passed in a length, just read that many bytes */
255             buffer = calloc(length, 1);
256 
257             ret = read_memory(handle, address, length, buffer);
258             if (ret == CMD_ACK) {
259                 if (fwrite(buffer, 1, length, file) < (size_t)length)
260                     perror("Failed to write all read bytes to file");
261 
262                 printf("Read %zd bytes from %s @ 0x%08x\n",
263                        length, read_filename, address);
264             } else {
265                 printf("Read failed\n");
266             }
267             free(buffer);
268         } else if (do_crc) {
269             /* otherwise if crc specified, read type, length, data, and crc */
270             uint8_t tmp_buf[sizeof(uint32_t)];
271             ret = read_memory(handle, address, sizeof(uint32_t), tmp_buf);
272             if (ret == CMD_ACK) {
273                 type = tmp_buf[0];
274                 length = ((tmp_buf[1] << 16) & 0x00FF0000) |
275                          ((tmp_buf[2] <<  8) & 0x0000FF00) |
276                          ((tmp_buf[3]      ) & 0x000000FF);
277 
278                 if (type != 0xFF) {
279                     buffer = calloc(tot_len(length), 1);
280                     ret = read_memory(handle, address,
281                                       tot_len(length), buffer);
282                     if (ret == CMD_ACK) {
283                         crc = stm32f4_crc32(buffer, tot_len(length));
284                         if (fwrite(buffer, 1, tot_len(length), file) < tot_len(length))
285                             perror("Failed to write all read bytes to file");
286 
287                         printf("Read %zd bytes from %s @ 0x%08x (type %02x, crc %s)\n",
288                                length, read_filename, address, type,
289                                crc == STM32F4_CRC_RESIDUE ? "good" : "bad");
290                     } else {
291                         printf("Read of payload failed\n");
292                     }
293                     free(buffer);
294                 } else {
295                     printf("Read invalid type: 0xFF\n");
296                 }
297             } else {
298                 printf("Read of header failed\n");
299             }
300         } else {
301             printf("No length or crc specified for read\n");
302         }
303         fclose(file);
304     }
305 
306     gpio = open(gpio_dev, O_WRONLY);
307     if (gpio < 0) {
308         perror("Error opening nreset gpio");
309     } else {
310         if (write_byte(gpio, '0') < 0)
311             perror("Failed to set gpio to 0");
312         close(gpio);
313     }
314 
315     close(fd);
316 
317     return 0;
318 }
319