comparison loadtools/compalload.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children b77005f6d315
comparison
equal deleted inserted replaced
-1:000000000000 0:e7502631a0f9
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 }