system/nxinit: Add NuttX Init
This component (abbreviated as "NxInit") is specifically developed
for NuttX and intended for system initialization. While we have
adopted the Android Init Language among various syntax options,
this is a brand-new implementation—it is not a port or variant of
Android Init.
Refer to the implementation of Android Init Language, consists of five broad
classes of statements: Actions, Commands, Services, Options, and Imports.
Actions support two types of triggers: event and action. Action triggers also
support runtime triggering. Services support lifecycle management, including
automatic restart (at specified intervals), and starting/stopping
individually or by class. Import supports files or directories, and we may
add a static method in the future. The following are some differences:
1. The Android Init Language treats lines starting with `#` as comments,
while we use a preprocessor to handle comments.
2. For action commands, we can omit "exec" and directly execute
built-in apps or nsh builtins.
3. Regarding the property service, users can either adapt it by self or
directly use the preset NVS-based properties.
4. Only part of standard action commands and service options are
implemented currlently.
To enable system/nxinit:
```diff
-CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_ENTRYPOINT="init_main"
+CONFIG_SYSTEM_NXINIT=y
```
For format and additional details, refer to:
https://android.googlesource.com/platform/system/core/+/
master/init/README.md
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
|
|
|
/****************************************************************************
|
|
|
|
|
* apps/system/nxinit/parser.h
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*
|
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
|
* under the License.
|
|
|
|
|
*
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#ifndef __APPS_SYSTEM_NXINIT_PARSER_H
|
|
|
|
|
#define __APPS_SYSTEM_NXINIT_PARSER_H
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
* Included Files
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
system/nxinit: add cmocka unit tests for parser/action/service
Add a test/ subdirectory (mirroring apps/system/uorb/test/) with
cmocka-based unit tests covering the NxInit logic most prone to
regression:
- init_parse_arguments(): plain/quoted arguments, "--" separator vs.
"--option" long options (regression coverage for a previously fixed
bug), argv-capacity truncation (asserting the exact folded contents
of the last slot, not just its presence).
- init_parse_config_file()/init_parse_config_lines()/
init_parse_config_buffer(): section routing, blank/whitespace-only
line skipping, unknown-section rejection, over-length line rejection,
and a line straddling two read-buffer refills, exercised through both
the file-based and buffer-based entry points.
- Action event matching: exact match, invert (!=), fnmatch wildcards,
and AND semantics across multiple events per action.
- Service conflict detection: duplicate service name rejection,
override replacing an earlier duplicate, and the SERVICE_ARGS_MAX
boundary built dynamically from CONFIG_SYSTEM_NXINIT_SERVICE_ARGS_MAX
rather than a hardcoded value.
Test sources compile action.c/parser.c/service.c a second time into a
separate nxinit_unit_test program, gated behind new
CONFIG_SYSTEM_NXINIT_TEST (depends on TESTING_CMOCKA); the default init
program is unaffected. The CMake path builds a dedicated
nxinit_unit_test target (with test/test_nxinit.c placed first in SRCS
so nuttx_add_application() renames its main() correctly); the Make path
appends the test sources into the shared CSRCS list.
Supporting bits required to make the suite exercise the real code:
- init_parse_config_buffer() is declared in parser.h and made
non-static so the buffer-based boundary test can call it directly,
alongside the existing init_parse_config_file() entry point.
- CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX default is raised from 1 to 2
so an action can carry more than one event ("on evA && evB"), which
the multi-event AND-semantics test exercises; a single event slot
made that test dead code.
- CONFIG_SYSTEM_NXINIT_TEST_STACKSIZE defaults to 8192: several parser
test cases build multi-hundred-byte stack buffers on top of cmocka's
own overhead, and the previous DEFAULT_TASK_STACKSIZE (2048)
overflowed the test task's stack silently on real hardware (no crash
dump, no watchdog reset, output just stopped) partway through the
suite.
Testing:
Built via `make CROSSDEV=riscv-none-elf-` for
esp32p4-pico-wifi-wareshare:nsh (CONFIG_SYSTEM_NXINIT_TEST=y) and ran
nxinit_unit_test on real esp32p4-pico-wifi-wareshare hardware over
UART:
nsh> nxinit_unit_test
[==========] nxinit_tests: Running 18 test(s).
...
[==========] nxinit_tests: 18 test(s) run.
[ PASSED ] 18 test(s).
nxstyle clean on all touched files.
Assisted-by: GitHubCopilot:claude-sonnet-5
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2026-08-27 10:50:26 +08:00
|
|
|
#include <stddef.h>
|
system/nxinit: Add NuttX Init
This component (abbreviated as "NxInit") is specifically developed
for NuttX and intended for system initialization. While we have
adopted the Android Init Language among various syntax options,
this is a brand-new implementation—it is not a port or variant of
Android Init.
Refer to the implementation of Android Init Language, consists of five broad
classes of statements: Actions, Commands, Services, Options, and Imports.
Actions support two types of triggers: event and action. Action triggers also
support runtime triggering. Services support lifecycle management, including
automatic restart (at specified intervals), and starting/stopping
individually or by class. Import supports files or directories, and we may
add a static method in the future. The following are some differences:
1. The Android Init Language treats lines starting with `#` as comments,
while we use a preprocessor to handle comments.
2. For action commands, we can omit "exec" and directly execute
built-in apps or nsh builtins.
3. Regarding the property service, users can either adapt it by self or
directly use the preset NVS-based properties.
4. Only part of standard action commands and service options are
implemented currlently.
To enable system/nxinit:
```diff
-CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_ENTRYPOINT="init_main"
+CONFIG_SYSTEM_NXINIT=y
```
For format and additional details, refer to:
https://android.googlesource.com/platform/system/core/+/
master/init/README.md
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
* Public Types
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
struct parser_s
|
|
|
|
|
{
|
|
|
|
|
FAR const char *key;
|
|
|
|
|
|
|
|
|
|
CODE int (*parse)(FAR const struct parser_s *, bool, FAR char *);
|
|
|
|
|
CODE int (*check)(FAR const struct parser_s *);
|
|
|
|
|
|
|
|
|
|
/* Type
|
|
|
|
|
* a. struct action_manager_s
|
|
|
|
|
* b. struct service_manager_s
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
FAR void *priv;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
* Public Function Prototypes
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
int init_parse_arguments(FAR char *buf, bool dup, int argc, FAR char **argv);
|
2025-10-22 16:04:09 +08:00
|
|
|
int init_parse_configs(FAR const struct parser_s *parser);
|
system/nxinit: Add NuttX Init
This component (abbreviated as "NxInit") is specifically developed
for NuttX and intended for system initialization. While we have
adopted the Android Init Language among various syntax options,
this is a brand-new implementation—it is not a port or variant of
Android Init.
Refer to the implementation of Android Init Language, consists of five broad
classes of statements: Actions, Commands, Services, Options, and Imports.
Actions support two types of triggers: event and action. Action triggers also
support runtime triggering. Services support lifecycle management, including
automatic restart (at specified intervals), and starting/stopping
individually or by class. Import supports files or directories, and we may
add a static method in the future. The following are some differences:
1. The Android Init Language treats lines starting with `#` as comments,
while we use a preprocessor to handle comments.
2. For action commands, we can omit "exec" and directly execute
built-in apps or nsh builtins.
3. Regarding the property service, users can either adapt it by self or
directly use the preset NVS-based properties.
4. Only part of standard action commands and service options are
implemented currlently.
To enable system/nxinit:
```diff
-CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_ENTRYPOINT="init_main"
+CONFIG_SYSTEM_NXINIT=y
```
For format and additional details, refer to:
https://android.googlesource.com/platform/system/core/+/
master/init/README.md
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
|
|
|
int init_parse_config_file(FAR const struct parser_s *parser,
|
|
|
|
|
FAR const char *file);
|
system/nxinit: add cmocka unit tests for parser/action/service
Add a test/ subdirectory (mirroring apps/system/uorb/test/) with
cmocka-based unit tests covering the NxInit logic most prone to
regression:
- init_parse_arguments(): plain/quoted arguments, "--" separator vs.
"--option" long options (regression coverage for a previously fixed
bug), argv-capacity truncation (asserting the exact folded contents
of the last slot, not just its presence).
- init_parse_config_file()/init_parse_config_lines()/
init_parse_config_buffer(): section routing, blank/whitespace-only
line skipping, unknown-section rejection, over-length line rejection,
and a line straddling two read-buffer refills, exercised through both
the file-based and buffer-based entry points.
- Action event matching: exact match, invert (!=), fnmatch wildcards,
and AND semantics across multiple events per action.
- Service conflict detection: duplicate service name rejection,
override replacing an earlier duplicate, and the SERVICE_ARGS_MAX
boundary built dynamically from CONFIG_SYSTEM_NXINIT_SERVICE_ARGS_MAX
rather than a hardcoded value.
Test sources compile action.c/parser.c/service.c a second time into a
separate nxinit_unit_test program, gated behind new
CONFIG_SYSTEM_NXINIT_TEST (depends on TESTING_CMOCKA); the default init
program is unaffected. The CMake path builds a dedicated
nxinit_unit_test target (with test/test_nxinit.c placed first in SRCS
so nuttx_add_application() renames its main() correctly); the Make path
appends the test sources into the shared CSRCS list.
Supporting bits required to make the suite exercise the real code:
- init_parse_config_buffer() is declared in parser.h and made
non-static so the buffer-based boundary test can call it directly,
alongside the existing init_parse_config_file() entry point.
- CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX default is raised from 1 to 2
so an action can carry more than one event ("on evA && evB"), which
the multi-event AND-semantics test exercises; a single event slot
made that test dead code.
- CONFIG_SYSTEM_NXINIT_TEST_STACKSIZE defaults to 8192: several parser
test cases build multi-hundred-byte stack buffers on top of cmocka's
own overhead, and the previous DEFAULT_TASK_STACKSIZE (2048)
overflowed the test task's stack silently on real hardware (no crash
dump, no watchdog reset, output just stopped) partway through the
suite.
Testing:
Built via `make CROSSDEV=riscv-none-elf-` for
esp32p4-pico-wifi-wareshare:nsh (CONFIG_SYSTEM_NXINIT_TEST=y) and ran
nxinit_unit_test on real esp32p4-pico-wifi-wareshare hardware over
UART:
nsh> nxinit_unit_test
[==========] nxinit_tests: Running 18 test(s).
...
[==========] nxinit_tests: 18 test(s) run.
[ PASSED ] 18 test(s).
nxstyle clean on all touched files.
Assisted-by: GitHubCopilot:claude-sonnet-5
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2026-08-27 10:50:26 +08:00
|
|
|
int init_parse_config_buffer(FAR const struct parser_s *parser,
|
|
|
|
|
FAR const char *buf, size_t len);
|
|
|
|
|
|
system/nxinit: Add NuttX Init
This component (abbreviated as "NxInit") is specifically developed
for NuttX and intended for system initialization. While we have
adopted the Android Init Language among various syntax options,
this is a brand-new implementation—it is not a port or variant of
Android Init.
Refer to the implementation of Android Init Language, consists of five broad
classes of statements: Actions, Commands, Services, Options, and Imports.
Actions support two types of triggers: event and action. Action triggers also
support runtime triggering. Services support lifecycle management, including
automatic restart (at specified intervals), and starting/stopping
individually or by class. Import supports files or directories, and we may
add a static method in the future. The following are some differences:
1. The Android Init Language treats lines starting with `#` as comments,
while we use a preprocessor to handle comments.
2. For action commands, we can omit "exec" and directly execute
built-in apps or nsh builtins.
3. Regarding the property service, users can either adapt it by self or
directly use the preset NVS-based properties.
4. Only part of standard action commands and service options are
implemented currlently.
To enable system/nxinit:
```diff
-CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_ENTRYPOINT="init_main"
+CONFIG_SYSTEM_NXINIT=y
```
For format and additional details, refer to:
https://android.googlesource.com/platform/system/core/+/
master/init/README.md
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
|
|
|
#endif
|