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 42 static inline size_t pad(ssize_t length) 43 { 44 return (length + 3) & ~3; 45 } 46 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 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 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