From 3566a74c9333cb1919fe41a7345bed639925a88e Mon Sep 17 00:00:00 2001 From: wangyongrong Date: Fri, 28 Aug 2026 21:13:04 +0800 Subject: [PATCH 1/3] system/nxinit: add rptun and unlink builtin commands BL uses init framework (not NSH), so the NSH rptun command is not available. Add rptun as an init builtin command that supports start and stop subcommands. Also add a generic unlink builtin command for removing device nodes. Usage in init.bl.rc: rptun stop /dev/rptun/corecs unlink /dev/rptun/corecs rptun start /dev/rptun/corecs - rptun start/stop: open device, ioctl(RPTUNIOC_START/STOP), close - unlink: generic command to unlink any file/device node Signed-off-by: wangyongrong --- system/nxinit/builtin.c | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/system/nxinit/builtin.c b/system/nxinit/builtin.c index 5ed7f3a29fe..a2bc722bfba 100644 --- a/system/nxinit/builtin.c +++ b/system/nxinit/builtin.c @@ -25,16 +25,23 @@ ****************************************************************************/ #include +#include #include #include #include #include +#include #include +#include #include #include #include +#ifdef CONFIG_RPTUN +#include +#endif + #include "builtin.h" #include "init.h" #include "property.h" @@ -91,6 +98,12 @@ static int cmd_start_cpu(FAR struct action_manager_s *am, static int cmd_netinit(FAR struct action_manager_s *am, int argc, FAR char **argv); #endif +#ifdef CONFIG_RPTUN +static int cmd_rptun(FAR struct action_manager_s *am, + int argc, FAR char **argv); +#endif +static int cmd_unlink(FAR struct action_manager_s *am, + int argc, FAR char **argv); /**************************************************************************** * Private Data @@ -120,6 +133,10 @@ static const struct cmd_map_s g_builtin[] = {"start", 2, 2, cmd_start}, {"stop", 2, 2, cmd_stop}, {"trigger", 2, 2, cmd_trigger}, +#ifdef CONFIG_RPTUN + {"rptun", 3, 3, cmd_rptun}, +#endif + {"unlink", 2, 2, cmd_unlink}, }; /**************************************************************************** @@ -269,6 +286,63 @@ static int cmd_exec(FAR struct action_manager_s *am, return -EINVAL; } +#ifdef CONFIG_RPTUN +static int cmd_rptun(FAR struct action_manager_s *am, + int argc, FAR char **argv) +{ + int fd; + int ret; + + UNUSED(am); + + fd = open(argv[2], O_WRONLY | O_CLOEXEC); + if (fd < 0) + { + init_err("rptun %s: open '%s' failed: %d", + argv[1], argv[2], errno); + return -errno; + } + + if (!strcmp(argv[1], "start")) + { + ret = ioctl(fd, RPTUNIOC_START, 0); + } + else if (!strcmp(argv[1], "stop")) + { + ret = ioctl(fd, RPTUNIOC_STOP, 0); + } + else + { + init_err("rptun: unknown command '%s'", argv[1]); + ret = -EINVAL; + } + + if (ret < 0) + { + init_err("rptun %s: failed: %d", argv[1], errno); + } + + close(fd); + return ret; +} +#endif + +static int cmd_unlink(FAR struct action_manager_s *am, + int argc, FAR char **argv) +{ + int ret; + + UNUSED(am); + + ret = unlink(argv[1]); + if (ret < 0) + { + init_err("unlink '%s' failed: %d", argv[1], errno); + } + + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ From 517a489d8e5839ad638116f389ad1e34c30c7436 Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Fri, 28 Aug 2026 21:13:53 +0800 Subject: [PATCH 2/3] system/nxinit: fix rptun builtin blocking the action queue RPTUNIOC_START returns the (positive) pid of the rptun kernel thread in async mode (CONFIG_RPTUN_START_SYNC unset). The action engine treats any positive builtin return value as the pid of a spawned child and waitpid()s on it (action.c: "if (ret > 0) pid_running = ret"). The rptun thread is a detached kthread, never a child of init, so that wait blocks the whole action queue forever and "on init" / console never run. Normalize a successful start to 0. Assisted-by: OpenCode:claude-sonnet-5 Signed-off-by: wangjianyu3 --- system/nxinit/builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/nxinit/builtin.c b/system/nxinit/builtin.c index a2bc722bfba..c12f8cef4cb 100644 --- a/system/nxinit/builtin.c +++ b/system/nxinit/builtin.c @@ -323,7 +323,7 @@ static int cmd_rptun(FAR struct action_manager_s *am, } close(fd); - return ret; + return ret < 0 ? ret : 0; } #endif From 7e1e173e0f6effd0286e9969cb76b8d63b9939c7 Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Fri, 28 Aug 2026 21:14:06 +0800 Subject: [PATCH 3/3] system/nxinit: add fallback option to resolve preset service conflict The preset kvdb service defined in parser.c conflicts with user-defined kvdb service in board-level init.rc, causing: Error redefined service 'kvdb' Add SVC_FALLBACK flag and fallback service option. When a service is marked as fallback, it will be silently ignored if another service with the same name already exists. This is the semantic opposite of override: - override: new definition replaces old - fallback: new definition yields to old - old has fallback + new arrives: old yields to new If neither flag is set, duplicate service names still produce EEXIST error as before. Mark the preset kvdb service as fallback so that board-specific init.rc can freely define its own kvdb service without conflict. Signed-off-by: wangjianyu3 --- system/nxinit/service.c | 39 ++++++++++++++++++++++++++++++++++----- system/nxinit/service.h | 4 ++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/system/nxinit/service.c b/system/nxinit/service.c index 8a92bb20baf..d3dbecb1aac 100644 --- a/system/nxinit/service.c +++ b/system/nxinit/service.c @@ -96,6 +96,8 @@ static int option_gentle_kill(FAR struct service_manager_s *sm, int argc, FAR char **argv); static int option_restart_period(FAR struct service_manager_s *sm, int argc, FAR char **argv); +static int option_fallback(FAR struct service_manager_s *sm, + int argc, FAR char **argv); static int option_override(FAR struct service_manager_s *sm, int argc, FAR char **argv); static int option_oneshot(FAR struct service_manager_s *sm, @@ -114,6 +116,7 @@ static const struct cmd_map_s g_option[] = {"class", 2, NXINIT_ACTION_CMD_ARGS_MAX, option_class}, {"gentle_kill", 1, 1, option_gentle_kill}, {"restart_period", 2, 2, option_restart_period}, + {"fallback", 1, 1, option_fallback}, {"override", 1, 1, option_override}, {"oneshot", 1, 1, option_oneshot}, #ifdef CONFIG_BOARDCTL_RESET @@ -131,6 +134,7 @@ static const struct flag_str_s g_flag_str[] = {SVC_GENTLE_KILL, "gentle_kill"}, {SVC_REMOVE, "remove"}, {SVC_SIGKILL, "sigkill"}, + {SVC_FALLBACK, "fallback"}, {SVC_OVERRIDE, "override"}, }; #endif @@ -253,6 +257,16 @@ static int option_restart_period(FAR struct service_manager_s *sm, return 0; } +static int option_fallback(FAR struct service_manager_s *sm, + int argc, FAR char **argv) +{ + FAR struct service_s *s = list_last_entry(&sm->services, struct service_s, + node); + + add_flags(s, SVC_FALLBACK); + return 0; +} + static int option_override(FAR struct service_manager_s *sm, int argc, FAR char **argv) { @@ -279,6 +293,7 @@ static int option_reboot_on_failure(FAR struct service_manager_s *sm, { FAR struct service_s *s = list_last_entry(&sm->services, struct service_s, node); + s->reset_reason = atoi(argv[1]); return 0; } @@ -649,17 +664,31 @@ int init_service_check(FAR const struct parser_s *parser) { if (!strcmp(s->argv[1], tmp->argv[1])) { - if (!check_flags(tmp, SVC_OVERRIDE)) + if (check_flags(tmp, SVC_OVERRIDE)) + { + init_info("override: remove old service '%s'", + s->argv[1]); + add_flags(s, SVC_DISABLED | SVC_REMOVE); + } + else if (check_flags(tmp, SVC_FALLBACK)) + { + init_info("fallback: ignore new service '%s'", + tmp->argv[1]); + add_flags(tmp, SVC_DISABLED | SVC_REMOVE); + } + else if (check_flags(s, SVC_FALLBACK)) + { + init_info("fallback: replace old service '%s'", + s->argv[1]); + add_flags(s, SVC_DISABLED | SVC_REMOVE); + } + else { init_err("Redefined service '%s'", tmp->argv[1]); init_dump_service(s); init_dump_service(tmp); return -EEXIST; } - - init_info("Remove duplicate definition of service '%s'", - tmp->argv[1]); - add_flags(s, SVC_DISABLED | SVC_REMOVE); } } } diff --git a/system/nxinit/service.h b/system/nxinit/service.h index 64520064886..bf93154b656 100644 --- a/system/nxinit/service.h +++ b/system/nxinit/service.h @@ -54,6 +54,10 @@ /* Flags below are new added. */ +/* Fallback: silently ignored if a service with the same name exists */ + +#define SVC_FALLBACK (1 << 28) + /* Override the previous definition for a service with the same name */ #define SVC_OVERRIDE (1 << 29)