24 #include <sys/ioctl.h>
26 #include <sys/select.h>
29 #include <sys/types.h>
40 #include <sys/epoll.h>
50 static uint32_t entrypoint;
52 #define dbg(fmt, ...) if (g_debug) { \
53 fprintf(stderr, "libeasynmc: " fmt, ##__VA_ARGS__); \
56 #define err(fmt, ...) if (g_debug) { \
57 fprintf(stderr, "libeasynmc: " fmt, ##__VA_ARGS__); \
67 "nmrun - The EasyNMC app runner wrapper\n"
68 "(c) 2014 RC Module | Andrew 'Necromant' Andrianov <andrew@ncrmnt.org>\n"
69 "This is free software; see the source for copying conditions. There is NO\n"
70 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
72 "Usage: %s [options] myapp.abs [arguments] - operate on core 0 (default)\n"
73 "Valid options are: \n"
74 " --help - Show this help\n"
75 " --core=id - Select a core to operate on (Default - use first usused core)\n"
76 " --force - Disable internal seatbelts (DANGEROUS!)\n"
77 " --nostdio - Do not auto-attach stdio\n"
78 " --nosigint - Do not catch SIGINT\n"
79 " --detach - Run app in background (do not attach console)\n"
80 "Debugging options: \n"
81 " --debug - Print lots of debugging info (nmctl)\n"
82 " --debug-lib - Print lots of debugging info (libeasynmc)\n"
87 static struct option long_options[] =
90 {
"help", no_argument, 0,
'h' },
93 {
"core", required_argument, 0,
'c' },
94 {
"force", no_argument, &
g_force, 1 },
97 {
"detach", no_argument, &
g_detach, 1 },
101 {
"debug", no_argument, &
g_debug, 1 },
102 {
"dump-ldr-regs", optional_argument, 0,
'D' },
109 struct termios ttystate;
112 tcgetattr(fd, &ttystate);
116 ttystate.c_lflag &= ~ICANON;
117 ttystate.c_lflag &= ~ECHO;
118 ttystate.c_lflag = 0;
119 ttystate.c_cc[VTIME] = 0;
120 ttystate.c_cc[VMIN] = 0;
126 ttystate.c_lflag |= ICANON | ECHO;
129 tcsetattr(fd, TCSANOW, &ttystate);
135 fprintf(stderr,
"\nCTRL+C pressed, terminating app\n");
140 if (isatty(STDIN_FILENO))
148 signal(sig, SIG_IGN);
157 unsigned char fromnmc[1024];
160 n = read(fd, fromnmc, 1024);
165 perror(
"read-from-nmc");
169 write(STDOUT_FILENO, fromnmc, n);
179 struct epoll_event event[3];
180 struct epoll_event *events;
181 int efd = epoll_create(2);
182 setvbuf(stdin,NULL,_IONBF,0);
186 perror (
"epoll_create");
191 int flags = fcntl(h->
iofd, F_GETFL, 0);
192 fcntl(h->
iofd, F_SETFL, flags | O_NONBLOCK);
194 if (!isatty(STDIN_FILENO)) {
195 flags = fcntl(STDIN_FILENO, F_GETFL, 0);
196 fcntl(h->
iofd, F_SETFL, flags | O_NONBLOCK);
201 event[0].data.fd = h->
iofd;
202 event[0].events = EPOLLIN | EPOLLOUT | EPOLLET;
204 event[1].data.fd = h->
memfd;
205 event[1].events = EPOLLNMI | EPOLLHP | EPOLLET;
207 event[2].data.fd = STDIN_FILENO;
208 event[2].events = EPOLLIN | EPOLLET;
210 for (i = 0; i < 3; i++) {
211 ret = epoll_ctl (efd, EPOLL_CTL_ADD, event[i].data.fd, &event[i]);
214 perror (
"epoll_ctl");
220 events = calloc (
NUMEVENTS,
sizeof event);
222 int can_read_stdin = 0;
223 int can_write_to_nmc = 0;
225 int gotfromstdin = 0;
226 int written_to_nmc = 0;
227 unsigned char tonmc[1024];
231 num = epoll_wait(efd, events,
NUMEVENTS, -1);
232 for (i = 0; i < num; i++) {
233 if ((events[i].data.fd == STDIN_FILENO) && (events[i].events & EPOLLIN))
236 if (can_read_stdin && !gotfromstdin)
238 gotfromstdin = read(STDIN_FILENO, tonmc, 1024);
239 if (isatty(STDIN_FILENO) && tonmc[0] == 3)
242 if (-1 == gotfromstdin) {
243 perror(
"read-from-stdin");
248 if (events[i].data.fd == h->
iofd && (events[i].events & EPOLLIN)) {
254 if (events[i].data.fd == h->
iofd && (events[i].events & EPOLLOUT))
257 if ((events[i].data.fd == h->
memfd) &&
267 fprintf(stderr,
"App terminated with result %d, exiting\n", ret);
272 if (can_write_to_nmc && (written_to_nmc != gotfromstdin)) {
273 int n = write(h->
iofd, &tonmc[written_to_nmc],
274 gotfromstdin - written_to_nmc);
278 if (written_to_nmc == gotfromstdin) {
283 else if (errno == EAGAIN) {
286 perror(
"write-to-nmc");
301 int main(
int argc,
char **argv)
305 char*
self =
"nmrun";
308 usage(argv[0]), exit(1);
313 int option_index = 0;
314 c = getopt_long (argc, argv,
"c:h",
315 long_options, &option_index);
324 if (strcmp(optarg,
"all") == 0)
339 char* absfile = argv[optind++];
340 int num_args = argc - optind;
341 char **args = &argv[optind];
352 fprintf(stderr,
"Failed to open core %d\n", core);
358 fprintf(stderr,
"Core is %s, expecting core to be idle\n",
easynmc_state_name(state));
364 fprintf(stderr,
"Failed to upload abs file\n");
370 fprintf(stderr,
"WARN: Failed to set arguments. Not supported by app?\n");
376 fprintf(stderr,
"Failed to reset polling counter (\n");
383 fprintf(stderr,
"Failed to start app (\n");
395 fprintf(stderr,
"Application now started, hit CTRL+C to %s it\n",
g_nosigint ?
"detach" :
"stop");
398 fprintf(stderr,
"Application started, detaching\n");
402 if (isatty(STDIN_FILENO))