#include <stdio.h>
+#include <stdlib.h>
/* According to POSIX.1-2001 */
#include <sys/select.h>
#include <string.h>
#define STLINKY_MAGIC 0xDEADF00D
+#define READ_UINT32_LE(buf) ((uint32_t) ( buf[0] \
+ | buf[1] << 8 \
+ | buf[2] << 16 \
+ | buf[3] << 24))
+
+static stlink_t* sl;
+sigset_t sig_mask;
+
struct stlinky {
stlink_t *sl;
uint32_t off;
size_t bufsize;
};
+void nonblock(int state);
+
+static void cleanup(int signal __attribute__((unused))) {
+ if (sl) {
+ /* Switch back to mass storage mode before closing. */
+ stlink_run(sl);
+ stlink_exit_debug_mode(sl);
+ stlink_close(sl);
+ }
+
+ printf("\n");
+ nonblock(0);
+ exit(1);
+}
+
+void sig_init() {
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, SIGINT);
+ sigaddset(&sig_mask, SIGTERM);
+ signal(SIGINT, &cleanup);
+ signal(SIGTERM, &cleanup);
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+}
+
+void sig_process() {
+ sigset_t pending;
+ sigpending(&pending);
+ if (sigismember(&pending, SIGINT) || sigismember(&pending, SIGTERM)) {
+ sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
+ sigsuspend(&pending);
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+ }
+}
/* Detects stlinky in RAM, returns handler */
struct stlinky* stlinky_detect(stlink_t* sl)
{
static const uint32_t sram_base = 0x20000000;
struct stlinky* st = malloc(sizeof(struct stlinky));
+ int multiple=0;
st->sl = sl;
- printf("sram: 0x%x bytes @ 0x%x\n", sl->sram_base, sl->sram_size);
+ printf("sram: 0x%x bytes @ 0x%zx\n", sl->sram_base, sl->sram_size);
uint32_t off;
for (off = 0; off < sl->sram_size; off += 4) {
+ if (off % 1024 == 0) sig_process();
stlink_read_mem32(sl, sram_base + off, 4);
- if ( STLINKY_MAGIC== *(uint32_t*) sl->q_buf)
+ if (STLINKY_MAGIC == READ_UINT32_LE(sl->q_buf))
{
+ if (multiple > 0) printf("WARNING: another ");
printf("stlinky detected at 0x%x\n", sram_base + off);
st->off = sram_base + off;
stlink_read_mem32(sl, st->off + 4, 4);
st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
printf("stlinky buffer size 0x%zu \n", st->bufsize);
- return st;
+ multiple++;
}
}
+ if (multiple > 0) {
+ if (multiple > 1) {
+ printf("Using last stlinky structure detected\n");
+ }
+ return st;
+ }
return NULL;
}
}
-static int keep_running = 1;
-static int sigcount=0;
-void cleanup(int dummy)
-{
- sigcount++;
- keep_running = 0;
- printf("\n\nGot a signal\n");
- if (sigcount==2) {
- printf("\n\nGot a second signal - bailing out\n");
- exit(1);
- }
-}
-
-
int main(int ac, char** av) {
- stlink_t* sl;
+ struct stlinky *st=NULL;
+
+ sig_init();
- /* unused */
- ac = ac;
- av = av;
sl = stlink_open_usb(10, 1);
if (sl != NULL) {
printf("ST-Linky proof-of-concept terminal :: Created by Necromant for lulz\n");
/* TODO: Make timeout adjustable via command line */
sleep(1);
- struct stlinky *st = stlinky_detect(sl);
+ if(ac == 1){
+ st = stlinky_detect(sl);
+ }else if(ac == 2){
+ st = malloc(sizeof(struct stlinky));
+ st->sl = sl;
+ st->off = (int)strtol(av[1], NULL, 16);
+ printf("using stlinky at 0x%x\n", st->off);
+ stlink_read_mem32(sl, st->off + 4, 4);
+ st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
+ printf("stlinky buffer size 0x%zu \n", st->bufsize);
+ }else{
+ cleanup(0);
+ }
if (st == NULL)
{
printf("stlinky magic not found in sram :(\n");
- goto bailout;
+ cleanup(0);
}
char* rxbuf = malloc(st->bufsize);
char* txbuf = malloc(st->bufsize);
int fd = fileno(stdin);
int saved_flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK);
- signal(SIGINT, cleanup);
printf("Entering interactive terminal. CTRL+C to exit\n\n\n");
while(1) {
+ sig_process();
if (stlinky_canrx(st)) {
tmp = stlinky_rx(st, rxbuf);
fwrite(rxbuf,tmp,1,stdout);
tmp = read(fd, txbuf, st->bufsize);
stlinky_tx(st,txbuf,tmp);
}
- if (!keep_running)
- break;
}
- bailout:
- nonblock(0);
- stlink_exit_debug_mode(sl);
- stlink_close(sl);
}
return 0;
}