3 /* According to POSIX.1-2001 */
4 #include <sys/select.h>
12 #include "stlink-common.h"
14 /* STLinky structure on STM chip
23 char upbuf[CONFIG_LIB_STLINKY_BSIZE];
24 char dwbuf[CONFIG_LIB_STLINKY_BSIZE];
25 } __attribute__ ((packed));
29 #define STLINKY_MAGIC 0xDEADF00D
31 #define ST_TERM_MAX_BUFF_SIZE (1024*1024) //1Mb
34 #define RX_BUFF_OFFSET 24
35 #define TX_Q_OFFSET 16
36 #define TX_BUFF_OFFSET(bufsize) (24 + bufsize)
38 #define READ_UINT32_LE(buf) ((uint32_t) ( buf[0] \
52 void nonblock(int state);
54 static void cleanup(int signal __attribute__((unused))) {
56 /* Switch back to mass storage mode before closing. */
58 stlink_exit_debug_mode(sl);
68 sigemptyset(&sig_mask);
69 sigaddset(&sig_mask, SIGINT);
70 sigaddset(&sig_mask, SIGTERM);
71 signal(SIGINT, &cleanup);
72 signal(SIGTERM, &cleanup);
73 sigprocmask(SIG_BLOCK, &sig_mask, NULL);
79 if (sigismember(&pending, SIGINT) || sigismember(&pending, SIGTERM)) {
80 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
82 sigprocmask(SIG_BLOCK, &sig_mask, NULL);
86 /* Detects stlinky in RAM, returns handler */
87 struct stlinky* stlinky_detect(stlink_t* sl)
89 static const uint32_t sram_base = 0x20000000;
90 struct stlinky* st = malloc(sizeof(struct stlinky));
93 printf("sram: 0x%x bytes @ 0x%zx\n", sl->sram_base, sl->sram_size);
95 for (off = 0; off < sl->sram_size; off += 4) {
96 if (off % 1024 == 0) sig_process();
97 stlink_read_mem32(sl, sram_base + off, 4);
98 if (STLINKY_MAGIC == READ_UINT32_LE(sl->q_buf))
100 if (multiple > 0) printf("WARNING: another ");
101 printf("stlinky detected at 0x%x\n", sram_base + off);
102 st->off = sram_base + off;
103 stlink_read_mem32(sl, st->off + 4, 4);
104 st->bufsize = READ_UINT32_LE(sl->q_buf);
105 printf("stlinky buffer size 0x%zu \n", st->bufsize);
111 printf("Using last stlinky structure detected\n");
118 static void stlinky_read_buff(struct stlinky *st, uint32_t off, uint32_t size, char *buffer)
125 //Read from device with 4-byte alignment
126 aligned_size = (size & 0xFFFFFFFC) + 8;
127 stlink_read_mem32(st->sl, off & 0xFFFFFFFC, aligned_size);
129 //copy to local buffer
130 memcpy(buffer, st->sl->q_buf + (off & 0x3), size);
135 static void stlinky_write_buf(struct stlinky *st, uint32_t off, uint32_t size, char *buffer)
137 memcpy(st->sl->q_buf, buffer, size);
138 stlink_write_mem8(st->sl, off, size);
142 size_t stlinky_rx(struct stlinky *st, char* buffer)
144 //read head and tail values
146 stlink_read_mem32(st->sl, st->off + RX_Q_OFFSET, sizeof(tail) + sizeof(head));
147 memcpy(&tail, &st->sl->q_buf[0], sizeof(tail));
148 memcpy(&head, &st->sl->q_buf[sizeof(tail)], sizeof(head));
157 stlinky_read_buff(st, st->off + RX_BUFF_OFFSET + tail, head - tail, buffer);
158 size_read += head - tail;
159 } else if(head < tail){
160 stlinky_read_buff(st, st->off + RX_BUFF_OFFSET + tail, st->bufsize - tail, buffer);
161 size_read += st->bufsize - tail;
163 stlinky_read_buff(st, st->off + RX_BUFF_OFFSET, head, buffer + size_read);
168 tail = (tail + size_read) % st->bufsize;
171 memcpy(st->sl->q_buf, &tail, sizeof(tail));
172 stlink_write_mem32(st->sl, st->off + RX_Q_OFFSET, sizeof(tail));
177 size_t stlinky_tx(struct stlinky *st, char* buffer, size_t siz)
179 //read head and tail values
181 stlink_read_mem32(st->sl, st->off + TX_Q_OFFSET, sizeof(tail) + sizeof(head));
182 memcpy(&tail, &st->sl->q_buf[0], sizeof(tail));
183 memcpy(&head, &st->sl->q_buf[sizeof(tail)], sizeof(head));
185 //Figure out buffer usage
186 int usage = head - tail;
188 usage += st->bufsize;
190 //check if new data will fit
191 if (usage + siz >= st->bufsize)
194 //copy in data (take care of possible split)
195 int first_chunk = head + siz >= st->bufsize ? st->bufsize - head : siz;
196 int second_chunk = siz - first_chunk;
199 stlinky_write_buf(st, st->off + TX_BUFF_OFFSET(st->bufsize) + head, first_chunk, buffer);
200 if (second_chunk > 0)
201 stlinky_write_buf(st, st->off + TX_BUFF_OFFSET(st->bufsize),
202 second_chunk, buffer + first_chunk);
204 //increment head pointer
205 head = (head + siz) % st->bufsize;
206 memcpy(st->sl->q_buf, &head, sizeof(head));
207 stlink_write_mem32(st->sl, st->off + TX_Q_OFFSET + sizeof(tail), sizeof(head));
219 FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
220 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
221 return FD_ISSET(STDIN_FILENO, &fds);
224 void nonblock(int state)
226 struct termios ttystate;
228 //get the terminal state
229 tcgetattr(STDIN_FILENO, &ttystate);
233 //turn off canonical mode
234 ttystate.c_lflag &= ~ICANON;
235 ttystate.c_lflag &= ~ECHO;
236 //minimum of number input read.
237 ttystate.c_cc[VMIN] = 1;
241 //turn on canonical mode
242 ttystate.c_lflag |= ICANON | ECHO;
244 //set the terminal attributes.
245 tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
249 int main(int ac, char** av) {
250 struct stlinky *st=NULL;
254 sl = stlink_open_usb(10, 1, NULL);
256 printf("ST-Linky proof-of-concept terminal :: Created by Necromant for lulz\n");
258 stlink_enter_swd_mode(sl);
259 printf("chip id: %#x\n", sl->chip_id);
260 printf("core_id: %#x\n", sl->core_id);
262 cortex_m3_cpuid_t cpuid;
263 stlink_cpu_id(sl, &cpuid);
264 printf("cpuid:impl_id = %0#x, variant = %#x\n", cpuid.implementer_id, cpuid.variant);
265 printf("cpuid:part = %#x, rev = %#x\n", cpuid.part, cpuid.revision);
268 stlink_force_debug(sl);
272 /* wait for device to boot */
273 /* TODO: Make timeout adjustable via command line */
277 st = stlinky_detect(sl);
279 st = malloc(sizeof(struct stlinky));
281 st->off = (int)strtol(av[1], NULL, 16);
282 printf("using stlinky at 0x%x\n", st->off);
283 stlink_read_mem32(sl, st->off + 4, 4);
284 st->bufsize = READ_UINT32_LE(sl->q_buf);
285 printf("stlinky buffer size 0x%zu \n", st->bufsize);
291 printf("stlinky magic not found in sram :(\n");
294 if (st->bufsize > ST_TERM_MAX_BUFF_SIZE){
295 printf("stlinky buffer size too big\n");
298 char* rxbuf = malloc(st->bufsize);
299 char* txbuf = malloc(st->bufsize);
302 int fd = fileno(stdin);
303 int saved_flags = fcntl(fd, F_GETFL);
304 fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK);
305 printf("Entering interactive terminal. CTRL+C to exit\n\n\n");
308 tmp = stlinky_rx(st, rxbuf);
311 fwrite(rxbuf,tmp,1,stdout);
315 tmp = read(fd, txbuf, st->bufsize);
316 stlinky_tx(st,txbuf,tmp);