Added support for Device.DeviceInfo.Reboots. object

This commit is contained in:
Amin Ben Romdhane 2024-10-15 12:03:06 +02:00
parent 5aa1298df5
commit a813bf2715
5 changed files with 489 additions and 0 deletions

View file

@ -0,0 +1,74 @@
# Design for Reboot Data Model
In TR-181 version 2.18, a new object, Device.DeviceInfo.Reboots, was introduced to track and monitor reboot operations. This object provides details such as reboot reasons, counts, timestamps, and more, offering a comprehensive view of the device's state. It simplifies diagnostics and troubleshooting for applications and processes running on the device.
Currently, there is no standard configuration mapping to this object. However, we propose introducing a custom config called `deviceinfo` to manage this information effectively.
The idea is to maintain a 1-to-1 mapping between the parameters and UCI config. To achieve this, we need to create an `init.d` service script that generates a UCI section each time the boot() function is called. Essentially, when the boot() function is executed, it will check the `/tmp/reset_reason` file for specific markers, such as (reset reason) and (reset triggered), to identify the cause of the last boot. And based on these markers, it will calculate the required counter for data model parameters and commit the changes in `deviceinfo.globals` section. Furthermore, if necessary, it will create a UCI reboot section by checking `deviceinfo.globals.max_reboot_entries` and adjusting the config accordingly.
This approach ensures that the data model maps directly to UCI config as closely as possible, eliminating the need for any adjustments at the data model layer.
## Parameter Mapping Details
- Device.DeviceInfo.Reboots.BootCount: Maps to deviceinfo.globals.boot_count. This value is determined based on the marker (reset triggered: defaultreset) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.CurrentVersionBootCount: Maps to deviceinfo.globals.curr_version_boot_count. This value is determined based on the marker (reset triggered: upgrade) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.WatchdogBootCount: Maps to deviceinfo.globals.watchdog_boot_count. This value is determined based on the marker (reset reason: WATCHDOG) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.ColdBootCount:
- Device.DeviceInfo.Reboots.WarmBootCount:
- Device.DeviceInfo.Reboots.MaxRebootEntries: Maps to deviceinfo.globals.max_reboot_entries. Possible values include {-1, 0, etc..}. Each case will be handled internally by bbfdm and default value is 3 and maximum reboot entry supported is 255.
- Device.DeviceInfo.Reboots.RebootNumberOfEntries: This is an internal bbfdm mechanism used to count the number of reboot entries.
- Device.DeviceInfo.Reboots.RemoveAllReboots(): An internal bbfdm API to remove all reboot sections.
- Device.DeviceInfo.Reboots.Reboot.{i}.: Each reboot entry is stored in a 'reboot' section.
- Device.DeviceInfo.Reboots.Reboot.{i}.Alias: Maps to deviceinfo.reboot[i].alias. This is managed internally by bbfdm.
- Device.DeviceInfo.Reboots.Reboot.{i}.TimeStamp: Maps to deviceinfo.reboot[i].time_stamp. This value is based on system uptime.
- Device.DeviceInfo.Reboots.Reboot.{i}.FirmwareUpdated: Maps to deviceinfo.reboot[i].firmware_updated.
- Device.DeviceInfo.Reboots.Reboot.{i}.Cause: Maps to deviceinfo.reboot[i].cause. Possible values include {LocalReboot, RemoteReboot, FactoryReset, LocalFactoryReset, RemoteFactoryReset}.
- Device.DeviceInfo.Reboots.Reboot.{i}.Reason: Maps to deviceinfo.reboot[i].reason. This value is determined based on the marker (reset reason) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.Reboot.{i}.Remove(): An internal bbfdm API to remove the current 'reboot' section.
## Example Configuration
Below is an example of the configuration file:
```bash
cat /etc/config/deviceinfo
config globals 'globals'
option boot_count '2'
option curr_version_boot_count '4'
option watchdog_boot_count '3'
option cold_boot_count '2'
option warm_boot_count '2'
option max_reboot_entries '3'
config reboot 'reboot_1'
option alias 'cpe-1'
option time_stamp '2024-09-22T20:34:45Z'
option firmware_updated '0'
option cause 'RemoteReboot'
option reason 'REBOOT'
config reboot 'reboot_2'
option alias 'cpe-2'
option time_stamp '2024-09-22T21:55:09Z'
option firmware_updated '0'
option cause 'LocalReboot'
option reason 'POR_RESET'
config reboot 'reboot_3'
option alias 'cpe-3'
option time_stamp '2024-09-23T04:11:24Z'
option firmware_updated '1'
option cause 'LocalReboot'
option reason 'upgrade'
config reboot 'reboot_4'
option alias 'cpe-4'
option time_stamp '2024-09-23T04:15:53Z'
option firmware_updated '0'
option cause 'RemoteFactoryReset'
option reason 'REBOOT'
```

View file

@ -875,6 +875,24 @@ static int browseProcessEntriesInst(struct dmctx *dmctx, DMNODE *parent_node, vo
return 0; return 0;
} }
static int browseDeviceInfoRebootsRebootInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
struct dm_data curr_data = {0};
struct uci_section *s = NULL;
char *inst = NULL;
uci_foreach_sections("deviceinfo", "reboot", s) {
curr_data.config_section = s;
inst = handle_instance(dmctx, parent_node, s, "reboot_instance", "reboot_alias");
if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
break;
}
return 0;
}
/************************************************************* /*************************************************************
* GET & SET PARAM * GET & SET PARAM
**************************************************************/ **************************************************************/
@ -1521,6 +1539,97 @@ static int get_process_state(char* refparam, struct dmctx *ctx, void *data, char
return 0; return 0;
} }
static int get_DeviceInfoReboots_BootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("deviceinfo", "globals", "boot_count", value);
return 0;
}
static int get_DeviceInfoReboots_CurrentVersionBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("deviceinfo", "globals", "curr_version_boot_count", value);
return 0;
}
static int get_DeviceInfoReboots_WatchdogBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("deviceinfo", "globals", "watchdog_boot_count", value);
return 0;
}
static int get_DeviceInfoReboots_ColdBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("deviceinfo", "globals", "cold_boot_count", value);
return 0;
}
static int get_DeviceInfoReboots_WarmBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("deviceinfo", "globals", "warm_boot_count", value);
return 0;
}
static int get_DeviceInfoReboots_MaxRebootEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("deviceinfo", "globals", "max_reboot_entries", "3");
return 0;
}
static int set_DeviceInfoReboots_MaxRebootEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1",NULL}}, 1))
return FAULT_9007;
break;
case VALUESET:
//TODO
break;
}
return 0;
}
static int get_DeviceInfoReboots_RebootNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
int cnt = get_number_of_entries(ctx, data, instance, browseDeviceInfoRebootsRebootInst);
dmasprintf(value, "%d", cnt);
return 0;
}
static int get_DeviceInfoRebootsReboot_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
return bbf_get_alias(ctx, ((struct dm_data *)data)->config_section, "reboot_alias", instance, value);
}
static int set_DeviceInfoRebootsReboot_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
return bbf_set_alias(ctx, ((struct dm_data *)data)->config_section, "reboot_alias", instance, value);
}
static int get_DeviceInfoRebootsReboot_TimeStamp(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "time_stamp", value);
return 0;
}
static int get_DeviceInfoRebootsReboot_FirmwareUpdated(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "firmware_updated", value);
return 0;
}
static int get_DeviceInfoRebootsReboot_Cause(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "cause", value);
return 0;
}
static int get_DeviceInfoRebootsReboot_Reason(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "reason", value);
return 0;
}
/************************************************************* /*************************************************************
* OPERATE COMMANDS * OPERATE COMMANDS
*************************************************************/ *************************************************************/
@ -1694,6 +1803,14 @@ static int get_operate_args_DeviceInfoFirmwareImage_Activate(char *refparam, str
void _exec_reboot(const void *arg1, void *arg2) void _exec_reboot(const void *arg1, void *arg2)
{ {
char config_name[16] = {0};
snprintf(config_name, sizeof(config_name), "%s", "deviceinfo");
// Set last_reboot_cause to 'RemoteReboot' because the upcoming reboot will be initiated by USP Operate
dmuci_set_value(config_name, "globals", "last_reboot_cause", "RemoteReboot");
dmuci_commit_package(config_name);
sleep(3); sleep(3);
dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0); dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0);
sleep(5); // Wait for reboot to happen sleep(5); // Wait for reboot to happen
@ -1701,6 +1818,10 @@ void _exec_reboot(const void *arg1, void *arg2)
dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0); dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0);
sleep(5); // Wait for reboot sleep(5); // Wait for reboot
BBF_ERR("Reboot call failed!!!"); BBF_ERR("Reboot call failed!!!");
// Set last_reboot_cause to empty because there is a problem in the system reboot
dmuci_set_value(config_name, "globals", "last_reboot_cause", "");
dmuci_commit_package(config_name);
} }
static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
@ -1810,6 +1931,22 @@ static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx
return res ? USP_FAULT_COMMAND_FAILURE : 0; return res ? USP_FAULT_COMMAND_FAILURE : 0;
} }
static int operate_DeviceInfoReboots_RemoveAllReboots(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
struct uci_section *s = NULL, *tmp_s = NULL;
uci_foreach_sections_safe("deviceinfo", "reboot", tmp_s, s) {
dmuci_delete_by_section(s, NULL, NULL);
}
return 0;
}
static int operate_DeviceInfoRebootsReboot_Remove(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
return 0;
}
/********************************************************************************************************************************** /**********************************************************************************************************************************
* OBJ & LEAF DEFINITION * OBJ & LEAF DEFINITION
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
@ -1822,6 +1959,7 @@ DMOBJ tDeviceInfoObj[] = {
{"Processor", &DMREAD, NULL, NULL, NULL, browseDeviceInfoProcessorInst, NULL, NULL, NULL, tDeviceInfoProcessorParams, NULL, BBFDM_BOTH, NULL}, {"Processor", &DMREAD, NULL, NULL, NULL, browseDeviceInfoProcessorInst, NULL, NULL, NULL, tDeviceInfoProcessorParams, NULL, BBFDM_BOTH, NULL},
{"SupportedDataModel", &DMREAD, NULL, NULL, NULL, browseDeviceInfoSupportedDataModelInst, NULL, NULL, NULL, tDeviceInfoSupportedDataModelParams, NULL, BBFDM_CWMP, NULL}, {"SupportedDataModel", &DMREAD, NULL, NULL, NULL, browseDeviceInfoSupportedDataModelInst, NULL, NULL, NULL, tDeviceInfoSupportedDataModelParams, NULL, BBFDM_CWMP, NULL},
{"FirmwareImage", &DMREAD, NULL, NULL, "file:/usr/libexec/rpcd/fwbank", browseDeviceInfoFirmwareImageInst, NULL, NULL, NULL, tDeviceInfoFirmwareImageParams, NULL, BBFDM_BOTH, NULL}, {"FirmwareImage", &DMREAD, NULL, NULL, "file:/usr/libexec/rpcd/fwbank", browseDeviceInfoFirmwareImageInst, NULL, NULL, NULL, tDeviceInfoFirmwareImageParams, NULL, BBFDM_BOTH, NULL},
{"Reboots", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoRebootsObj, tDeviceInfoRebootsParams, NULL, BBFDM_USP, NULL},
{0} {0}
}; };
@ -1934,3 +2072,35 @@ DMLEAF tDeviceInfoFirmwareImageParams[] = {
{"Activate()", &DMASYNC, DMT_COMMAND, get_operate_args_DeviceInfoFirmwareImage_Activate, operate_DeviceInfoFirmwareImage_Activate, BBFDM_USP}, {"Activate()", &DMASYNC, DMT_COMMAND, get_operate_args_DeviceInfoFirmwareImage_Activate, operate_DeviceInfoFirmwareImage_Activate, BBFDM_USP},
{0} {0}
}; };
/* *** Device.DeviceInfo.Reboots. *** */
DMOBJ tDeviceInfoRebootsObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"Reboot", &DMREAD, NULL, NULL, NULL, browseDeviceInfoRebootsRebootInst, NULL, NULL, NULL, tDeviceInfoRebootsRebootParams, NULL, BBFDM_USP, NULL},
{0}
};
DMLEAF tDeviceInfoRebootsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"BootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_BootCount, NULL, BBFDM_USP},
{"CurrentVersionBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_CurrentVersionBootCount, NULL, BBFDM_USP},
{"WatchdogBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_WatchdogBootCount, NULL, BBFDM_USP},
{"ColdBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_ColdBootCount, NULL, BBFDM_USP},
{"WarmBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_WarmBootCount, NULL, BBFDM_USP},
{"MaxRebootEntries", &DMWRITE, DMT_INT, get_DeviceInfoReboots_MaxRebootEntries, set_DeviceInfoReboots_MaxRebootEntries, BBFDM_USP},
{"RebootNumberOfEntries", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_RebootNumberOfEntries, NULL, BBFDM_USP},
{"RemoveAllReboots()", &DMASYNC, DMT_COMMAND, NULL, operate_DeviceInfoReboots_RemoveAllReboots, BBFDM_USP},
{0}
};
/* *** Device.DeviceInfo.Reboots.Reboot.{i}. *** */
DMLEAF tDeviceInfoRebootsRebootParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Alias", &DMWRITE, DMT_STRING, get_DeviceInfoRebootsReboot_Alias, set_DeviceInfoRebootsReboot_Alias, BBFDM_USP},
{"TimeStamp", &DMREAD, DMT_TIME, get_DeviceInfoRebootsReboot_TimeStamp, NULL, BBFDM_USP},
{"FirmwareUpdated", &DMREAD, DMT_BOOL, get_DeviceInfoRebootsReboot_FirmwareUpdated, NULL, BBFDM_USP},
{"Cause", &DMREAD, DMT_STRING, get_DeviceInfoRebootsReboot_Cause, NULL, BBFDM_USP},
{"Reason", &DMREAD, DMT_STRING, get_DeviceInfoRebootsReboot_Reason, NULL, BBFDM_USP},
{"Remove()", &DMASYNC, DMT_COMMAND, NULL, operate_DeviceInfoRebootsReboot_Remove, BBFDM_USP},
{0}
};

View file

@ -25,6 +25,9 @@ extern DMLEAF tDeviceInfoProcessStatusProcessParams[];
extern DMLEAF tDeviceInfoProcessorParams[]; extern DMLEAF tDeviceInfoProcessorParams[];
extern DMLEAF tDeviceInfoSupportedDataModelParams[]; extern DMLEAF tDeviceInfoSupportedDataModelParams[];
extern DMLEAF tDeviceInfoFirmwareImageParams[]; extern DMLEAF tDeviceInfoFirmwareImageParams[];
extern DMOBJ tDeviceInfoRebootsObj[];
extern DMLEAF tDeviceInfoRebootsParams[];
extern DMLEAF tDeviceInfoRebootsRebootParams[];
void _exec_reboot(const void *arg1, void *arg2); void _exec_reboot(const void *arg1, void *arg2);
#endif #endif

View file

@ -0,0 +1,36 @@
config globals 'globals'
option boot_count '2'
option curr_version_boot_count '4'
option watchdog_boot_count '3'
option cold_boot_count '2'
option warm_boot_count '2'
option max_reboot_entries '3'
config reboot
option alias 'cpe-1'
option time_stamp '2024-09-22T20:34:45Z'
option firmware_updated '0'
option cause 'RemoteReboot'
option reason 'REBOOT'
config reboot
option alias 'cpe-2'
option time_stamp '2024-09-22T21:55:09Z'
option firmware_updated '0'
option cause 'LocalReboot'
option reason 'POR_RESET'
config reboot
option alias 'cpe-3'
option time_stamp '2024-09-23T04:11:24Z'
option firmware_updated '1'
option cause 'LocalReboot'
option reason 'upgrade'
config reboot
option alias 'cpe-4'
option time_stamp '2024-09-23T04:15:53Z'
option firmware_updated '0'
option cause 'RemoteFactoryReset'
option reason 'REBOOT'

View file

@ -0,0 +1,206 @@
#!/bin/sh
# Script to handle Reboots Object
#
# Copyright © 2024 IOPSYS Software Solutions AB
# Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
#
. /lib/functions.sh
RESET_REASON_PATH="/tmp/reset_reason"
MAX_RETRIES=3
RETRY_DELAY=1
log() {
echo "$@" | logger -t bbf_reboot -p info
}
reset_option_counter() {
local option_name=$1
local option_value=$2
uci_set "deviceinfo" "globals" "${option_name}" "${option_value}"
}
increment_option_counter() {
local option_name=$1
local option_value=$(uci_get "deviceinfo" "globals" "${option_name}" "0")
local counter=$((option_value + 1))
uci_set "deviceinfo" "globals" "${option_name}" "$counter"
}
get_boot_trigger() {
local trigger
trigger=$(grep "triggered" ${RESET_REASON_PATH} | cut -d ':' -f2 | xargs)
echo "${trigger}"
}
get_boot_reason() {
local reason
reason=$(grep "reason" ${RESET_REASON_PATH} | cut -d ':' -f2 | xargs)
echo "${reason}"
}
calculate_boot_time() {
# Get current time and uptime in seconds
local current_time uptime_seconds boot_time boot_time_formatted
current_time=$(date +%s)
uptime_seconds=$(awk '{print $1}' /proc/uptime | cut -d. -f1)
# Calculate the boot time by subtracting the uptime from the current time
boot_time=$((current_time - uptime_seconds))
# Convert the boot time to a human-readable format
boot_time_formatted=$(date -d "@$boot_time" +"%Y-%m-%dT%H:%M:%SZ")
echo "${boot_time_formatted}"
}
boot_reason_message() {
# Generate a human-readable message based on the boot reason and trigger
local trigger reason
trigger=$(get_boot_trigger)
if [ -n "${trigger}" ]; then
case "${trigger}" in
"defaultreset")
echo "FACTORY RESET"
;;
"upgrade")
echo "FIRMWARE UPGRADE"
;;
*)
echo "${trigger}"
;;
esac
else
reason=$(get_boot_reason)
case "${reason}" in
"POR_RESET")
echo "POWER ON RESET"
;;
*)
echo "${reason}"
;;
esac
fi
}
create_reboot_section() {
local trigger=$1
local reboot_sec
reboot_sec="reboot_$(date +%Y%m%d%H%M%S)"
uci_add "deviceinfo" "reboot" "${reboot_sec}"
uci_set "deviceinfo" "${reboot_sec}" "time_stamp" "$(calculate_boot_time)"
if [ "${trigger}" = "upgrade" ]; then
uci_set "deviceinfo" "${reboot_sec}" "firmware_updated" "1"
else
uci_set "deviceinfo" "${reboot_sec}" "firmware_updated" "0"
fi
if [ "${trigger}" = "defaultreset" ]; then
uci_set "deviceinfo" "${reboot_sec}" "cause" "FactoryReset"
else
local last_reboot_cause
last_reboot_cause=$(uci_get "deviceinfo" "globals" "last_reboot_cause" "LocalReboot")
uci_set "deviceinfo" "${reboot_sec}" "cause" "${last_reboot_cause}"
uci_set "deviceinfo" "globals" "last_reboot_cause" ""
fi
uci_set "deviceinfo" "${reboot_sec}" "reason" "$(boot_reason_message)"
}
handle_reboot_action() {
local trigger reason max_reboot_entries retry_count reboot_sec_num
retry_count=0
# Retry fetching the reset reason file
while [ ! -f "${RESET_REASON_PATH}" ] && [ $retry_count -lt $MAX_RETRIES ]; do
log "Warning: '${RESET_REASON_PATH}' not found. Attempt $((retry_count + 1)) of ${MAX_RETRIES}"
sleep $RETRY_DELAY
retry_count=$((retry_count + 1))
done
if [ ! -f "${RESET_REASON_PATH}" ]; then
log "Error: '${RESET_REASON_PATH}' is not generated after ${MAX_RETRIES} attempts!!!"
return 1
fi
uci_load "deviceinfo"
trigger=$(get_boot_trigger)
reason=$(get_boot_reason)
# Reset or increment boot counter based on trigger
if [ "${trigger}" = "defaultreset" ]; then
## Reset all counters ##
reset_option_counter "boot_count" "1"
reset_option_counter "curr_version_boot_count" "0"
reset_option_counter "watchdog_boot_count" "0"
reset_option_counter "cold_boot_count" "0"
reset_option_counter "warm_boot_count" "0"
else
# Incrementing boot counter
increment_option_counter "boot_count"
fi
# Reset or increment current version boot counter based on trigger
if [ "${trigger}" = "upgrade" ]; then
# Resetting current version boot counter
reset_option_counter "curr_version_boot_count" "1"
else
# Incrementing current version boot counter
increment_option_counter "curr_version_boot_count"
fi
# Increment watchdog boot counter if the reason indicates a watchdog reset
if echo "${reason}" | grep -qi "watchdog"; then
# Incrementing watchdog boot counter
increment_option_counter "watchdog_boot_count"
fi
# Increment cold or warm boot counter based on the reason
if [ "${reason}" = "POR_RESET" ]; then
increment_option_counter "cold_boot_count"
else
increment_option_counter "warm_boot_count"
fi
# Get the max reboot entries
max_reboot_entries=$(uci_get "deviceinfo" "globals" "max_reboot_entries" "3")
if [ "${max_reboot_entries}" -eq 0 ]; then
# Commit the UCI changes to persist the configuration
uci_commit "deviceinfo"
return 0
fi
if [ $max_reboot_entries -gt 0 ]; then
# Calculate the number of reboot sections in the config
reboot_sec_num=$(uci -q show deviceinfo | grep "=reboot" | wc -l)
# Delete excess reboot sections if they exceed the max reboot entries
if [ "${reboot_sec_num}" -ge "${max_reboot_entries}" ]; then
local diff=$((reboot_sec_num - max_reboot_entries + 1))
for i in $(seq 1 $diff); do
uci_remove "deviceinfo" "@reboot[0]"
done
fi
fi
# Create a new reboot section with the current boot information
create_reboot_section "${trigger}"
# Commit the UCI changes to persist the configuration
uci_commit "deviceinfo"
}
# Run the main function
handle_reboot_action
exit 0