yocto: add fota upgrade support [1/1]
PD#SWPL-89639
Problem:
add fota upgrade support
Solution:
add fota upgrade support
Verify:
S4_AQ2432
Change-Id: I8d8c02c084b4a2994dd487592591ac127769120a
Signed-off-by: Bing Jiang <bing.jiang@amlogic.com>
diff --git a/fota/dmgr_api.h b/fota/dmgr_api.h
new file mode 100644
index 0000000..9598d00
--- /dev/null
+++ b/fota/dmgr_api.h
@@ -0,0 +1,314 @@
+#ifndef __DMGR_API_H
+#define __DMGR_API_H
+
+#include <stdarg.h>
+
+typedef int dmgr_t;
+struct notifier_block;
+
+enum NOTIFY {
+ NOTIFY_USER_BEGIN = 0,
+ NOTIFY_CHECKVERSION_PREPARE,
+ NOTIFY_CHECKVERSION_ABORTED,
+ NOTIFY_CHECKVERSION_FINISHED,
+ NOTIFY_DOWNLOAD_PREPARE,
+ NOTIFY_DOWNLOAD_ABORTED,
+ NOTIFY_DOWNLOAD_TRANSLATING,
+ NOTIFY_DOWNLOAD_FINISHED,
+ NOTIFY_DOWNLOAD_PARTTIAL_FINISHED,
+ NOTIFY_SOCKET_CONNECT_PREPARE,
+ NOTIFY_SOCKET_CONNECT_ABORTED,
+ NOTIFY_SOCKET_CONNECT_FINISHED,
+ NOTIFY_SOCKET_CONNECT_CLOSED,
+ NOTIFY_SOCKET_SEND_PREPARE,
+ NOTIFY_SOCKET_SEND_TRANSLATING,
+ NOTIFY_SOCKET_SEND_ABORTED,
+ NOTIFY_SOCKET_SEND_FINISHED,
+ NOTIFY_SOCKET_RECV_PREPARE,
+ NOTIFY_SOCKET_RECV_TRANSLATING,
+ NOTIFY_SOCKET_RECV_ABORTED,
+ NOTIFY_SOCKET_RECV_FINISHED,
+ NOTIFY_USER_END
+};
+
+enum NOTIFIER_ID {
+ NOTIFY_ID_CHECK_VERSION = 0,
+ NOTIFY_ID_DOWNLOAD,
+ NOTIFY_ID_SOCKET,
+ MAX_USER_NOTIFIERS
+};
+
+enum _DMGR_ERRNO {
+ E_OK = 0,
+ E_BEGIN = 300,
+ E_NOMEM,
+ E_INVAL_PARAM,
+ E_INVAL_OPERATION,
+ E_IO_FAILED,
+ E_IO_TIMEDOUT,
+ E_VERIFIED_FAILED,
+ E_CANCELLED,
+ E_NESTING_CALLED,
+ E_RESERVE1 = 400,
+ /* Error from server */
+ E_INVAL_TOKEN,
+ E_INVAL_PLATFORM,
+ E_PARAM_MISSING,
+ E_UNCONFIGURED_VERSION,
+ E_INTERNAL_ERROR,
+ E_RESERVE2 = 500,
+ E_URL_MALFORMAT,
+ E_COULDNT_RESOLVE_HOST,
+ E_COULDNT_CONNECT,
+ E_HTTP_RETURNED_ERROR,
+ E_RANGE_ERROR,
+ E_HTTP_POST_ERROR,
+ E_BAD_DOWNLOAD_RESUME,
+ E_ABORTED,
+ E_AGAIN,
+ E_TOO_MANY_REDIRECTS,
+ E_GOT_NOTHING,
+ E_SEND_ERROR,
+ E_RECV_ERROR,
+ E_NO_CONNECTION_AVAILABLE,
+ E_END
+};
+
+#define DMGR_ERRNO(err) (int)(-(err))
+#define SOCKET_WAIT_FOREVER ((int)-1)
+
+#define VERINFO_FLAGS_FORCE_PACKAGE (int)(0x01 << 0)
+typedef struct version_info {
+ char *version_name;
+ int file_size;
+ char *delta_id;
+ char *md5sum;
+ char *delta_url;
+ char *release_note;
+ int flags;
+ char *upgrade_from_time;
+ char *upgrade_to_time;
+ char *upgrade_gap;
+ char *meta_data;
+ char *event_id;
+} version_info_t;
+
+typedef struct download_info {
+ long total_bytes;
+ long break_bytes;
+ long saved_bytes;
+ long now_bytes;
+} download_info_t;
+
+typedef struct error_value {
+ int error;
+} error_value_t;
+
+typedef struct socket_sbuf {
+ char *data;
+ size_t size;
+} socket_sbuf_t;
+
+typedef struct notifier_data {
+ union {
+ struct error_value errvalue;
+ struct download_info dlinfo;
+ struct version_info verinfo;
+ struct socket_sbufs {
+ struct socket_sbuf *sock_sbufs;
+ size_t count;
+ } ssbufs;
+ } u;
+} notifier_data_t;
+
+typedef int (*notifier_fn_t)(struct notifier_block *nb,
+ unsigned long action,
+ void *data);
+
+typedef struct socket_connect {
+ int (*create)(struct socket_connect *conn,
+ char *hostname,
+ int port,
+ int recv_timeout,
+ int send_timeout,
+ int connect_timeout,
+ int flags);
+ int (*destory)(struct socket_connect *conn);
+ int (*connect)(struct socket_connect *conn);
+ int (*send)(struct socket_connect *conn,
+ char *buf,
+ size_t size,
+ size_t *sent_size);
+ int (*send_sbufs)(struct socket_connect *conn,
+ struct socket_sbuf *sbufs,
+ size_t count,
+ size_t *sent_size);
+ int (*recv)(struct socket_connect *conn,
+ char *buf,
+ size_t size,
+ size_t *recved_size);
+ int (*close)(struct socket_connect *conn);
+} socket_connect_t;
+
+typedef struct notifier_block {
+ notifier_fn_t notifier_call;
+ struct notifier_block *next;
+ int priority;
+ int alloc_set;
+} notifier_block_t;
+
+#define init_notifier_block(nb, call, pri) \
+ do { \
+ (nb)->notifier_call = call; \
+ (nb)->next = NULL; \
+ (nb)->priority = pri; \
+ (nb)->alloc_set= 0; \
+ } while (0)
+
+#define SERVER_TRANSOPT_FOTA ((0x00 << 0) & 0x0f)
+#define SERVER_TRANSOPT_RELIANCE ((0x01 << 0) & 0x0f)
+#define SERVER_TRANSOPT_RELIANCE_ST ((0x02 << 0) & 0x0f)
+#define SERVER_TRANSOPT_VEHICLE ((0x03 << 0) & 0x0f)
+#define SERVER_TRANSOPT_IOT ((0x04 << 0) & 0x0f)
+#define SERVER_TRANSOPT_HTTPS ((0x01 << 4) & 0xf0)
+#define SERVER_TRANSOPT_HTTP ((0x02 << 4) & 0xf0)
+#define SERVER_TRANSOPT_COMPACT_HTTP ((0x03 << 4) & 0xf0)
+
+typedef struct policy_info {
+ int so_transfer_timeout; /* The tcp/ip receive/send data timeout */
+ int so_connect_timeout; /* The tcp/ip connection timeout */
+ int so_recv_buffer_size; /* The max size of receive buffer */
+ int download_retry; /* The retry count for download failed */
+ int download_retry_time; /* The retry delay time(seconds) for download failed */
+ int server_transfer_opt; /* The type or opt of sepcific server */
+ char *sstate_cached_path; /* The path used for cache dmgr shared-state */
+ char *root_certificates; /* Root certificates are self-signed and form
+ the basis of an X.509-based public key
+ infrastructure (PKI) */
+ char *sub_certificates; /* The path used for cache dmgr shared-state */
+ int freespace_for_file_frac; /* file bavail safe proportion */
+} policy_info_t;
+
+#define POLICY_INFO_INIT(name) \
+ { .so_transfer_timeout = -1, \
+ .so_connect_timeout = -1, \
+ .so_recv_buffer_size = 8192, \
+ .download_retry = 10, \
+ .download_retry_time = 5, \
+ .server_transfer_opt = SERVER_TRANSOPT_FOTA| \
+ SERVER_TRANSOPT_COMPACT_HTTP, \
+ .sstate_cached_path = "/var", \
+ .root_certificates = NULL, \
+ .sub_certificates = NULL, \
+ .freespace_for_file_frac = 90 \
+ }
+
+#define POLICY_INFO(name) \
+ struct policy_info name = POLICY_INFO_INIT(name)
+
+enum LOGGER {
+ LOGGER_STDIO = 0,
+ LOGGER_BUFFER,
+ LOGGER_FILE
+};
+
+enum LOG_LEVEL {
+ LOG_VERBOSE = 0,
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_WARNING,
+ LOG_ERROR,
+ LOG_FATAL,
+ LOG_OFF
+};
+
+enum LOG_TYPE {
+ LOG_TYPE_CHECK = 0,
+ LOG_TYPE_DOWNLOAD,
+ LOG_TYPE_HTTP,
+ LOG_TYPE_LAST
+};
+
+dmgr_t dmgr_alloc(struct policy_info *policy,
+ enum LOG_LEVEL default_log_level,
+ enum LOGGER logger, ...);
+int dmgr_free(dmgr_t dm_id);
+int dmgr_keepalive_with_server(dmgr_t dm_id);
+int dmgr_register_device_to_server(dmgr_t dm_id);
+int dmgr_register_socket(dmgr_t dm_id, struct socket_connect *conn);
+int dmgr_alloc_notifier(dmgr_t dm_id,
+ enum NOTIFIER_ID nh_id,
+ notifier_fn_t notifier_call,
+ int priority,
+ int extra_bytes);
+int dmgr_register_notifier(dmgr_t dm_id,
+ struct notifier_block *nb,
+ enum NOTIFIER_ID nh_id);
+int dmgr_register_deviceinfo(dmgr_t dm_id,
+ const char *name,
+ const char *value);
+int dmgr_register_salesinfo(dmgr_t dm_id,
+ const char *name,
+ const char *value);
+
+#define SERI_KEEP_URL "KEEP_URL"
+#define SERI_REG_URL "REG_URL"
+#define SERI_CHK_URL "CHK_URL"
+#define SERI_DL_URL "DL_URL"
+#define SERI_REPORT_DLR_URL "REPORT_DLR_URL"
+#define SERI_REPORT_UPGR_URL "REPORT_UPGR_URL"
+#define SERI_REPORT_SALES_URL "REPORT_SALES_URL"
+
+int dmgr_register_serverinfo(dmgr_t dm_id,
+ const char *name,
+ const char *value);
+
+/* The public for checking version */
+int dmgr_check_version(dmgr_t dm_id);
+int dmgr_async_check_version(dmgr_t dm_id);
+int dmgr_async_cancel_checking(dmgr_t dm_id);
+
+/* The public interface for downloading */
+#define DOWNLOAD_FILE_SEEK_BEGIN ((long)0)
+#define DOWNLOAD_FILE_SEEK_END ((long)-1)
+
+int dmgr_filmap_version(dmgr_t dm_id,
+ struct version_info *version,
+ char *file_path,
+ long file_seek,
+ long map_addr_start,
+ long map_size);
+int dmgr_async_filmap_version(dmgr_t dm_id,
+ struct version_info *version,
+ char *file_path,
+ long file_seek,
+ long map_addr_start,
+ long map_size);
+
+int dmgr_download_version(dmgr_t dm_id,
+ struct version_info *version,
+ char *file_path,
+ long file_seek,
+ long start_from,
+ long max_size);
+int dmgr_async_download_version(dmgr_t dm_id,
+ struct version_info *version,
+ char *file_path,
+ long file_seek,
+ long start_from,
+ long max_size);
+
+int dmgr_async_cancel_downloading(dmgr_t dm_id);
+
+/* The public for reporting interface */
+int dmgr_report_upgraded_version(dmgr_t dm_id,
+ struct version_info *version,
+ const char *upgraded_desc);
+
+int dmgr_report_sales_tracker(dmgr_t dm_id);
+int dmgr_set_log_level(int dm_id,
+ enum LOG_TYPE type,
+ enum LOG_LEVEL level);
+int dmgr_version(char *version_buf, int size);
+
+#endif
diff --git a/fota/libdmgr.a b/fota/libdmgr.a
new file mode 100644
index 0000000..df3dd8b
--- /dev/null
+++ b/fota/libdmgr.a
Binary files differ
diff --git a/utils/Makefile b/utils/Makefile
index 485892c..134003d 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -52,6 +52,9 @@
battery_monitor: battery_monitor.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+fota_upgrade: fota_upgrade.c ../aml_utility/unifykey.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) -L../fota -ldmgr -lamldeviceproperty -lm -ldl -lpthread
+
all: $(UTILS)
diff --git a/utils/fota_upgrade.c b/utils/fota_upgrade.c
new file mode 100644
index 0000000..2656ea2
--- /dev/null
+++ b/utils/fota_upgrade.c
@@ -0,0 +1,647 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <time.h>
+
+#include "../fota/dmgr_api.h"
+#include "../aml_utility/unifykey.h"
+#include "aml_device_property.h"
+
+#define CHECK_NETWORK_DEALY 20 //60
+#define INFO_LEN 128
+
+struct test_context {
+ char DEVINFO_OEM[INFO_LEN];
+ char DEVINFO_DEVICETYPE[INFO_LEN];
+ char DEVINFO_PLATFORM[INFO_LEN];
+ char DEVINFO_MODELS[INFO_LEN];
+ char DEVINFO_VERSION[INFO_LEN];
+ char DEVINFO_PRODUCTID[INFO_LEN];
+ char DEVINFO_PRODUCTSECRET[INFO_LEN];
+ const char *DEVINFO_APPVERSION;
+ const char *DEVINFO_NETWORKTYPE;
+ const char *DEVINFO_CHK_URL;
+ char DEVINFO_MID[256];
+
+ int DEVINFO_SERVER_OPT;
+
+ struct notifier_block nb_checkversion;
+ struct notifier_block nb_download;
+
+ int has_new_version;
+ struct version_info cloned_version;
+ int download_exit;
+
+};
+
+#define INIT_DEFAULT_TEST_CONTEXT() \
+{ \
+ .DEVINFO_OEM = "Amlogic", \
+ .DEVINFO_DEVICETYPE = "smarthome", \
+ .DEVINFO_PLATFORM = "A113D", \
+ .DEVINFO_MODELS = "OTT", \
+ .DEVINFO_MID = "20220809043042",\
+ .DEVINFO_VERSION = "0.5.0", \
+ .DEVINFO_PRODUCTID = "1660115992", \
+ .DEVINFO_PRODUCTSECRET = "fa7bfc8d755c4c0b8c52fdb00d431d3f", \
+ .DEVINFO_APPVERSION = "2", \
+ .DEVINFO_NETWORKTYPE= "WIFI", \
+ .DEVINFO_CHK_URL = NULL, \
+ .DEVINFO_SERVER_OPT = SERVER_TRANSOPT_IOT| SERVER_TRANSOPT_HTTP, \
+ .has_new_version = 0, \
+ .download_exit = 0, \
+}
+
+#define TEST_ASSERT_EQUAL_INT(expected, actual) do{ if(expected != actual) return -1;}while(0)
+
+#ifndef CONTAINER_OF
+#define CONTAINER_OF(ptr, type, member) \
+ (type *)((char *)(ptr) - (char *) &((type *)0)->member)
+#endif
+
+#define FOTA_WEB_SERVER "www.abupdate.com"
+#define AML_SYS_SAVE_PATH "/data"
+
+static char *__save_file_path = "/data/software.swu";
+static char *__version_file_path = "/version.txt";
+static char *__new_version_file = "new_version";
+
+static int write_new_version(struct version_info *ver) {
+ FILE *ver_fd = NULL;
+ char *save_path = AML_SYS_SAVE_PATH;
+ char cmd_buf[200];
+
+ snprintf(cmd_buf, 200, "%s/%s", save_path, __new_version_file);
+ if (access(cmd_buf, F_OK) != -1) {
+ snprintf(cmd_buf, 200, "rm %s/%s", save_path, __new_version_file);
+ system(cmd_buf);
+ }
+
+ snprintf(cmd_buf, 200, "%s/%s", save_path, __new_version_file);
+ ver_fd = fopen(cmd_buf, "w+");
+ if (NULL == ver_fd) {
+ printf("Cannot open version file %s\n", cmd_buf);
+ return -1;
+ }
+
+ fprintf(ver_fd, "version_name:%s\n", ver->version_name);
+ //fprintf(ver_fd, "file_size:%d\n", ver->file_size);
+ //fprintf(ver_fd, "delta_id:%s\n", ver->delta_id);
+ //fprintf(ver_fd, "md5sum:%s\n", ver->md5sum);
+ //fprintf(ver_fd, "delta_url:%s\n", ver->delta_url);
+ //fprintf(ver_fd, "release_note:%s\n", ver->release_note);
+ //fprintf(ver_fd, "upgrade_from_time:%s\n", ver->upgrade_from_time);
+ //fprintf(ver_fd, "upgrade_to_time:%s\n", ver->upgrade_to_time);
+ //fprintf(ver_fd, "upgrade_gap:%s\n", ver->upgrade_gap);
+ //fprintf(ver_fd, "meta_data:%s\n", ver->meta_data);
+ //fprintf(ver_fd, "event_id:%s\n", ver->event_id);
+
+ fclose(ver_fd);
+ return 0;
+}
+
+static char *simple_strndup(const char *s, size_t n)
+{
+ size_t max_len = strnlen(s, n);
+
+ char *dest = malloc(max_len + 1);
+ if (dest) {
+ memcpy(dest, s, max_len);
+ dest[max_len] = '\0';
+ }
+
+ return dest;
+}
+
+static char *simple_strdup(const char *s)
+{
+ return simple_strndup(s, 0x7fffff);
+}
+
+static void clone_version(struct test_context *test_ctx, struct version_info *info)
+{
+ test_ctx->cloned_version.file_size = info->file_size;
+ test_ctx->cloned_version.flags = info->flags;
+
+ if (info->version_name) {
+ test_ctx->cloned_version.version_name = simple_strdup(info->version_name);
+ }
+ if (info->delta_id) {
+ test_ctx->cloned_version.delta_id = simple_strdup(info->delta_id);
+ }
+ if (info->md5sum) {
+ test_ctx->cloned_version.md5sum = simple_strdup(info->md5sum);
+ }
+ if (info->delta_url) {
+ test_ctx->cloned_version.delta_url = simple_strdup(info->delta_url);
+ }
+ if (info->release_note) {
+ test_ctx->cloned_version.release_note = simple_strdup(info->release_note);
+ }
+ if (info->upgrade_from_time) {
+ test_ctx->cloned_version.upgrade_from_time = strdup(info->upgrade_from_time);
+ }
+ if (info->upgrade_to_time) {
+ test_ctx->cloned_version.upgrade_to_time = strdup(info->upgrade_to_time);
+ }
+ if (info->upgrade_gap) {
+ test_ctx->cloned_version.upgrade_gap = strdup(info->upgrade_gap);
+ }
+ if (info->meta_data) {
+ test_ctx->cloned_version.meta_data = simple_strdup(info->meta_data);
+ }
+ if (info->event_id) {
+ test_ctx->cloned_version.event_id = strdup(info->event_id);
+ }
+}
+
+static void free_cloned_version(struct test_context *test_ctx)
+{
+ struct version_info *info = &test_ctx->cloned_version;
+
+ if (!test_ctx->has_new_version) {
+ return;
+ }
+
+ if (info->version_name) {
+ free(info->version_name);
+ }
+ if (info->delta_id) {
+ free(info->delta_id);
+ }
+ if (info->md5sum) {
+ free(info->md5sum);
+ }
+ if (info->delta_url) {
+ free(info->delta_url);
+ }
+ if (info->release_note) {
+ free(info->release_note);
+ }
+ if (info->upgrade_from_time) {
+ free(info->upgrade_from_time);
+ }
+ if (info->upgrade_to_time) {
+ free(info->upgrade_to_time);
+ }
+ if (info->upgrade_gap) {
+ free(info->upgrade_gap);
+ }
+ if (info->meta_data) {
+ free(info->meta_data);
+ }
+ if (info->event_id) {
+ free(info->event_id);
+ }
+
+ memset(info, 0x00, sizeof(*info));
+ test_ctx->has_new_version = 0;
+}
+
+static int checkversion_notifier(struct notifier_block *nb,
+ unsigned long action,
+ void *data)
+{
+ struct test_context *test_ctx = CONTAINER_OF(nb, struct test_context, nb_checkversion);
+
+ switch (action) {
+ case NOTIFY_CHECKVERSION_PREPARE:
+ printf("[callback: checkversion_prepare]\n");
+ break;
+
+ case NOTIFY_CHECKVERSION_ABORTED:
+ printf("[callback: checkversion_abored]\n");
+ break;
+
+ case NOTIFY_CHECKVERSION_FINISHED:
+ printf("[callback: checkversion_finished]\n");
+ if (data) {
+ printf("[callback: new version %s]\n", ((struct version_info *)data)->version_name);
+ test_ctx->has_new_version = 1;
+ clone_version(test_ctx, data);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int download_notifier(struct notifier_block *nb,
+ unsigned long action,
+ void *data)
+{
+ struct test_context *test_ctx = CONTAINER_OF(nb, struct test_context, nb_download);
+ notifier_data_t *notify_data = (notifier_data_t *)data;
+ long total_Kbytes = notify_data->u.dlinfo.total_bytes/1024;
+ long saved_Kbytes = notify_data->u.dlinfo.saved_bytes/1024;
+ unsigned int percent = (saved_Kbytes * 100)/total_Kbytes;
+ static unsigned int pre_percent = 0;
+
+ //printf("[download_notifier] percent:%d, total_Kbytes:%d, saved_Kbytes:%d\n", percent, total_Kbytes, saved_Kbytes);
+
+ switch (action) {
+ case NOTIFY_DOWNLOAD_PREPARE:
+ printf("[callback: download_prepare]\n");
+ pre_percent = 0;
+ break;
+
+ case NOTIFY_DOWNLOAD_ABORTED:
+ printf("[callback: download_abored]\n");
+ test_ctx->download_exit = -1;
+ break;
+
+ case NOTIFY_DOWNLOAD_TRANSLATING:
+ if (percent < 100) {
+ if (pre_percent != percent) {
+ pre_percent = percent;
+ printf("[callback: download_translating] percent:%d\n", percent);
+
+ char cmd_buf[100];
+ snprintf(cmd_buf, 100, "echo Downloading %d > /tmp/fota_stat", percent);
+ system(cmd_buf);
+ }
+ }
+ break;
+
+ case NOTIFY_DOWNLOAD_FINISHED:
+ test_ctx->download_exit = 1;
+ percent = 100;
+ printf("[callback: download_finished], percent:%d\n", percent);
+ break;
+
+ case NOTIFY_DOWNLOAD_PARTTIAL_FINISHED:
+ printf("[callback: download_partial_finished]\n");
+ test_ctx->download_exit = 1;
+ break;
+ }
+
+ return 0;
+}
+
+static int init_notifier(dmgr_t dm_id, struct test_context *test_ctx)
+{
+ test_ctx->nb_checkversion.notifier_call = checkversion_notifier;
+ test_ctx->nb_checkversion.priority = 0;
+
+ test_ctx->nb_download.notifier_call = download_notifier;
+ test_ctx->nb_download.priority = 0;
+
+ TEST_ASSERT_EQUAL_INT(0, dmgr_register_notifier(dm_id,
+ &test_ctx->nb_checkversion,
+ NOTIFY_ID_CHECK_VERSION));
+
+ TEST_ASSERT_EQUAL_INT(0, dmgr_register_notifier(dm_id,
+ &test_ctx->nb_download,
+ NOTIFY_ID_DOWNLOAD));
+
+ return 0;
+}
+
+static void WAIT_DOWNLOAD_COMPLETED(struct test_context *test_ctx)
+{
+ if (!test_ctx) {
+ return;
+ }
+ for (;;) {
+ if (test_ctx->download_exit != 0) {
+ printf(">>>>>download_exit = %d\n", test_ctx->download_exit);
+ break;
+ }
+ sleep(1);
+ }
+}
+
+static int getMid(char* readbuf)
+{
+ #define DEVICE_NAME "deviceid"
+ int fd,ret = -1;
+
+ ret = Aml_Util_UnifyKeyInit(UNIFYKEYS_PATH);
+ if (0 > ret) {
+ printf("%s() %d, init unifykey failed @ %d!\n",
+ __func__, __LINE__, ret);
+ }
+
+ ret = Aml_Util_UnifyKeyRead(UNIFYKEYS_PATH, DEVICE_NAME, readbuf);
+ return ret;
+}
+
+static int get_sw_version(char *sw_version) {
+ FILE *ver_fd = NULL;
+ char line[200];
+
+ ver_fd = fopen(__version_file_path, "r");
+ if (NULL == ver_fd) {
+ printf("Cannot open version file %s\n", __version_file_path);
+ return -1;
+ }
+
+ while (fgets(line, sizeof(line), ver_fd))
+ {
+ char *pLine = strstr(line, "imagename");
+ if (NULL != pLine)
+ {
+ // 20220809043042
+ memcpy(sw_version, pLine+strlen(pLine)-15, 14);
+ break;
+ }
+ }
+
+ fclose(ver_fd);
+
+ return 0;
+}
+
+static int get_deviceinfo(struct test_context *test_ctx) {
+ int ret;
+ char out_value[INFO_LEN];
+
+ ret = get_sw_version(test_ctx->DEVINFO_VERSION);
+
+ // SDK_VERSION of device.properties, only can sync time base on clean build
+ //ret = AmlDeviceGetProperty("SDK_VERSION", out_value, INFO_LEN);
+ //if (ret == AMLDEVICE_SUCCESS) {
+ // memcpy(test_ctx->DEVINFO_VERSION, out_value, strlen(out_value));
+ //}
+
+ ret = AmlDeviceGetProperty("DEVINFO_OEM", out_value, INFO_LEN);
+ if (ret == AMLDEVICE_SUCCESS) {
+ memcpy(test_ctx->DEVINFO_OEM, out_value, strlen(out_value));
+ }
+
+ ret = AmlDeviceGetProperty("DEVINFO_DEVICETYPE", out_value, INFO_LEN);
+ if (ret == AMLDEVICE_SUCCESS) {
+ memcpy(test_ctx->DEVINFO_DEVICETYPE, out_value, strlen(out_value));
+ }
+
+ ret = AmlDeviceGetProperty("DEVINFO_PLATFORM", out_value, INFO_LEN);
+ if (ret == AMLDEVICE_SUCCESS) {
+ memcpy(test_ctx->DEVINFO_PLATFORM, out_value, strlen(out_value));
+ }
+
+ ret = AmlDeviceGetProperty("DEVINFO_MODELS", out_value, INFO_LEN);
+ if (ret == AMLDEVICE_SUCCESS) {
+ memcpy(test_ctx->DEVINFO_MODELS, out_value, strlen(out_value));
+ }
+
+ ret = AmlDeviceGetProperty("DEVINFO_PRODUCTID", out_value, INFO_LEN);
+ if (ret == AMLDEVICE_SUCCESS) {
+ memcpy(test_ctx->DEVINFO_PRODUCTID, out_value, strlen(out_value));
+ }
+
+ ret = AmlDeviceGetProperty("DEVINFO_PRODUCTSECRET", out_value, INFO_LEN);
+ if (ret == AMLDEVICE_SUCCESS) {
+ memcpy(test_ctx->DEVINFO_PRODUCTSECRET, out_value, strlen(out_value));
+ }
+
+ return ret;
+}
+
+static int report_upgraded_version(dmgr_t dm_id, char *ver) {
+ struct version_info cur_ver;
+ int ret;
+
+ if (ver == NULL) return -1;
+
+ memset(&cur_ver, 0, sizeof(struct version_info));
+ cur_ver.version_name = ver;
+ ret = dmgr_report_upgraded_version(dm_id, &cur_ver, "Upgrade done");
+ printf("dmgr_report_upgraded_version %s ret = %d\n", ver, ret);
+
+ return ret;
+}
+
+#define STR_VALUE(val) #val
+#define STR(name) STR_VALUE(name)
+
+#define PATH_LEN 256
+#define MD5_LEN 32
+
+static int CalcFileMD5(char *file_name, char *md5_sum)
+{
+#define MD5SUM_CMD_FMT "md5sum %." STR(PATH_LEN) "s 2>/dev/null"
+ char cmd[PATH_LEN + sizeof (MD5SUM_CMD_FMT)];
+ sprintf(cmd, MD5SUM_CMD_FMT, file_name);
+#undef MD5SUM_CMD_FMT
+
+ FILE *p = popen(cmd, "r");
+ if (p == NULL) return 0;
+
+ int i, ch;
+ for (i = 0; i < MD5_LEN && isxdigit(ch = fgetc(p)); i++) {
+ *md5_sum++ = ch;
+ }
+
+ *md5_sum = '\0';
+ pclose(p);
+
+ return i == MD5_LEN;
+}
+
+static int check_md5(char *md5sum) {
+ char md5_str[MD5_LEN+1];
+
+ if (!CalcFileMD5(__save_file_path, md5_str)) {
+ printf("Cannot calculate the md5 sum\n");
+ return -1;
+ }
+
+ printf("Calculate the md5 sum = %s\n", md5_str);
+ if (!strncmp(md5_str, md5sum, MD5_LEN)) {
+ printf("Check md5sum OK\n");
+ return 0;
+ }
+
+ return -1;
+}
+
+int checkNet(const char *web_server) {
+ char buffer[200];
+ FILE *fp;
+ char *p, num[3];
+
+ snprintf(buffer, 200, "ping %s -c 1 -w 2 > /tmp/netlog", web_server);
+ //printf("command: %s\n", buffer);
+ system(buffer);
+ //sleep(2);
+ usleep(50000);
+
+ fp = fopen("/tmp/netlog", "r");
+ if (fp < 0) {
+ printf("open file failed.\n");
+ return 0;
+ }
+
+ fseek(fp, 0, SEEK_SET);
+ memset(buffer, 0, sizeof(buffer));
+ // read penultimate row, 1 packets transmitted, 1 received, 0% packet loss, time 0ms
+ while (fgets(buffer, 200, fp) != NULL) {
+ p = strstr(buffer, "received,");
+ if (p) {
+ //printf("string is: %s", p);
+ memcpy(num, p+10, 3);
+ //printf("num: %s\n", num);
+ if (atoi(num) == 0)
+ return 1;
+ else
+ return 0;
+ }
+ memset(buffer, 0, sizeof(buffer));
+ }
+ fclose(fp);
+
+ system("rm /tmp/netlog");
+ return 0;
+}
+
+int main(void)
+{
+ dmgr_t dm_id,ret;
+ char rbuf[64];
+ struct test_context test_ctx = INIT_DEFAULT_TEST_CONTEXT();
+ struct policy_info policy = POLICY_INFO_INIT(policy);
+ policy.sstate_cached_path = "/var";
+ policy.sub_certificates = "/var/client.crt";
+ policy.server_transfer_opt = SERVER_TRANSOPT_IOT | SERVER_TRANSOPT_HTTP;
+
+ ret = getMid(rbuf);
+ if ((0 != strcmp(rbuf,"")) && (0 < ret)) {
+ strcpy(test_ctx.DEVINFO_MID, rbuf);
+ } else {
+ printf("get mid fail\n");
+ return -1;
+ }
+
+ ret = get_deviceinfo(&test_ctx);
+ if (ret < 0) {
+ printf("get deviceinfo fail\n");
+ return -1;
+ }
+
+#if 1
+ printf(" %s: DEVINFO_OEM = %s \n",__func__,test_ctx.DEVINFO_OEM);
+ printf(" %s: DEVINFO_DEVICETYPE = %s \n",__func__,test_ctx.DEVINFO_DEVICETYPE);
+ printf(" %s: DEVINFO_PLATFORM = %s \n",__func__,test_ctx.DEVINFO_PLATFORM);
+ printf(" %s: DEVINFO_MODELS = %s \n",__func__,test_ctx.DEVINFO_MODELS);
+ printf(" %s: DEVINFO_MID = %s \n",__func__,test_ctx.DEVINFO_MID);
+ printf(" %s: DEVINFO_VERSION = %s \n",__func__,test_ctx.DEVINFO_VERSION);
+ printf(" %s: DEVINFO_PRODUCTID = %s \n",__func__,test_ctx.DEVINFO_PRODUCTID);
+ printf(" %s: DEVINFO_PRODUCTSECRET = %s \n",__func__,test_ctx.DEVINFO_PRODUCTSECRET);
+ printf(" %s: DEVINFO_APPVERSION = %s \n",__func__,test_ctx.DEVINFO_APPVERSION);
+ printf(" %s: DEVINFO_NETWORKTYPE = %s \n",__func__,test_ctx.DEVINFO_NETWORKTYPE);
+#endif
+
+ system("echo Checking_NewVersion > /tmp/fota_stat");
+ while (1) {
+ if (0 == checkNet(FOTA_WEB_SERVER)) {
+ printf(" network not connect \n ");
+ system("echo network_not_connect > /tmp/fota_stat");
+ //sleep(CHECK_NETWORK_DEALY);
+ return -1;
+ }
+
+ printf(" network connected \n ");
+ dm_id = dmgr_alloc(&policy, LOG_INFO, LOGGER_STDIO, stdout);
+ if (0 >= dm_id) {
+ return -1;
+ }
+
+ if (0 != dmgr_register_deviceinfo(dm_id,
+ "oem", test_ctx.DEVINFO_OEM) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "deviceType",test_ctx.DEVINFO_DEVICETYPE) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "platform", test_ctx.DEVINFO_PLATFORM) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "models", test_ctx.DEVINFO_MODELS) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "mid", test_ctx.DEVINFO_MID) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "version", test_ctx.DEVINFO_VERSION) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "productId", test_ctx.DEVINFO_PRODUCTID) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "productSecret", test_ctx.DEVINFO_PRODUCTSECRET) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "appversion", test_ctx.DEVINFO_APPVERSION) ||
+ 0 != dmgr_register_deviceinfo(dm_id,
+ "networkType", test_ctx.DEVINFO_NETWORKTYPE)) {
+ TEST_ASSERT_EQUAL_INT(0, dmgr_free(dm_id));
+ continue;
+ }
+
+ if (test_ctx.DEVINFO_CHK_URL) {
+ if (0 != dmgr_register_serverinfo(dm_id,
+ SERI_CHK_URL,
+ test_ctx.DEVINFO_CHK_URL)) {
+ TEST_ASSERT_EQUAL_INT(0, dmgr_free(dm_id));
+ continue;
+ }
+ }
+
+ init_notifier(dm_id, &test_ctx);
+ if (0 != dmgr_check_version(dm_id)) {
+ TEST_ASSERT_EQUAL_INT(0, dmgr_free(dm_id));
+ printf(">>>> no new version detect\n");
+ system("echo Check_NewVersion Failed> /tmp/fota_stat");
+ break;
+ }
+ if (0 == test_ctx.has_new_version) {
+ if ((access("/data/software.swu",F_OK)) != -1) {
+ system("rm /data/software.swu");
+ }
+ TEST_ASSERT_EQUAL_INT(0, dmgr_free(dm_id));
+ printf(" no new_version \n");
+ system("echo No_NewVersion > /tmp/fota_stat");
+ ret = 0;
+ break;
+ } else {
+ printf(" ADUPS : has_new_version \n");
+ system("echo NewVersion > /tmp/fota_stat");
+ }
+
+ system("echo downloading > /tmp/fota_stat");
+ if (0 != dmgr_async_download_version(dm_id,
+ &test_ctx.cloned_version,
+ __save_file_path,
+ DOWNLOAD_FILE_SEEK_END,
+ 0,
+ -1)) {
+ TEST_ASSERT_EQUAL_INT(0, dmgr_free(dm_id));
+ system("echo Download_FAILED > /tmp/fota_stat");
+ ret = -1;
+ break;
+ }
+
+ WAIT_DOWNLOAD_COMPLETED(&test_ctx);
+
+ if (test_ctx.has_new_version &&
+ (test_ctx.download_exit == 1)) {
+ write_new_version(&test_ctx.cloned_version);
+ // ota package not match md5sum, remove software.swu
+ if (check_md5(test_ctx.cloned_version.md5sum) == 0) {
+ printf("secure upgrade check pass!\n");
+ system("echo package_check_SUCCESS > /tmp/fota_stat");
+ system("reboot recovery");
+ ret = 1;
+ } else {
+ system("rm /data/software.swu");
+ system("sync");
+ TEST_ASSERT_EQUAL_INT(0, dmgr_free(dm_id));
+ system("echo package_check_FAILED > /tmp/fota_stat");
+ printf("ota package not match md5sum!\n");
+ ret = -1;
+ }
+ }
+
+ free_cloned_version(&test_ctx);
+ break;
+ }
+
+ return ret;
+}