2013-03-06 10:29:49 +01:00
|
|
|
/**
|
|
|
|
* Native CPU entry code
|
|
|
|
*
|
2014-05-15 18:07:02 +02:00
|
|
|
* Copyright (C) 2013 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
|
2013-03-06 10:29:49 +01:00
|
|
|
*
|
2013-11-22 20:47:05 +01:00
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
2013-06-18 17:21:38 +02:00
|
|
|
* Public License. See the file LICENSE in the top level directory for more
|
|
|
|
* details.
|
2013-03-06 10:29:49 +01:00
|
|
|
*
|
|
|
|
* @ingroup arch
|
|
|
|
* @{
|
|
|
|
* @file
|
|
|
|
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2013-11-07 17:23:08 +01:00
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#else
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#endif
|
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
#include <stdio.h>
|
2013-06-26 23:29:09 +02:00
|
|
|
#include <stdlib.h>
|
2013-08-18 20:34:53 +02:00
|
|
|
#include <unistd.h>
|
2013-06-26 23:29:09 +02:00
|
|
|
#include <err.h>
|
2013-08-18 20:34:53 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2013-06-26 23:29:09 +02:00
|
|
|
|
2013-11-07 17:23:08 +01:00
|
|
|
#include "kernel_internal.h"
|
|
|
|
#include "cpu.h"
|
2013-06-26 23:29:09 +02:00
|
|
|
|
2013-08-18 20:34:53 +02:00
|
|
|
#include "board_internal.h"
|
2013-11-07 17:23:08 +01:00
|
|
|
#include "native_internal.h"
|
|
|
|
#include "tap.h"
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-08-18 20:34:53 +02:00
|
|
|
int _native_null_in_pipe[2];
|
|
|
|
int _native_null_out_file;
|
2013-12-10 12:10:05 +01:00
|
|
|
const char *_progname;
|
2014-02-14 16:18:40 +01:00
|
|
|
char **_native_argv;
|
2014-05-13 16:53:36 +02:00
|
|
|
pid_t _native_pid;
|
2014-05-16 15:40:06 +02:00
|
|
|
pid_t _native_id;
|
2014-05-19 19:58:40 +02:00
|
|
|
const char *_native_unix_socket_path = NULL;
|
2013-08-18 20:34:53 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* initialize _native_null_in_pipe to allow for reading from stdin
|
|
|
|
* @param stdiotype: "stdio" (only initialize pipe) or any string
|
|
|
|
* (redirect stdin to _native_null_in_pipe)
|
|
|
|
*/
|
|
|
|
void _native_null_in(char *stdiotype)
|
|
|
|
{
|
2014-06-13 23:52:05 +02:00
|
|
|
if (real_pipe(_native_null_in_pipe) == -1) {
|
2014-07-18 10:07:02 +02:00
|
|
|
err(EXIT_FAILURE, "_native_null_in(): pipe()");
|
2013-08-18 20:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(stdiotype, "stdio") == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-06-18 20:34:12 +02:00
|
|
|
if (real_dup2(_native_null_in_pipe[0], STDIN_FILENO) == -1) {
|
2013-08-18 20:34:53 +02:00
|
|
|
err(EXIT_FAILURE, "_native_null_in: dup2(STDIN_FILENO)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set up stdout redirection
|
|
|
|
*
|
|
|
|
* @param stdouttype: "stdio" (leave intact), "null" (redirect to
|
|
|
|
* /dev/null) or "file" (redirect to /tmp/riot.stdout.PID)
|
|
|
|
*/
|
|
|
|
void _native_log_stdout(char *stdouttype)
|
|
|
|
{
|
|
|
|
int stdout_outfile;
|
|
|
|
|
|
|
|
if (strcmp(stdouttype, "stdio") == 0) {
|
|
|
|
_native_null_out_file = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (strcmp(stdouttype, "null") == 0) {
|
|
|
|
if ((stdout_outfile = open("/dev/null", O_WRONLY)) == -1) {
|
|
|
|
err(EXIT_FAILURE, "_native_log_stdout: open");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(stdouttype, "file") == 0) {
|
|
|
|
char stdout_logname[255];
|
2014-05-13 16:53:36 +02:00
|
|
|
snprintf(stdout_logname, sizeof(stdout_logname), "/tmp/riot.stdout.%d", _native_pid);
|
2013-08-18 20:34:53 +02:00
|
|
|
if ((stdout_outfile = creat(stdout_logname, 0666)) == -1) {
|
|
|
|
err(EXIT_FAILURE, "_native_log_stdout: open");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
errx(EXIT_FAILURE, "_native_log_stdout: unknown log type");
|
|
|
|
}
|
|
|
|
|
2014-06-18 20:34:12 +02:00
|
|
|
if (real_dup2(stdout_outfile, STDOUT_FILENO) == -1) {
|
2013-08-18 20:34:53 +02:00
|
|
|
err(EXIT_FAILURE, "_native_log_stdout: dup2(STDOUT_FILENO)");
|
|
|
|
}
|
|
|
|
_native_null_out_file = stdout_outfile;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set up stderr redirection
|
|
|
|
*
|
|
|
|
* @param stderrtype: "stdio" (leave intact), "null" (redirect to
|
|
|
|
* /dev/null) or "file" (redirect to /tmp/riot.stdout.PID)
|
|
|
|
*/
|
|
|
|
void _native_log_stderr(char *stderrtype)
|
|
|
|
{
|
|
|
|
int stderr_outfile;
|
|
|
|
|
|
|
|
if (strcmp(stderrtype, "stdio") == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (strcmp(stderrtype, "null") == 0) {
|
|
|
|
if ((stderr_outfile = open("/dev/null", O_WRONLY)) == -1) {
|
|
|
|
err(EXIT_FAILURE, "_native_log_stderr: open");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(stderrtype, "file") == 0) {
|
|
|
|
char stderr_logname[255];
|
2014-05-13 16:53:36 +02:00
|
|
|
snprintf(stderr_logname, sizeof(stderr_logname), "/tmp/riot.stderr.%d", _native_pid);
|
2013-08-18 20:34:53 +02:00
|
|
|
if ((stderr_outfile = creat(stderr_logname, 0666)) == -1) {
|
|
|
|
err(EXIT_FAILURE, "_native_log_stderr: open");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
errx(EXIT_FAILURE, "_native_log_stderr: unknown log type");
|
|
|
|
}
|
|
|
|
|
2014-06-18 20:34:12 +02:00
|
|
|
if (real_dup2(stderr_outfile, STDERR_FILENO) == -1) {
|
2013-08-18 20:34:53 +02:00
|
|
|
err(EXIT_FAILURE, "_native_log_stderr: dup2(STDERR_FILENO)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-07 12:36:32 +02:00
|
|
|
void daemonize(void)
|
2013-08-18 20:34:53 +02:00
|
|
|
{
|
2014-06-18 20:34:12 +02:00
|
|
|
if ((_native_pid = real_fork()) == -1) {
|
2013-08-18 20:34:53 +02:00
|
|
|
err(EXIT_FAILURE, "daemonize: fork");
|
|
|
|
}
|
|
|
|
|
2014-05-13 16:53:36 +02:00
|
|
|
if (_native_pid > 0) {
|
|
|
|
real_printf("RIOT pid: %d\n", _native_pid);
|
2013-08-18 20:34:53 +02:00
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
2014-05-19 19:58:05 +02:00
|
|
|
else {
|
|
|
|
_native_pid = real_getpid();
|
|
|
|
}
|
2013-08-18 20:34:53 +02:00
|
|
|
}
|
|
|
|
|
2014-05-07 12:36:32 +02:00
|
|
|
void usage_exit(void)
|
2013-08-18 20:34:53 +02:00
|
|
|
{
|
2013-12-10 12:10:05 +01:00
|
|
|
real_printf("usage: %s", _progname);
|
2013-08-18 20:34:53 +02:00
|
|
|
|
|
|
|
#ifdef MODULE_NATIVENET
|
|
|
|
real_printf(" <tap interface>");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MODULE_UART0
|
2014-07-17 12:55:24 +02:00
|
|
|
real_printf(" [-t <port>|-u [path]] [-r]");
|
2013-08-18 20:34:53 +02:00
|
|
|
#endif
|
|
|
|
|
2014-05-16 15:40:06 +02:00
|
|
|
real_printf(" [-i <id>] [-d] [-e|-E] [-o]\n");
|
2013-08-18 20:34:53 +02:00
|
|
|
|
2014-04-19 12:37:17 +02:00
|
|
|
real_printf(" help: %s -h\n", _progname);
|
|
|
|
|
2013-08-18 20:34:53 +02:00
|
|
|
real_printf("\nOptions:\n\
|
2014-07-22 16:25:00 +02:00
|
|
|
-h help\n");
|
2013-08-18 20:34:53 +02:00
|
|
|
|
|
|
|
#ifdef MODULE_UART0
|
|
|
|
real_printf("\
|
2014-07-22 16:25:00 +02:00
|
|
|
-t <port> redirect stdio to TCP socket listening on <port>\n\
|
|
|
|
-u <path> redirect stdio to UNIX socket (<path> if given,\n\
|
2014-07-17 12:55:24 +02:00
|
|
|
/tmp/riot.tty.PID otherwise)\n\
|
|
|
|
-r replay missed output when (re-)attaching to socket\n\
|
|
|
|
(implies -o)\n");
|
2013-08-18 20:34:53 +02:00
|
|
|
#endif
|
2014-07-22 16:25:00 +02:00
|
|
|
real_printf("\
|
|
|
|
-i <id> specify instance id (set by config module)\n\
|
|
|
|
-d daemonize\n\
|
|
|
|
-e redirect stderr to file\n\
|
|
|
|
-E do not redirect stderr (i.e. leave sterr unchanged despite\n\
|
|
|
|
daemon/socket io)\n\
|
|
|
|
-o redirect stdout to file (/tmp/riot.stdout.PID) when not attached\n\
|
|
|
|
to socket\n");
|
2013-08-18 20:34:53 +02:00
|
|
|
|
|
|
|
real_printf("\n\
|
|
|
|
The order of command line arguments matters.\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-06-26 23:29:09 +02:00
|
|
|
__attribute__((constructor)) static void startup(int argc, char **argv)
|
2013-03-06 01:08:15 +01:00
|
|
|
{
|
2014-07-18 10:07:02 +02:00
|
|
|
_native_init_syscalls();
|
2014-01-24 17:03:01 +01:00
|
|
|
|
2014-05-13 16:53:36 +02:00
|
|
|
_native_argv = argv;
|
2013-12-10 12:10:05 +01:00
|
|
|
_progname = argv[0];
|
2014-05-13 17:41:36 +02:00
|
|
|
_native_pid = real_getpid();
|
2014-02-14 16:18:40 +01:00
|
|
|
|
2014-05-16 15:40:06 +02:00
|
|
|
/* will possibly be overridden via option below: */
|
|
|
|
_native_id = _native_pid;
|
|
|
|
|
2013-08-18 20:34:53 +02:00
|
|
|
int argp = 1;
|
|
|
|
char *stderrtype = "stdio";
|
|
|
|
char *stdouttype = "stdio";
|
|
|
|
char *stdiotype = "stdio";
|
|
|
|
#ifdef MODULE_UART0
|
|
|
|
char *ioparam = NULL;
|
2014-07-17 12:55:24 +02:00
|
|
|
int replay = 0;
|
2013-08-18 20:34:53 +02:00
|
|
|
#endif
|
2013-06-26 23:29:09 +02:00
|
|
|
|
2013-08-08 11:08:33 +02:00
|
|
|
#ifdef MODULE_NATIVENET
|
2014-04-19 12:37:17 +02:00
|
|
|
if (
|
|
|
|
(argc < 2)
|
|
|
|
|| (
|
|
|
|
(strcmp("-h", argv[argp]) == 0)
|
|
|
|
|| (strcmp("--help", argv[argp]) == 0)
|
|
|
|
)
|
|
|
|
) {
|
2013-08-18 20:34:53 +02:00
|
|
|
usage_exit();
|
|
|
|
}
|
|
|
|
argp++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (; argp < argc; argp++) {
|
|
|
|
char *arg = argv[argp];
|
2014-04-19 12:37:17 +02:00
|
|
|
if ((strcmp("-h", arg) == 0) || (strcmp("--help", arg) == 0)) {
|
|
|
|
usage_exit();
|
|
|
|
}
|
2014-05-16 15:40:06 +02:00
|
|
|
else if (strcmp("-i", arg) == 0) {
|
|
|
|
if (argp + 1 < argc) {
|
|
|
|
argp++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
usage_exit();
|
|
|
|
}
|
|
|
|
_native_id = atol(argv[argp]);
|
|
|
|
}
|
2014-04-19 12:37:17 +02:00
|
|
|
else if (strcmp("-d", arg) == 0) {
|
2013-08-18 20:34:53 +02:00
|
|
|
daemonize();
|
|
|
|
if (strcmp(stdiotype, "stdio") == 0) {
|
|
|
|
stdiotype = "null";
|
|
|
|
}
|
|
|
|
if (strcmp(stdouttype, "stdio") == 0) {
|
|
|
|
stdouttype = "null";
|
|
|
|
}
|
|
|
|
if (strcmp(stderrtype, "stdio") == 0) {
|
|
|
|
stderrtype = "null";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp("-e", arg) == 0) {
|
|
|
|
stderrtype = "file";
|
|
|
|
}
|
|
|
|
else if (strcmp("-E", arg) == 0) {
|
|
|
|
stderrtype = "stdio";
|
|
|
|
}
|
|
|
|
else if (strcmp("-o", arg) == 0) {
|
|
|
|
stdouttype = "file";
|
|
|
|
}
|
|
|
|
#ifdef MODULE_UART0
|
2014-07-17 12:55:24 +02:00
|
|
|
else if (strcmp("-r", arg) == 0) {
|
|
|
|
stdouttype = "file";
|
|
|
|
replay = 1;
|
|
|
|
}
|
2013-08-18 20:34:53 +02:00
|
|
|
else if (strcmp("-t", arg) == 0) {
|
|
|
|
stdiotype = "tcp";
|
2014-05-19 19:29:48 +02:00
|
|
|
if (argp + 1 < argc) {
|
2013-08-18 20:34:53 +02:00
|
|
|
ioparam = argv[++argp];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
usage_exit();
|
|
|
|
}
|
|
|
|
if (strcmp(stdouttype, "stdio") == 0) {
|
|
|
|
stdouttype = "null";
|
|
|
|
}
|
|
|
|
if (strcmp(stderrtype, "stdio") == 0) {
|
|
|
|
stderrtype = "null";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp("-u", arg) == 0) {
|
|
|
|
stdiotype = "unix";
|
|
|
|
if (strcmp(stdouttype, "stdio") == 0) {
|
|
|
|
stdouttype = "null";
|
|
|
|
}
|
|
|
|
if (strcmp(stderrtype, "stdio") == 0) {
|
|
|
|
stderrtype = "null";
|
|
|
|
}
|
2014-05-19 19:58:40 +02:00
|
|
|
|
|
|
|
/* parse optional path */
|
|
|
|
if ((argp + 1 < argc) && (argv[argp + 1][0] != '-')) {
|
|
|
|
_native_unix_socket_path = argv[++argp];
|
|
|
|
}
|
2013-08-18 20:34:53 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else {
|
|
|
|
usage_exit();
|
|
|
|
}
|
2013-06-26 23:29:09 +02:00
|
|
|
}
|
2013-08-18 20:34:53 +02:00
|
|
|
|
|
|
|
_native_log_stderr(stderrtype);
|
|
|
|
_native_log_stdout(stdouttype);
|
|
|
|
_native_null_in(stdiotype);
|
|
|
|
|
|
|
|
#ifdef MODULE_UART0
|
2014-07-17 12:55:24 +02:00
|
|
|
_native_init_uart0(stdiotype, ioparam, replay);
|
2013-06-26 23:29:09 +02:00
|
|
|
#endif
|
|
|
|
|
2013-11-13 01:22:30 +01:00
|
|
|
native_hwtimer_pre_init();
|
2013-03-06 01:08:15 +01:00
|
|
|
native_cpu_init();
|
|
|
|
native_interrupt_init();
|
2013-08-08 11:08:33 +02:00
|
|
|
#ifdef MODULE_NATIVENET
|
2013-06-26 23:29:09 +02:00
|
|
|
tap_init(argv[1]);
|
|
|
|
#endif
|
2013-03-06 01:08:15 +01:00
|
|
|
|
|
|
|
board_init();
|
|
|
|
|
|
|
|
puts("RIOT native hardware initialization complete.\n");
|
|
|
|
kernel_init();
|
|
|
|
}
|