FreeCalypso > hg > freecalypso-sw
comparison loadtools/compalload.c @ 379:7b3fd0e2a352
loadtools: compalstage support implemented in fc-iram
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 09 Jun 2014 21:07:39 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
378:3164604a6c70 | 379:7b3fd0e2a352 |
---|---|
1 /* | |
2 * This module implements Compal's serial code loading protocol to load | |
3 * what we call compalstage, a piece of code that re-enables the Calypso | |
4 * boot ROM and allows us to use the same loadagent which we use on | |
5 * freedom-enabled target devices. | |
6 */ | |
7 | |
8 #include <sys/param.h> | |
9 #include <sys/file.h> | |
10 #include <sys/stat.h> | |
11 #include <sys/ioctl.h> | |
12 #include <stdio.h> | |
13 #include <stdlib.h> | |
14 #include <string.h> | |
15 #include <strings.h> | |
16 #include <termios.h> | |
17 #include <unistd.h> | |
18 | |
19 extern char default_helpers_dir[]; | |
20 extern char *target_ttydev; | |
21 extern int target_fd; | |
22 extern struct termios target_termios; | |
23 | |
24 static char compalstage_pathname[MAXPATHLEN]; | |
25 static u_char *compalstage_imgbuf; | |
26 static size_t compalstage_len, compalstage_totlen; | |
27 static int rx_state; | |
28 static u_char rx_msg[3]; | |
29 | |
30 void | |
31 set_compalstage_short(arg) | |
32 char *arg; | |
33 { | |
34 if (strcmp(arg, "none")) | |
35 sprintf(compalstage_pathname, "%s/compalstage-%s.bin", | |
36 default_helpers_dir, arg); | |
37 else | |
38 compalstage_pathname[0] = 0; | |
39 } | |
40 | |
41 void | |
42 set_compalstage_fullpath(arg) | |
43 char *arg; | |
44 { | |
45 strcpy(compalstage_pathname, arg); | |
46 } | |
47 | |
48 static void | |
49 compute_checksum() | |
50 { | |
51 size_t i, l; | |
52 u_char ck; | |
53 | |
54 ck = 0x02; | |
55 l = compalstage_len + 3; | |
56 for (i = 1; i < l; i++) | |
57 ck ^= compalstage_imgbuf[i]; | |
58 compalstage_imgbuf[l] = ck; | |
59 } | |
60 | |
61 static | |
62 handle_rx_msg() | |
63 { | |
64 static u_char download_cmd[7] = {0x1B, 0xF6, 0x02, 0x00, | |
65 0x52, 0x01, 0x53}; | |
66 | |
67 if (rx_msg[0] == 0x41 && rx_msg[1] == 0x01 && rx_msg[2] == 0x40) { | |
68 printf("Received PROMPT1, sending download command\n"); | |
69 write(target_fd, download_cmd, 7); | |
70 return(0); | |
71 } else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x02 && rx_msg[2] == 0x43){ | |
72 printf("Received PROMPT2, sending download image\n"); | |
73 write(target_fd, compalstage_imgbuf, compalstage_totlen); | |
74 return(0); | |
75 } else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x03 && rx_msg[2] == 0x42){ | |
76 printf("Received ACK; downloaded image should now be running!\n"); | |
77 return(1); | |
78 } else if (rx_msg[0] == 0x45 && rx_msg[1] == 0x53 && rx_msg[2] == 0x16){ | |
79 printf("Bootloader indicates bad checksum :-(\n"); | |
80 return(0); | |
81 } else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x03 && rx_msg[2] == 0x57){ | |
82 printf("Bootloader indicates bad magic :-(\n"); | |
83 return(0); | |
84 } else { | |
85 printf("Unknown msg from bootloader: 1B F6 02 00 %02X %02X %02X\n", | |
86 rx_msg[0], rx_msg[1], rx_msg[2]); | |
87 return(0); | |
88 } | |
89 } | |
90 | |
91 static | |
92 handle_rx_byte(rxb) | |
93 { | |
94 switch (rx_state) { | |
95 case 0: | |
96 if (rxb == 0x1B) | |
97 rx_state = 1; | |
98 return(0); | |
99 case 1: | |
100 if (rxb == 0xF6) | |
101 rx_state = 2; | |
102 else if (rxb == 0x1B) | |
103 rx_state = 1; | |
104 else | |
105 rx_state = 0; | |
106 return(0); | |
107 case 2: | |
108 if (rxb == 0x02) | |
109 rx_state = 3; | |
110 else if (rxb == 0x1B) | |
111 rx_state = 1; | |
112 else | |
113 rx_state = 0; | |
114 return(0); | |
115 case 3: | |
116 if (rxb == 0x00) | |
117 rx_state = 4; | |
118 else if (rxb == 0x1B) | |
119 rx_state = 1; | |
120 else | |
121 rx_state = 0; | |
122 return(0); | |
123 case 4: | |
124 rx_msg[0] = rxb; | |
125 rx_state = 5; | |
126 return(0); | |
127 case 5: | |
128 rx_msg[1] = rxb; | |
129 rx_state = 6; | |
130 return(0); | |
131 case 6: | |
132 rx_msg[2] = rxb; | |
133 rx_state = 0; | |
134 return handle_rx_msg(); | |
135 } | |
136 } | |
137 | |
138 static void | |
139 read_loop() | |
140 { | |
141 u_char rdbuf[16]; | |
142 int cc, i; | |
143 | |
144 for (;;) { | |
145 cc = read(target_fd, rdbuf, sizeof rdbuf); | |
146 if (cc <= 0) { | |
147 fprintf(stderr, "EOF/error on target tty\n"); | |
148 exit(1); | |
149 } | |
150 for (i = 0; i < cc; i++) | |
151 if (handle_rx_byte(rdbuf[i])) | |
152 return; | |
153 } | |
154 } | |
155 | |
156 perform_compal_stage(for_boot_rom) | |
157 { | |
158 int fd; | |
159 struct stat st; | |
160 static int zero = 0; | |
161 | |
162 if (!compalstage_pathname[0]) | |
163 return(0); | |
164 fd = open(compalstage_pathname, O_RDONLY); | |
165 if (fd < 0) { | |
166 perror(compalstage_pathname); | |
167 exit(1); | |
168 } | |
169 fstat(fd, &st); | |
170 if (!S_ISREG(st.st_mode)) { | |
171 fprintf(stderr, "error: %s is not a regular file\n", | |
172 compalstage_pathname); | |
173 exit(1); | |
174 } | |
175 if (st.st_size > 65535) { | |
176 fprintf(stderr, | |
177 "error: %s exceed Compal download limit of 65535 bytes\n", | |
178 compalstage_pathname); | |
179 exit(1); | |
180 } | |
181 compalstage_len = st.st_size; | |
182 compalstage_totlen = compalstage_len + 4; | |
183 compalstage_imgbuf = malloc(compalstage_totlen); | |
184 if (!compalstage_imgbuf) { | |
185 perror("malloc"); | |
186 exit(1); | |
187 } | |
188 compalstage_imgbuf[0] = 0x02; | |
189 compalstage_imgbuf[1] = compalstage_len >> 8; | |
190 compalstage_imgbuf[2] = compalstage_len; | |
191 if (read(fd, compalstage_imgbuf+3, compalstage_len) != compalstage_len){ | |
192 fprintf(stderr, "%s: read error or short read\n", | |
193 compalstage_pathname); | |
194 exit(1); | |
195 } | |
196 close(fd); | |
197 compute_checksum(); | |
198 | |
199 printf("Using Compal stage image %s\n", compalstage_pathname); | |
200 cfsetispeed(&target_termios, B115200); | |
201 cfsetospeed(&target_termios, B115200); | |
202 if (tcsetattr(target_fd, TCSAFLUSH, &target_termios) < 0) { | |
203 perror("tcsetattr to switch baud rate"); | |
204 exit(1); | |
205 } | |
206 ioctl(target_fd, FIONBIO, &zero); | |
207 printf("Waiting for PROMPT1 from target (%s) at 115200 baud\n", | |
208 target_ttydev); | |
209 read_loop(); | |
210 free(compalstage_imgbuf); | |
211 | |
212 if (for_boot_rom) { | |
213 cfsetispeed(&target_termios, B19200); | |
214 cfsetospeed(&target_termios, B19200); | |
215 if (tcsetattr(target_fd, TCSAFLUSH, &target_termios) < 0) { | |
216 perror("tcsetattr to switch baud rate"); | |
217 exit(1); | |
218 } | |
219 } | |
220 | |
221 return(1); | |
222 } |