Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 95 additions & 20 deletions system/nxinit/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,83 @@ static int event_callback(FAR struct action_manager_s *am,
return event->pending;
}

static FAR char *parse_operator(FAR char *pos,
FAR enum action_cmd_op_e *op)
{
bool in_quotes = false;

for (; *pos != '\0'; pos++)
{
if (*pos == '"')
{
in_quotes = !in_quotes;
continue;
}

if (in_quotes)
{
continue;
}

if (*pos == '&' && *(pos + 1) == '&')
{
*op = CMD_OP_AND;
*pos = '\0';
return pos + 2;
}

if (*pos == '|' && *(pos + 1) == '|')
{
*op = CMD_OP_OR;
*pos = '\0';
return pos + 2;
}
}

*op = CMD_OP_NONE;
return pos;
}

static int parse_command(FAR char *pos,
FAR struct list_node *cmds)
{
FAR enum action_cmd_op_e op = CMD_OP_NONE;
FAR enum action_cmd_op_e next_op;
FAR struct action_cmd_s *cmd;
FAR char *next_pos;

while (*pos)
{
next_pos = parse_operator(pos, &next_op);

cmd = calloc(1, sizeof(*cmd));
if (cmd == NULL)
{
return -errno;
}

cmd->argc = init_parse_arguments(pos, true,
nitems(cmd->argv) - 1,
cmd->argv);
if (cmd->argc < 1)
{
free(cmd);
init_err("invalid argument");
return -EINVAL;
}

cmd->op = op;
list_add_tail(cmds, &cmd->node);
init_debug("add command %p(%s) to list %p", cmd, cmd->argv[0], cmds);
init_dump_args(cmd->argc, cmd->argv);

op = next_op;
pos = next_pos;
}

return 0;
}

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -315,6 +392,15 @@ int init_action_run_command(FAR struct action_manager_s *am)
struct action_cmd_s, node);
}

if ((am->running->op == CMD_OP_AND && ready->prev_ret != 0) ||
(am->running->op == CMD_OP_OR && ready->prev_ret == 0))
{
init_debug("Skipping command due to op (prev_ret %d)",
ready->prev_ret);
init_action_reap_command(am, ready->prev_ret);
return 0;
}

#if defined(CONFIG_SYSTEM_NXINIT_ACTION_WARN_SLOW) && \
CONFIG_SYSTEM_NXINIT_ACTION_WARN_SLOW > 0
clock_gettime(CLOCK_MONOTONIC, &am->time_run);
Expand All @@ -326,13 +412,13 @@ int init_action_run_command(FAR struct action_manager_s *am)
}
else
{
init_action_reap_command(am);
init_action_reap_command(am, ret);
}

return 0;
}

void init_action_reap_command(FAR struct action_manager_s *am)
void init_action_reap_command(FAR struct action_manager_s *am, int ret)
{
FAR struct action_s *ready = list_peek_head_type(&am->ready_actions,
struct action_s,
Expand Down Expand Up @@ -361,6 +447,7 @@ void init_action_reap_command(FAR struct action_manager_s *am)
#endif

am->pid_running = -1;
ready->prev_ret = ret;
if (list_is_tail(&ready->cmds, &am->running->node))
{
am->running = NULL;
Expand All @@ -377,7 +464,6 @@ int init_action_parse(FAR const struct parser_s *parser,
{
FAR struct action_manager_s *am = parser->priv;
FAR char *argv[2 * CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX];
FAR struct action_cmd_s *cmd;
FAR struct action_s *a;
int ret;

Expand Down Expand Up @@ -435,26 +521,15 @@ int init_action_parse(FAR const struct parser_s *parser,
}
else
{
cmd = calloc(1, sizeof(*cmd));
if (cmd == NULL)
{
init_err("Alloc action command");
return -errno;
}

cmd->argc = init_parse_arguments(buf, true, nitems(cmd->argv) - 1,
cmd->argv);
if (cmd->argc < 1)
a = list_last_entry(&am->actions, struct action_s, node);
ret = parse_command(buf, &a->cmds);
if (ret < 0)
{
free(cmd);
init_err("Invalid command argument");
return -EINVAL;
init_err("failed to parse command line: %s", buf);
return ret;
}

a = list_last_entry(&am->actions, struct action_s, node);
list_add_tail(&a->cmds, &cmd->node);
init_debug("Add command %p(%s) to action %p", cmd, cmd->argv[0], a);
init_dump_args(cmd->argc, cmd->argv);
init_debug("add command line to action %p", a);
}

return 0;
Expand Down
11 changes: 10 additions & 1 deletion system/nxinit/action.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,19 @@
* Public Types
****************************************************************************/

enum action_cmd_op_e
{
CMD_OP_NONE,
CMD_OP_AND,
CMD_OP_OR,
};

struct action_cmd_s
{
struct list_node node; /* Command list node */
int argc;
FAR char *argv[CONFIG_SYSTEM_NXINIT_ACTION_CMD_ARGS_MAX];
enum action_cmd_op_e op;
};

struct action_event_s
Expand All @@ -58,6 +66,7 @@ struct action_s
struct list_node ready_node; /* Ready list node */
struct action_event_s events[CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX];
struct list_node cmds; /* Command header, struct action_cmd_s */
int prev_ret;
};

struct action_manager_s
Expand Down Expand Up @@ -102,7 +111,7 @@ typedef CODE int (*init_action_event_cb)(FAR struct action_manager_s *,
int init_action_add_event(FAR struct action_manager_s *am,
FAR const char *name);
int init_action_run_command(FAR struct action_manager_s *am);
void init_action_reap_command(FAR struct action_manager_s *am);
void init_action_reap_command(FAR struct action_manager_s *am, int ret);
int init_action_parse(FAR const struct parser_s *parser,
bool create, FAR char *buf);
int init_action_foreach_event(FAR struct action_manager_s *am,
Expand Down
83 changes: 82 additions & 1 deletion system/nxinit/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
#include <nuttx/config.h>

#include <errno.h>
#include <inttypes.h>
#include <poll.h>
#include <stdio.h>
#include <string.h>
#include <sys/boardctl.h>
#include <sys/param.h>
#include <sys/wait.h>

Expand Down Expand Up @@ -91,7 +95,7 @@ static void reap_process(FAR struct service_manager_s *sm,
if (pid == am->pid_running)
{
name = am->running->argv[0];
init_action_reap_command(am);
init_action_reap_command(am, ret);
}

service = init_service_find_by_pid(sm, pid);
Expand All @@ -107,6 +111,77 @@ static void reap_process(FAR struct service_manager_s *sm,
}
}

#ifdef CONFIG_BOARDCTL_RESET_CAUSE
static int init_boot_reason(FAR struct action_manager_s *am)
{
static FAR const char *const resetcause[] =
{
[BOARDIOC_RESETCAUSE_NONE] = "unknown",
[BOARDIOC_RESETCAUSE_SYS_CHIPPOR] = "cold",
[BOARDIOC_RESETCAUSE_SYS_RWDT] = "watchdog",
[BOARDIOC_RESETCAUSE_SYS_BOR] = "undervoltage",
[BOARDIOC_RESETCAUSE_CORE_DPSP] = "warm",
[BOARDIOC_RESETCAUSE_CORE_MWDT] = "watchdog",
[BOARDIOC_RESETCAUSE_CORE_RWDT] = "watchdog",
[BOARDIOC_RESETCAUSE_CPU_MWDT] = "watchdog",
[BOARDIOC_RESETCAUSE_CPU_RWDT] = "watchdog",
[BOARDIOC_RESETCAUSE_PIN] = "powerkey",
[BOARDIOC_RESETCAUSE_LOWPOWER] = "lowpower",
[BOARDIOC_RESETCAUSE_UNKOWN] = "unknown",
};

static FAR const char * const resetflag[] =
{
[BOARDIOC_SOFTRESETCAUSE_USER_REBOOT] = "reboot",
[BOARDIOC_SOFTRESETCAUSE_ASSERT] = "assert",
[BOARDIOC_SOFTRESETCAUSE_PANIC] = "kernel_panic",
[BOARDIOC_SOFTRESETCAUSE_ENTER_BOOTLOADER] = "bootloader",
[BOARDIOC_SOFTRESETCAUSE_ENTER_RECOVERY] = "recovery",
[BOARDIOC_SOFTRESETCAUSE_RESTORE_FACTORY] = "factory_reset",
[BOARDIOC_SOFTRESETCAUSE_RESTORE_FACTORY_INQUIRY] =
"factory_reset_inquiry",
[BOARDIOC_SOFTRESETCAUSE_THERMAL] = "thermal",
};

char buf[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX];
struct boardioc_reset_cause_s reset;
FAR const char *value;
int ret;

memset(&reset, 0, sizeof(reset));
ret = boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset);
if (ret < 0)
{
init_err("boardctl BOARDIOC_RESET_CAUSE failed: %d", ret);
return ret;
}

if (reset.cause >= nitems(resetcause))
{
reset.cause = nitems(resetcause) - 1;
}

if (reset.flag >= nitems(resetflag))
{
reset.flag = nitems(resetflag) - 1;
}

if (resetcause[reset.cause])
{
sprintf(buf, "%s,%" PRIu32 "", resetcause[reset.cause], reset.flag);
value = buf;
}
else
{
value = resetflag[reset.flag];
}

return init_property_set(am->prop, "sys.boot.reason", value);
}
#else
# define init_boot_reason(am) (0)
#endif

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -185,6 +260,12 @@ int main(int argc, FAR char *argv[])
init_dump_actions(&am.actions);
init_dump_services(&sm.services);

r = init_boot_reason(&am);
if (r < 0)
{
goto out;
}

init_action_add_event(&am, "boot");

for (; ; )
Expand Down
Loading