rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <string.h>
|
nuclear@0
|
4 #include <stdint.h>
|
nuclear@0
|
5 #include <errno.h>
|
nuclear@0
|
6 #include <assert.h>
|
nuclear@0
|
7 #include <unistd.h>
|
nuclear@0
|
8 #include <fcntl.h>
|
nuclear@0
|
9 #include <termios.h>
|
nuclear@0
|
10
|
nuclear@0
|
11 enum {
|
nuclear@0
|
12 OP_NONE,
|
nuclear@0
|
13 OP_WRITE,
|
nuclear@0
|
14 OP_READ,
|
nuclear@0
|
15 OP_RESET
|
nuclear@0
|
16 };
|
nuclear@0
|
17
|
nuclear@0
|
18 int op_write(FILE *dev, FILE *fp);
|
nuclear@0
|
19 int op_read(FILE *dev, FILE *fp);
|
nuclear@0
|
20 int op_reset(FILE *dev);
|
nuclear@0
|
21 int parse_args(int argc, char **argv);
|
nuclear@0
|
22
|
nuclear@0
|
23 int op, verify = 0;
|
nuclear@0
|
24 const char *devname = "/dev/ttyUSB0";
|
nuclear@0
|
25 char *fname = 0;
|
nuclear@0
|
26 uint32_t start_addr;
|
nuclear@0
|
27 int read_size = 128 * 1024;
|
nuclear@0
|
28
|
nuclear@0
|
29 int main(int argc, char **argv)
|
nuclear@0
|
30 {
|
nuclear@0
|
31 FILE *fp, *devfp;
|
nuclear@0
|
32 int dev;
|
nuclear@0
|
33 struct termios term;
|
nuclear@0
|
34
|
nuclear@0
|
35 if(parse_args(argc, argv) == -1) {
|
nuclear@0
|
36 return 1;
|
nuclear@0
|
37 }
|
nuclear@0
|
38
|
nuclear@0
|
39 if((dev = open(devname, O_RDWR)) == -1) {
|
nuclear@0
|
40 fprintf(stderr, "failed to open device %s: %s\n", devname, strerror(errno));
|
nuclear@0
|
41 return 1;
|
nuclear@0
|
42 }
|
nuclear@0
|
43 if(tcgetattr(dev, &term) == -1) {
|
nuclear@0
|
44 fprintf(stderr, "failed to get terminal attributes for %s: %s\n", devname, strerror(errno));
|
nuclear@0
|
45 return 1;
|
nuclear@0
|
46 }
|
nuclear@0
|
47 term.c_cflag = CS8 | CLOCAL;
|
nuclear@0
|
48 term.c_iflag &= ~(IXON | IXOFF);
|
nuclear@0
|
49 term.c_lflag = 0;
|
nuclear@0
|
50
|
nuclear@0
|
51 cfsetispeed(&term, B38400);
|
nuclear@0
|
52 cfsetospeed(&term, B38400);
|
nuclear@0
|
53
|
nuclear@0
|
54 if(tcsetattr(dev, TCSANOW, &term) == -1) {
|
nuclear@0
|
55 fprintf(stderr, "failed to set terminal attributes for %s: %s\n", devname, strerror(errno));
|
nuclear@0
|
56 return 1;
|
nuclear@0
|
57 }
|
nuclear@0
|
58
|
nuclear@0
|
59 if(!(devfp = fdopen(dev, "r+"))) {
|
nuclear@0
|
60 perror("failed to attach I/O stream to the device file\n");
|
nuclear@0
|
61 return 1;
|
nuclear@0
|
62 }
|
nuclear@0
|
63 setvbuf(devfp, 0, _IONBF, 0);
|
nuclear@0
|
64
|
nuclear@0
|
65 if(fname && !(fp = fopen(fname, op == OP_READ ? "w" : "r"))) {
|
nuclear@0
|
66 fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno));
|
nuclear@0
|
67 return 1;
|
nuclear@0
|
68 }
|
nuclear@0
|
69
|
nuclear@0
|
70 switch(op) {
|
nuclear@0
|
71 case OP_WRITE:
|
nuclear@0
|
72 if(op_write(devfp, fp) == -1) {
|
nuclear@0
|
73 fprintf(stderr, "write failed\n");
|
nuclear@0
|
74 return 1;
|
nuclear@0
|
75 }
|
nuclear@0
|
76 break;
|
nuclear@0
|
77
|
nuclear@0
|
78 case OP_READ:
|
nuclear@0
|
79 if(op_read(devfp, fp) == -1) {
|
nuclear@0
|
80 fprintf(stderr, "read failed\n");
|
nuclear@0
|
81 return 1;
|
nuclear@0
|
82 }
|
nuclear@0
|
83 break;
|
nuclear@0
|
84
|
nuclear@0
|
85 case OP_RESET:
|
nuclear@0
|
86 if(op_reset(devfp) == -1) {
|
nuclear@0
|
87 fprintf(stderr, "reset failed\n");
|
nuclear@0
|
88 return 1;
|
nuclear@0
|
89 }
|
nuclear@0
|
90 break;
|
nuclear@0
|
91
|
nuclear@0
|
92 default:
|
nuclear@0
|
93 break;
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 fclose(devfp);
|
nuclear@0
|
97 close(dev);
|
nuclear@0
|
98 if(fp) {
|
nuclear@0
|
99 fclose(fp);
|
nuclear@0
|
100 }
|
nuclear@0
|
101 return 0;
|
nuclear@0
|
102 }
|
nuclear@0
|
103
|
nuclear@0
|
104 #define RET_IF_FAIL(x) \
|
nuclear@0
|
105 if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') return x
|
nuclear@0
|
106
|
nuclear@0
|
107 int op_write(FILE *dev, FILE *fp)
|
nuclear@0
|
108 {
|
nuclear@0
|
109 char buf[128];
|
nuclear@0
|
110 int c;
|
nuclear@0
|
111
|
nuclear@0
|
112 fprintf(dev, "p\n");
|
nuclear@0
|
113 RET_IF_FAIL(-1);
|
nuclear@0
|
114 fprintf(dev, "a%d\n", start_addr);
|
nuclear@0
|
115 RET_IF_FAIL(-1);
|
nuclear@0
|
116
|
nuclear@0
|
117 while((c = fgetc(fp)) != -1) {
|
nuclear@0
|
118 fprintf(dev, "w%d\n", c);
|
nuclear@0
|
119 RET_IF_FAIL(-1);
|
nuclear@0
|
120 }
|
nuclear@0
|
121
|
nuclear@0
|
122 fprintf(dev, "b\n");
|
nuclear@0
|
123 RET_IF_FAIL(-1);
|
nuclear@0
|
124 return 0;
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 int op_read(FILE *dev, FILE *fp)
|
nuclear@0
|
128 {
|
nuclear@0
|
129 char buf[128];
|
nuclear@0
|
130 int i, val;
|
nuclear@0
|
131
|
nuclear@0
|
132 fprintf(dev, "p\n");
|
nuclear@0
|
133 RET_IF_FAIL(-1);
|
nuclear@0
|
134 fprintf(dev, "a%d\n", start_addr);
|
nuclear@0
|
135 RET_IF_FAIL(-1);
|
nuclear@0
|
136
|
nuclear@0
|
137 for(i=0; i<read_size; i++) {
|
nuclear@0
|
138 fprintf(dev, "r\n");
|
nuclear@0
|
139 if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') {
|
nuclear@0
|
140 fprintf(stderr, "read error after %d bytes\n", i);
|
nuclear@0
|
141 break;
|
nuclear@0
|
142 }
|
nuclear@0
|
143 val = atoi(buf + 3); /* skip 'O', 'K', ' ' */
|
nuclear@0
|
144 fputc(val, fp);
|
nuclear@0
|
145 }
|
nuclear@0
|
146
|
nuclear@0
|
147 fprintf(dev, "b\n");
|
nuclear@0
|
148 RET_IF_FAIL(-1);
|
nuclear@0
|
149 return 0;
|
nuclear@0
|
150 }
|
nuclear@0
|
151
|
nuclear@0
|
152 int op_reset(FILE *dev)
|
nuclear@0
|
153 {
|
nuclear@0
|
154 char buf[128];
|
nuclear@0
|
155 fprintf(dev, "p\n");
|
nuclear@0
|
156 RET_IF_FAIL(-1);
|
nuclear@0
|
157 fprintf(dev, "b\n");
|
nuclear@0
|
158 RET_IF_FAIL(-1);
|
nuclear@0
|
159 return 0;
|
nuclear@0
|
160 }
|
nuclear@0
|
161
|
nuclear@0
|
162 int parse_args(int argc, char **argv)
|
nuclear@0
|
163 {
|
nuclear@0
|
164 int i;
|
nuclear@0
|
165
|
nuclear@0
|
166 for(i=1; i<argc; i++) {
|
nuclear@0
|
167 if(strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-write") == 0) {
|
nuclear@0
|
168 op = OP_WRITE;
|
nuclear@0
|
169 if(!(fname = argv[++i])) {
|
nuclear@0
|
170 fprintf(stderr, "%s must be followed by a filename\n", argv[i - 1]);
|
nuclear@0
|
171 return -1;
|
nuclear@0
|
172 }
|
nuclear@0
|
173
|
nuclear@0
|
174 } else if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-read") == 0) {
|
nuclear@0
|
175 op = OP_READ;
|
nuclear@0
|
176 if(!(fname = argv[++i])) {
|
nuclear@0
|
177 fprintf(stderr, "%s must be followed by a filename\n", argv[i - 1]);
|
nuclear@0
|
178 return -1;
|
nuclear@0
|
179 }
|
nuclear@0
|
180
|
nuclear@0
|
181 } else if(strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "-addr") == 0) {
|
nuclear@0
|
182 char *endp;
|
nuclear@0
|
183 if(!argv[++i] || ((start_addr = strtol(argv[i], &endp, 0)), endp == argv[i])) {
|
nuclear@0
|
184 fprintf(stderr, "%s must be followed by an address\n", argv[i - 1]);
|
nuclear@0
|
185 return -1;
|
nuclear@0
|
186 }
|
nuclear@0
|
187
|
nuclear@0
|
188 } else if(strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "-reset") == 0) {
|
nuclear@0
|
189 op = OP_RESET;
|
nuclear@0
|
190
|
nuclear@0
|
191 } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-size") == 0) {
|
nuclear@0
|
192 char *endp;
|
nuclear@0
|
193 if(!argv[++i] || ((read_size = strtol(argv[i], &endp, 0)), endp == argv[i])) {
|
nuclear@0
|
194 fprintf(stderr, "%s must be followed by a size in bytes\n", argv[i - 1]);
|
nuclear@0
|
195 return -1;
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 } else if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-verify") == 0) {
|
nuclear@0
|
199 verify = 1;
|
nuclear@0
|
200
|
nuclear@0
|
201 } else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-device") == 0) {
|
nuclear@0
|
202 devname = argv[++i];
|
nuclear@0
|
203
|
nuclear@0
|
204 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
|
nuclear@0
|
205 printf("Usage: %s [options]\n", argv[0]);
|
nuclear@0
|
206 printf("Options:\n");
|
nuclear@0
|
207 printf(" -w|-write <filename>\n");
|
nuclear@0
|
208 printf(" -r|-read <filename>\n");
|
nuclear@0
|
209 printf(" -a|-addr <address>: start address for read/write operations\n");
|
nuclear@0
|
210 printf(" -R|-reset: reboot machine\n");
|
nuclear@0
|
211 printf(" -v|-verify: do verification after writing\n");
|
nuclear@0
|
212 printf(" -s|-size: read size in bytes\n");
|
nuclear@0
|
213 printf(" -d|-device <device file>: serial device (eg /dev/ttyUSB0)\n");
|
nuclear@0
|
214 printf(" -h|-help: print usage and exit\n");
|
nuclear@0
|
215 return 0;
|
nuclear@0
|
216
|
nuclear@0
|
217 } else {
|
nuclear@0
|
218 fprintf(stderr, "invalid argument: %s\n", argv[i]);
|
nuclear@0
|
219 return -1;
|
nuclear@0
|
220 }
|
nuclear@0
|
221 }
|
nuclear@0
|
222
|
nuclear@0
|
223 if(!op) {
|
nuclear@0
|
224 fprintf(stderr, "you must specify an operation\n");
|
nuclear@0
|
225 return -1;
|
nuclear@0
|
226 }
|
nuclear@0
|
227 return 0;
|
nuclear@0
|
228 }
|