Skip to content

binary_manager: Support new APIs for partition swap #6706

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
29 changes: 29 additions & 0 deletions framework/include/binary_manager/binary_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
* Included Files
***************************************************************************/
#include <tinyara/binary_manager.h>
#include <tinyara/config.h>

#ifdef __cplusplus
extern "C" {
#endif

/****************************************************************************
* Pre-processor Definitions
Expand Down Expand Up @@ -69,6 +74,17 @@ binmgr_result_type_e binary_manager_get_update_info(char *binary_name, binary_up
* @since TizenRT v3.0
*/
binmgr_result_type_e binary_manager_get_update_info_all(binary_update_info_list_t *binary_info_list);

/**
* @brief Get the all binaries information in inactive partition
* @details @b #include <binary_manager/binary_manager.h>\n
* It requests the binary manager to get the information of all binaries in inactive partition.
* @param[out] binary_info_list The address value to receive the binary information list
* @return A defined value of binmgr_result_type_e in <tinyara/binary_manager.h>
* 0 (BINMGR_OK) On success. On failure, negative value is returned.
* @since TizenRT v3.0
*/
binmgr_result_type_e binary_manager_get_inactive_info_all(binary_update_info_list_t *binary_info_list);
#endif

/**
Expand Down Expand Up @@ -150,6 +166,19 @@ binmgr_result_type_e binary_manager_get_state(char *binary_name, int *state);
*/
binmgr_result_type_e binary_manager_set_bootparam(uint8_t type, binary_setbp_result_t *update_result);

/**
* @brief Swap partition to inactive partition
* @details @b #include <binary_manager/binary_manager.h>\n
* It sends a message the binary manager to update boot paramer to swap opposite partition.
* @return A defined value of binmgr_result_type_e in <tinyara/binary_manager.h>
* 0 (BINMGR_OK) on success. On failure, negative value is returned.
* @since TizenRT v5.0
*/
binmgr_result_type_e binary_manager_swap_partition(void);
#ifdef __cplusplus
}
#endif

#endif
/**
* @}
Expand Down
2 changes: 2 additions & 0 deletions framework/src/binary_manager/binary_manager_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ binmgr_result_type_e binary_manager_set_request(binmgr_request_t *request_msg, i
case BINMGR_SETBP:
request_msg->data.type = *(uint8_t *)arg;
break;
case BINMGR_SWAPBP:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? It looks that default covers.

break;
#endif
case BINMGR_REGISTER_STATECB:
if (arg == NULL) {
Expand Down
63 changes: 63 additions & 0 deletions framework/src/binary_manager/binary_manager_update.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,66 @@ binmgr_result_type_e binary_manager_get_current_path(char *binary_name, char *do

return response_msg.result;
}

binmgr_result_type_e binary_manager_swap_partition(void)
{
#ifndef CONFIG_USE_BP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about locating positive case first? Because n could be missing at code checking.

/* In the case of 3.1 bootloader, we dont have bp. So we need not
* update the bp to swap partitions, it is automatically done on
* reboot, so return success */
return BINMGR_OK;
#else
binmgr_result_type_e ret;
binmgr_request_t request_msg;
binmgr_setbp_response_t response_msg;

ret = binary_manager_set_request(&request_msg, BINMGR_SWAPBP, NULL);
if (ret != BINMGR_OK) {
return ret;
}

ret = binary_manager_send_request(&request_msg);
if (ret != BINMGR_OK) {
return ret;
}

ret = binary_manager_receive_response(&response_msg, sizeof(binmgr_response_t));
if (ret != BINMGR_OK) {
return ret;
}

return response_msg.result;
#endif
}

binmgr_result_type_e binary_manager_get_inactive_info_all(binary_update_info_list_t *binary_info_list)
{
binmgr_result_type_e ret;
binmgr_request_t request_msg;
binmgr_getinfo_all_response_t response_msg;

ret = binary_manager_set_request(&request_msg, BINMGR_GET_INFO_INACTIVE_ALL, NULL);
if (ret != BINMGR_OK) {
return ret;
}

ret = binary_manager_send_request(&request_msg);
if (ret != BINMGR_OK) {
return ret;
}

ret = binary_manager_receive_response(&response_msg, sizeof(binmgr_getinfo_all_response_t));
if (ret != BINMGR_OK) {
return ret;
}

if (response_msg.result == BINMGR_OK) {
/* Copy binary info list data */
memset(binary_info_list, 0, sizeof(binary_update_info_list_t));
memcpy(binary_info_list, &response_msg.data, sizeof(binary_update_info_list_t));
} else {
bmdbg("Binary manager getinfo_inactive_all FAIL %d\n", response_msg.result);
}

return response_msg.result;
}
21 changes: 13 additions & 8 deletions os/include/tinyara/binary_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#include <limits.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef CONFIG_BINARY_MANAGER
/****************************************************************************
* Pre-processor Definitions
Expand Down Expand Up @@ -125,6 +129,10 @@ enum binmgr_request_msg_type {
#ifdef CONFIG_BINMGR_RECOVERY
BINMGR_FAULT,
#endif
#ifdef CONFIG_USE_BP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In enum, I wanna remove conditionals.
Let's return INVALID or NOT SUPPORT when the related config is disabled.

BINMGR_SWAPBP,
#endif
BINMGR_GET_INFO_INACTIVE_ALL,
};

/* Result values of returned from binary manager. */
Expand Down Expand Up @@ -254,6 +262,11 @@ struct binmgr_request_s {
};
typedef struct binmgr_request_s binmgr_request_t;

struct binmgr_response_s {
binmgr_result_type_e result;
};
typedef struct binmgr_response_s binmgr_response_t;

struct binmgr_setbp_response_s {
binmgr_result_type_e result;
binary_setbp_result_t data;
Expand Down Expand Up @@ -300,14 +313,6 @@ void binary_manager_register_respart(int part_num, int part_size, uint32_t part_
int binary_manager_mount_resource(void);
void binary_manager_deinit_modules(void);

#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif

#undef EXTERN
#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 6 additions & 0 deletions os/kernel/binary_manager/binary_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ int binary_manager(int argc, char *argv[])
case BINMGR_GET_INFO_ALL:
binary_manager_get_info_all(request_msg.requester_pid);
break;
case BINMGR_GET_INFO_INACTIVE_ALL:
binary_manager_get_inactive_info_all(request_msg.requester_pid);
break;
case BINMGR_GET_DOWNLOAD_PATH:
binary_manager_get_inactive_path(request_msg.requester_pid, request_msg.data.bin_name);
break;
Expand All @@ -221,6 +224,9 @@ int binary_manager(int argc, char *argv[])
case BINMGR_SETBP:
binary_manager_update_bootparam(request_msg.requester_pid, request_msg.data.type);
break;
case BINMGR_SWAPBP:
binary_manager_swap_bootparam(request_msg.requester_pid);
break;
#endif
case BINMGR_UPDATE:
#ifdef CONFIG_APP_BINARY_SEPARATION
Expand Down
4 changes: 3 additions & 1 deletion os/kernel/binary_manager/binary_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,10 @@ int binary_manager_update_kernel_binary(void);
#ifdef CONFIG_RESOURCE_FS
binmgr_resinfo_t *binary_manager_get_resdata(void);
int binary_manager_unmount_resource(void);
int binary_manager_check_resource_update(void);
int binary_manager_check_resource_update(bool check_updatable);
#endif
int binary_manager_check_kernel_update(bool check_updatable);
int binary_manager_check_user_update(int bin_idx, bool check_updatable);

/****************************************************************************
* Binary Manager Main Thread
Expand Down
114 changes: 105 additions & 9 deletions os/kernel/binary_manager/binary_manager_bootparam.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <stdbool.h>

#include <tinyara/binary_manager.h>
#include <tinyara/reboot_reason.h>

#include "binary_manager.h"

Expand Down Expand Up @@ -284,8 +285,8 @@ void binary_manager_update_bootparam(int requester_pid, uint8_t type)

if (BM_CHECK_GROUP(type, BINARY_KERNEL)) {
/* Update bootparam and Reboot if new kernel binary exists */
ret = binary_manager_check_kernel_update();
if (ret == BINMGR_OK) {
ret = binary_manager_check_kernel_update(true);
if (ret > 0) {
/* Update index for inactive partition */
update_bp_data.active_idx ^= 1;
} else if (ret == BINMGR_ALREADY_UPDATED || ret == BINMGR_NOT_FOUND) {
Expand All @@ -301,8 +302,8 @@ void binary_manager_update_bootparam(int requester_pid, uint8_t type)
#ifdef CONFIG_RESOURCE_FS
if (BM_CHECK_GROUP(type, BINARY_RESOURCE)) {
/* Update bootparam if new resource binary exists */
ret = binary_manager_check_resource_update();
if (ret == BINMGR_OK) {
ret = binary_manager_check_resource_update(true);
if (ret > 0) {
/* Update index for inactive partition */
update_bp_data.resource_active_idx ^= 1;
} else if (ret == BINMGR_ALREADY_UPDATED || ret == BINMGR_NOT_FOUND) {
Expand All @@ -324,8 +325,8 @@ void binary_manager_update_bootparam(int requester_pid, uint8_t type)
/* Reload binaries if new binary is scanned */
for (bin_idx = 1; bin_idx <= bin_count; bin_idx++) {
/* Scan binary files */
ret = binary_manager_check_user_update(bin_idx);
if (ret == BINMGR_OK) {
ret = binary_manager_check_user_update(bin_idx, true);
if (ret > 0) {
/* Update index for inactive partition */
update_bp_data.app_data[BIN_BPIDX(bin_idx)].useidx ^= 1;
need_update = true;
Expand All @@ -345,8 +346,8 @@ void binary_manager_update_bootparam(int requester_pid, uint8_t type)

#ifdef CONFIG_SUPPORT_COMMON_BINARY
if (BM_CHECK_GROUP(type, BINARY_COMMON)) {
ret = binary_manager_check_user_update(BM_CMNLIB_IDX);
if (ret == BINMGR_OK) {
ret = binary_manager_check_user_update(BM_CMNLIB_IDX, true);
if (ret > 0) {
/* Update index for inactive partition */
update_bp_data.app_data[BIN_BPIDX(BM_CMNLIB_IDX)].useidx ^= 1;
} else if (ret == BINMGR_ALREADY_UPDATED || ret == BINMGR_NOT_FOUND) {
Expand Down Expand Up @@ -376,7 +377,9 @@ void binary_manager_update_bootparam(int requester_pid, uint8_t type)
}

send_response:
kmm_free(bootparam);
if (bootparam) {
kmm_free(bootparam);
}
response_msg.result = ret;
snprintf(q_name, BIN_PRIVMQ_LEN, "%s%d", BINMGR_RESPONSE_MQ_PREFIX, requester_pid);
binary_manager_send_response(q_name, &response_msg, sizeof(binmgr_setbp_response_t));
Expand Down Expand Up @@ -422,3 +425,96 @@ void binary_manager_set_bpidx(uint8_t index)
{
g_bp_info.inuse_idx = index;
}

void binary_manager_swap_bootparam(int requester_pid)
{
int ret;
char *bootparam;
bool is_all_updatable;
char q_name[BIN_PRIVMQ_LEN];
binmgr_bpdata_t update_bp_data;
binmgr_response_t response_msg;
#ifdef CONFIG_APP_BINARY_SEPARATION
int bin_idx;
uint32_t bin_count;
#endif

memset((void *)&response_msg, 0, sizeof(binmgr_response_t));

if (requester_pid < 0) {
bmdbg("Invalid requester pid %d\n", requester_pid);
return;
}

bootparam = (char *)kmm_malloc(BOOTPARAM_SIZE);
if (!bootparam) {
bmdbg("Fail to malloc to read BP\n");
ret = BINMGR_OUT_OF_MEMORY;
goto send_response;
}
memset(bootparam, 0xff, BOOTPARAM_SIZE);

response_msg.result = BINMGR_OK;
is_all_updatable = true;

/* Get current bootparam data */
memcpy(&update_bp_data, binary_manager_get_bpdata(), sizeof(binmgr_bpdata_t));
update_bp_data.version++;

/* Update bootparam and Reboot if valid kernel binary exists */
ret = binary_manager_check_kernel_update(false);
if (ret < 0) {
bmdbg("Fail to find valid kernel binary, %d\n", ret);
goto send_response;
}
update_bp_data.active_idx ^= 1;

#ifdef CONFIG_RESOURCE_FS
/* Update bootparam if valid resource binary exists */
ret = binary_manager_check_resource_update(false);
if (ret < 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we get failure at somewhere, kernel update or resource update or user update, can we know which gets failure?

bmdbg("Fail to find valid resource binary, %d\n", ret);
goto send_response;
}
update_bp_data.resource_active_idx ^= 1;
#endif

#ifdef CONFIG_APP_BINARY_SEPARATION
bin_count = binary_manager_get_ucount();
for (bin_idx = 1; bin_idx <= bin_count; bin_idx++) {
/* Scan binary files */
ret = binary_manager_check_user_update(bin_idx, false);
if (ret < 0) {
bmdbg("Fail to find valid user binary, %d\n", ret);
goto send_response;
}
update_bp_data.app_data[BIN_BPIDX(bin_idx)].useidx ^= 1;
}

#ifdef CONFIG_SUPPORT_COMMON_BINARY
ret = binary_manager_check_user_update(BM_CMNLIB_IDX, false);
if (ret < 0) {
bmdbg("Fail to find valid common binary, %d\n", ret);
goto send_response;
}
update_bp_data.app_data[BIN_BPIDX(BM_CMNLIB_IDX)].useidx ^= 1;
#endif
#endif

/* Then, Write bootparam with updated bootparam data */
memcpy(bootparam, &update_bp_data, sizeof(binmgr_bpdata_t));
ret = binary_manager_write_bootparam(bootparam);
if (ret == BINMGR_OK) {
bmvdbg("Update BP SUCCESS\n");
} else {
bmdbg("Fail to update BP, %d\n", ret);
}

send_response:
if (bootparam) {
kmm_free(bootparam);
}
response_msg.result = ret;
snprintf(q_name, BIN_PRIVMQ_LEN, "%s%d", BINMGR_RESPONSE_MQ_PREFIX, requester_pid);
binary_manager_send_response(q_name, &response_msg, sizeof(binmgr_response_t));
}
Loading