diff --git a/src/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh b/src/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh index 4e66a73..6e1e4ff 100755 --- a/src/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh +++ b/src/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh @@ -2,10 +2,11 @@ # Script to activate image in specified time. # -# Copyright © 2022 IOPSYS Software Solutions AB +# Copyright © 2022 - 2025 IOPSYS Software Solutions AB # Author: Amin Ben Romdhane # +. /usr/share/libubox/jshn.sh ROOT="$(dirname "${0}")" CHECK_IDLE_FILE="${ROOT}/bbf_check_idle.sh" @@ -18,8 +19,10 @@ log() { } activate_and_reboot_device() { - local bank_id="${1}" - local keep_config="${2:-1}" + local bank_id="${1}"; shift + local keep_settings="${1}"; shift + local keep_opconf="${1}"; shift + local config_scope="${1}"; shift local success success=$(ubus call fwbank set_bootbank "{'bank':${bank_id}}" | jsonfilter -e @.success) @@ -28,12 +31,15 @@ activate_and_reboot_device() { exit 1 fi - if [ "${keep_config}" = "1" ]; then - success=$(/etc/sysmngr/fwbank call copy_config 2> /dev/null | jsonfilter -e @.success) - if [ "${success}" != "true" ]; then - log "Can't copy config" - exit 1 - fi + json_init + [ -n "${keep_settings}" ] && json_add_boolean "keep_settings" "${keep_settings}" + [ -n "${keep_opconf}" ] && json_add_boolean "keep_opconf" "${keep_opconf}" + [ -n "${config_scope}" ] && json_add_string "config_scope" "${config_scope}" + + success=$(json_dump| /etc/sysmngr/fwbank call copy_config 2> /dev/null | jsonfilter -e @.success) + if [ "${success}" != "true" ]; then + log "Can't copy config" + exit 1 fi log "The device will restart after a few seconds" @@ -45,16 +51,18 @@ handle_whenidle_mode() { local bank_id="${1}" local end_time="${2}" local force_activation="${3}" - local keep_config="${4}" + local keep_settings="${4}" + local keep_opconf="${5}" + local config_scope="${6}" local diff=0 [ ! -x "${CHECK_IDLE_FILE}" ] && { - activate_and_reboot_device "${bank_id}" "${keep_config}" + activate_and_reboot_device "${bank_id}" "${keep_settings}" "${keep_opconf}" "${config_scope}" } sh "${CHECK_IDLE_FILE}" if [ "$?" = "0" ]; then - activate_and_reboot_device "${bank_id}" "${keep_config}" + activate_and_reboot_device "${bank_id}" "${keep_settings}" "${keep_opconf}" "${config_scope}" else [ "${end_time}" -gt "$((diff + RETRY_TIME))" ] && { sleep "${RETRY_TIME}" @@ -66,7 +74,7 @@ handle_whenidle_mode() { while [ "${end_time}" -gt "${diff}" ]; do sh "${CHECK_IDLE_FILE}" if [ "$?" = "0" ]; then - activate_and_reboot_device "${bank_id}" "${keep_config}" + activate_and_reboot_device "${bank_id}" "${keep_settings}" "${keep_opconf}" "${config_scope}" else if [ "${end_time}" -gt "$((diff + RETRY_TIME))" ]; then @@ -81,7 +89,7 @@ handle_whenidle_mode() { done [ "${force_activation}" = "1" ] && { - activate_and_reboot_device "${bank_id}" "${keep_config}" + activate_and_reboot_device "${bank_id}" "${keep_settings}" "${keep_opconf}" "${config_scope}" } } @@ -92,7 +100,7 @@ handle_confirmation_needed_mode() { } ######################## main ######################## -if [ "$#" -lt "6" ]; then +if [ "$#" -lt "8" ]; then log "Invalid inputs [$*]" exit 1 fi @@ -103,14 +111,16 @@ ENDTIME="${1}"; shift LASTWINDOW="${1}"; shift MAXRETRIES="${1}"; shift KEEPCONFIG="${1}"; shift +KEEPOPCONF="${1}"; shift +CONFIGSCOPE="${1}"; shift MSG="$*" if [ "${MODE}" = "Immediately" ] || [ "${MODE}" = "AnyTime" ]; then - activate_and_reboot_device "${BANKID}" "${KEEPCONFIG}" + activate_and_reboot_device "${BANKID}" "${KEEPCONFIG}" "${KEEPOPCONF}" "${CONFIGSCOPE}" elif [ "${MODE}" = "WhenIdle" ]; then - handle_whenidle_mode "${BANKID}" "${ENDTIME}" "${LASTWINDOW}" "${KEEPCONFIG}" + handle_whenidle_mode "${BANKID}" "${ENDTIME}" "${LASTWINDOW}" "${KEEPCONFIG}" "${KEEPOPCONF}" "${CONFIGSCOPE}" elif [ "${MODE}" = "ConfirmationNeeded" ]; then - handle_confirmation_needed_mode "${BANKID}" "${ENDTIME}" "${LASTWINDOW}" "${MAXRETRIES}" "${KEEPCONFIG}" "${MSG}" + handle_confirmation_needed_mode "${BANKID}" "${ENDTIME}" "${LASTWINDOW}" "${MAXRETRIES}" "${KEEPCONFIG}" "${KEEPOPCONF}" "${CONFIGSCOPE}" "${MSG}" else log "[${MODE}] mode is not supported" exit 1 diff --git a/src/fw_images.c b/src/fw_images.c index 7203d4d..4f14289 100644 --- a/src/fw_images.c +++ b/src/fw_images.c @@ -30,12 +30,13 @@ struct fw_download_data { char *obj_path; char *commandKey; char *keep_config; + char *keep_opconf; + char *config_scope; char *requestor; }; #define CRONTABS_ROOT "/etc/crontabs/root" #define ACTIVATE_HANDLER_FILE "/usr/share/bbfdm/scripts/bbf_activate_handler.sh" -#define COPY_CONFIG_CMD "/etc/sysmngr/fwbank call copy_config 2> /dev/null" #define MAX_TIME_WINDOW 5 /************************************************************* @@ -111,11 +112,39 @@ static char *get_fwbank_bank_id(const char *option_name) return bank_id ? bank_id : ""; } -static void fwbank_copy_config(void) +static void fwbank_copy_config(const char *keep_settings, const char *keep_opconf, const char *config_scope) { - char output[64] = {0}; + char cmd[256] = {0}; + struct blob_buf bb = {0}; + bool res = false; + char *str = NULL; - run_cmd(COPY_CONFIG_CMD, output, sizeof(output)); + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + if (DM_STRLEN(keep_settings) != 0) { + string_to_bool(keep_settings, &res); + blobmsg_add_u8(&bb, "keep_settings", res); + } + + if (DM_STRLEN(keep_opconf) != 0) { + string_to_bool(keep_opconf, &res); + blobmsg_add_u8(&bb, "keep_opconf", res); + } + + if (DM_STRLEN(config_scope) != 0) { + blobmsg_add_string(&bb, "config_scope", config_scope); + } + + str = blobmsg_format_json(bb.head, true); + if (str) { + char output[256] = {0}; + snprintf(cmd, sizeof(cmd), "echo '%s' |/etc/sysmngr/fwbank call copy_config 2> /dev/null", str); + run_cmd(cmd, output, sizeof(output)); + FREE(str); + } else { + BBFDM_ERR("Failed to get json from blob"); + } } static bool fwbank_set_bootbank(const char *bank_id) @@ -123,17 +152,41 @@ static bool fwbank_set_bootbank(const char *bank_id) return sysmngr_fwbank_set_bootbank((uint32_t)DM_STRTOUL(bank_id)); } -static bool fwbank_upgrade(const char *path, bool activate, const char *bank_id, const char *keep_settings) +static bool fwbank_upgrade(const char *fw_path, struct fw_download_data *dw_data) { + json_object *jp_in = NULL; json_object *json_obj = NULL; - bool res = true; + bool res = false; - if (activate == false) { - dmubus_call_blocking("fwbank", "upgrade", UBUS_ARGS{{"path", path, String}, {"auto_activate", "0", Boolean}, {"bank", bank_id, Integer}, {"keep_settings", "0", Boolean}}, 4, &json_obj); - } else { - dmubus_call_blocking("fwbank", "upgrade", UBUS_ARGS{{"path", path, String}, {"auto_activate", "1", Boolean}, {"bank", bank_id, Integer}, {"keep_settings", keep_settings, Boolean}}, 4, &json_obj); + jp_in = json_object_new_object(); + if (jp_in == NULL) { + BBFDM_ERR("Failed to create json object"); + return false; } + json_object_object_add(jp_in, "path", json_object_new_string(fw_path)); + json_object_object_add(jp_in, "bank", json_object_new_int(strtol(dw_data->bank_id, NULL, 10))); + if (DM_STRLEN(dw_data->auto_activate) != 0) { + string_to_bool(dw_data->auto_activate, &res); + json_object_object_add(jp_in, "auto_activate", json_object_new_boolean(res)); + } + + if (DM_STRLEN(dw_data->keep_config) != 0) { + string_to_bool(dw_data->keep_config, &res); + json_object_object_add(jp_in, "keep_settings", json_object_new_boolean(res)); + } + + if (DM_STRLEN(dw_data->keep_opconf) != 0) { + string_to_bool(dw_data->keep_opconf, &res); + json_object_object_add(jp_in, "keep_opconf", json_object_new_boolean(res)); + } + + if (DM_STRLEN(dw_data->config_scope) != 0) { + json_object_object_add(jp_in, "config_scope", json_object_new_string(dw_data->config_scope)); + } + + res = true; + dmubus_call_blob_blocking("fwbank", "upgrade", jp_in, &json_obj); if (json_obj) { char *result = dmjson_get_value(json_obj, 1, "result"); res = (DM_LSTRCMP(result, "ok") == 0) ? true : false; @@ -142,6 +195,9 @@ static bool fwbank_upgrade(const char *path, bool activate, const char *bank_id, if (json_obj != NULL) json_object_put(json_obj); + if (jp_in) + json_object_put(jp_in); + return res; } @@ -278,10 +334,8 @@ static int bbf_fw_image_download(struct ubus_context *ctx, struct fw_download_da goto end; } - string_to_bool(dw_data->auto_activate, &activate); - // Apply Firmware Image - if (!fwbank_upgrade(fw_image_path, activate, dw_data->bank_id, DM_STRLEN(dw_data->keep_config) ? dw_data->keep_config : "1")) { + if (!fwbank_upgrade(fw_image_path, dw_data)) { res = 1; snprintf(fault_msg, sizeof(fault_msg), "Internal error occurred when applying the firmware"); goto end; @@ -293,7 +347,6 @@ static int bbf_fw_image_download(struct ubus_context *ctx, struct fw_download_da }; dmubus_wait_for_event("sysupgrade", 120, &ev_data, dmubus_receive_sysupgrade, NULL); - if (ev_data.status == false) { res = 1; snprintf(fault_msg, sizeof(fault_msg), "Failed to apply the downloaded image file"); @@ -301,6 +354,7 @@ static int bbf_fw_image_download(struct ubus_context *ctx, struct fw_download_da } // Schedule a device Reboot, if auto activation is true + string_to_bool(dw_data->auto_activate, &activate); if (activate) { bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); } @@ -545,6 +599,8 @@ static operation_args firmware_image_download_args = { "CheckSum", #ifdef SYSMNGR_VENDOR_EXTENSIONS CUSTOM_PREFIX"KeepConfig", + CUSTOM_PREFIX"KeepOpConf", + CUSTOM_PREFIX"ConfigScope", #endif NULL } @@ -595,6 +651,8 @@ static int operate_DeviceInfoFirmwareImage_Download(char *refparam, struct dmctx #ifdef SYSMNGR_VENDOR_EXTENSIONS dw_data.keep_config = dmjson_get_value((json_object *)value, 1, CUSTOM_PREFIX"KeepConfig"); + dw_data.keep_opconf = dmjson_get_value((json_object *)value, 1, CUSTOM_PREFIX"KeepOpConf"); + dw_data.config_scope = dmjson_get_value((json_object *)value, 1, CUSTOM_PREFIX"ConfigScope"); #endif dw_data.bank_id = get_fwbank_option_value(data, "id"); dw_data.obj_path = dmstrdup(obj_path); @@ -617,6 +675,8 @@ static operation_args firmware_image_activate_args = { "TimeWindow.{i}.MaxRetries", #ifdef SYSMNGR_VENDOR_EXTENSIONS CUSTOM_PREFIX"KeepConfig", + CUSTOM_PREFIX"KeepOpConf", + CUSTOM_PREFIX"ConfigScope", #endif NULL } @@ -637,19 +697,16 @@ static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx char *user_message[MAX_TIME_WINDOW] = {0}; char *max_retries[MAX_TIME_WINDOW] = {0}; char *keep_config = NULL; - bool bKeepConfig = false; + char *keep_opconf = NULL; + char *config_scope = NULL; int res = 0, last_idx = -1; #ifdef SYSMNGR_VENDOR_EXTENSIONS keep_config = dmjson_get_value((json_object *)value, 1, CUSTOM_PREFIX"KeepConfig"); + keep_opconf = dmjson_get_value((json_object *)value, 1, CUSTOM_PREFIX"KeepOpConf"); + config_scope = dmjson_get_value((json_object *)value, 1, CUSTOM_PREFIX"ConfigScope"); #endif - if (DM_STRLEN(keep_config) == 0) { - bKeepConfig = true; - } else { - string_to_bool(keep_config, &bKeepConfig); - } - for (int i = 0; i < MAX_TIME_WINDOW; i++) { char buf[32] = {0}; @@ -720,9 +777,10 @@ static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx ACTIVATE_HANDLER_FILE); len = strlen(buffer); - snprintf(buffer+len, sizeof(buffer)-len, " '%s' '%s' '%ld' '%d' '%s' '%d' '%s'\n", + snprintf(buffer+len, sizeof(buffer)-len, " '%s' '%s' '%ld' '%d' '%s' '%s' '%s' '%s' '%s'\n", mode[i], bank_id, (DM_STRTOL(end_time[i]) - DM_STRTOL(start_time[i])), - (i == last_idx), max_retries[i], bKeepConfig, user_message[i]); + (i == last_idx), max_retries[i], (keep_config)?keep_config:"1", + (keep_opconf)?keep_opconf:"1", config_scope, user_message[i]); fprintf(file, "%s", buffer); } @@ -734,10 +792,7 @@ static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx if (!fwbank_set_bootbank(bank_id)) return USP_FAULT_COMMAND_FAILURE; - if (bKeepConfig == true) { - fwbank_copy_config(); - } - + fwbank_copy_config(keep_config, keep_opconf, config_scope); bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); } diff --git a/src/fwbank.c b/src/fwbank.c index 67327e8..f831653 100644 --- a/src/fwbank.c +++ b/src/fwbank.c @@ -538,20 +538,26 @@ static void fwbank_upgrade_finish_callback(struct ubus_context *ctx, struct ubus return; } -int sysmngr_fwbank_upgrade(const char *path, bool auto_activate, uint32_t bank_id, bool keep_settings, struct ubus_request_data *req) +static int sysmngr_fwbank_upgrade(struct blob_buf *bbp, int bank_id, struct ubus_request_data *req) { + char *str = NULL; char cmd[1024] = {0}; + int res = 0; - snprintf(cmd, sizeof(cmd), "echo '{\"path\":\"%s\", \"auto_activate\":%d, \"bank\":%u, \"keep_settings\":%d}' | %s 2>/dev/null", - path, auto_activate, bank_id, keep_settings, FWBANK_UPGRADE_CMD); - - int res = sysmngr_task_fork(fwbank_upgrade_finish_callback, cmd, 60, req, bank_id); - if (res) { - BBFDM_ERR("Failed to start task for fwbank upgrade command"); + str = blobmsg_format_json(bbp->head, true); + if (str == NULL) { return -1; } - return 0; + snprintf(cmd, sizeof(cmd), "echo '%s' | %s 2>/dev/null", str, FWBANK_UPGRADE_CMD); + res = sysmngr_task_fork(fwbank_upgrade_finish_callback, cmd, 60, req, bank_id); + if (res) { + BBFDM_ERR("Failed to start task for fwbank upgrade command"); + res = -1; + } + + FREE(str); + return res; } static int dump_handler(struct ubus_context *ctx, struct ubus_object *obj, @@ -640,6 +646,8 @@ enum { UPGRADE_AUTO_ACTIVATE, UPGRADE_BANK, UPGRADE_KEEP_SETTINGS, + UPGRADE_KEEP_OPCONF, + UPGRADE_CONFIG_MODE, __UPGRADE_MAX }; @@ -648,6 +656,8 @@ static const struct blobmsg_policy upgrade_policy[] = { [UPGRADE_AUTO_ACTIVATE] = { .name = "auto_activate", .type = BLOBMSG_TYPE_BOOL }, [UPGRADE_BANK] = { .name = "bank", .type = BLOBMSG_TYPE_INT32 }, [UPGRADE_KEEP_SETTINGS] = { .name = "keep_settings", .type = BLOBMSG_TYPE_BOOL}, + [UPGRADE_KEEP_OPCONF] = { .name = "keep_opconf", .type = BLOBMSG_TYPE_BOOL}, + [UPGRADE_CONFIG_MODE] = { .name = "config_scope", .type = BLOBMSG_TYPE_STRING}, }; static int upgrade_handler(struct ubus_context *ctx, struct ubus_object *obj, @@ -655,11 +665,11 @@ static int upgrade_handler(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *msg) { struct blob_attr *tb[__UPGRADE_MAX]; - char *fw_path = NULL; uint32_t bank_id = 0; - bool auto_activate = false; - bool keep_settings = false; + char *tmp_string = NULL; + bool tmp_boolean = false; int res = 0; + struct blob_buf bb = {0}; if (blobmsg_parse(upgrade_policy, __UPGRADE_MAX, tb, blob_data(msg), blob_len(msg))) { BBFDM_ERR("Failed to parse the 'upgrade' message"); @@ -667,22 +677,53 @@ static int upgrade_handler(struct ubus_context *ctx, struct ubus_object *obj, } if (tb[UPGRADE_PATH]) - fw_path = blobmsg_get_string(tb[UPGRADE_PATH]); + tmp_string = blobmsg_get_string(tb[UPGRADE_PATH]); - if (tb[UPGRADE_AUTO_ACTIVATE]) - auto_activate = blobmsg_get_bool(tb[UPGRADE_AUTO_ACTIVATE]); + if (DM_STRLEN(tmp_string) == 0) { + BBFDM_ERR("Path missing, aborting upgrade!!!"); + return UBUS_STATUS_UNKNOWN_ERROR; + } - if (tb[UPGRADE_BANK]) + if (tb[UPGRADE_BANK]) { bank_id = blobmsg_get_u32(tb[UPGRADE_BANK]); + } else { + BBFDM_ERR("bank missing, aborting upgrade!!!"); + return UBUS_STATUS_UNKNOWN_ERROR; + } - if (tb[UPGRADE_KEEP_SETTINGS]) - keep_settings = blobmsg_get_bool(tb[UPGRADE_KEEP_SETTINGS]); + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); - res = sysmngr_fwbank_upgrade(fw_path, auto_activate, bank_id, keep_settings, req); + blobmsg_add_string(&bb, "path", tmp_string); + blobmsg_add_u32(&bb, "bank", bank_id); + + // default values will be enforced in fwbank script + if (tb[UPGRADE_AUTO_ACTIVATE]) { + tmp_boolean = blobmsg_get_bool(tb[UPGRADE_AUTO_ACTIVATE]); + blobmsg_add_u8(&bb, "auto_activate", tmp_boolean); + } else { + blobmsg_add_u8(&bb, "auto_activate", false); + } + + if (tb[UPGRADE_KEEP_SETTINGS]) { + tmp_boolean = blobmsg_get_bool(tb[UPGRADE_KEEP_SETTINGS]); + blobmsg_add_u8(&bb, "keep_settings", tmp_boolean); + } + + if (tb[UPGRADE_KEEP_OPCONF]) { + tmp_boolean = blobmsg_get_bool(tb[UPGRADE_KEEP_OPCONF]); + blobmsg_add_u8(&bb, "keep_opconf", tmp_boolean); + } + + if (tb[UPGRADE_CONFIG_MODE]) { + tmp_string = blobmsg_get_string(tb[UPGRADE_CONFIG_MODE]); + blobmsg_add_string(&bb, "config_scope", tmp_string); + } + + res = sysmngr_fwbank_upgrade(&bb, bank_id, req); + blob_buf_free(&bb); if (res) { - struct blob_buf bb = {0}; - memset(&bb, 0, sizeof(struct blob_buf)); blob_buf_init(&bb, 0); blobmsg_add_string(&bb, "result", "failure"); diff --git a/src/fwbank.h b/src/fwbank.h index aaae952..cd87929 100644 --- a/src/fwbank.h +++ b/src/fwbank.h @@ -17,7 +17,6 @@ extern struct blobmsg_policy sysmngr_bank_policy[]; struct blob_buf *sysmngr_fwbank_dump(void); bool sysmngr_fwbank_set_bootbank(uint32_t bank_id); -int sysmngr_fwbank_upgrade(const char *path, bool auto_activate, uint32_t bank_id, bool keep_settings, struct ubus_request_data *req); void sysmngr_fwbank_refresh_global_dump(void);