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 35 static inline size_t pad(ssize_t length) 36 { 37 return (length + 3) & ~3; 38 } 39 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 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 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