From 9ae2530a318f8c9e721fc0b36d489949b37a5457 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Wed, 5 Jul 2017 11:44:29 +0900 Subject: [PATCH] Add TW1 resources Change-Id: I981fa028dd508e2c7067fdd82234a199cc9fbc95 Signed-off-by: Sunmin Lee --- CMakeLists.txt | 4 + fota_gui/CMakeLists.txt | 51 +- fota_gui/fota_gr_direct.c | 1 + fota_gui/fota_gr_direct_wc1.c | 549 +++++++++ fota_gui/fota_gui_common.h | 67 ++ fota_gui/fota_gui_log.h | 85 ++ fota_gui/fota_gui_util.c | 79 ++ fota_gui/fota_gui_util.h | 26 + fota_gui/fota_show_img.c | 120 -- packaging/tota-ua.spec | 48 +- res/tw1/images/tw1_fota_progress_000.png | Bin 0 -> 977 bytes res/tw1/images/tw1_fota_progress_001.png | Bin 0 -> 1190 bytes res/tw1/images/tw1_fota_progress_002.png | Bin 0 -> 1257 bytes res/tw1/images/tw1_fota_progress_003.png | Bin 0 -> 1364 bytes res/tw1/images/tw1_fota_progress_004.png | Bin 0 -> 1359 bytes res/tw1/images/tw1_fota_progress_005.png | Bin 0 -> 1348 bytes res/tw1/images/tw1_fota_progress_006.png | Bin 0 -> 1241 bytes res/tw1/images/tw1_fota_progress_007.png | Bin 0 -> 1095 bytes res/tw1/images/tw1_fota_progress_008.png | Bin 0 -> 932 bytes res/tw1/images/tw1_fota_progress_009.png | Bin 0 -> 1172 bytes res/tw1/images/tw1_fota_progress_010.png | Bin 0 -> 1253 bytes res/tw1/images/tw1_fota_progress_011.png | Bin 0 -> 1342 bytes res/tw1/images/tw1_fota_progress_012.png | Bin 0 -> 1344 bytes res/tw1/images/tw1_fota_progress_013.png | Bin 0 -> 1318 bytes res/tw1/images/tw1_fota_progress_014.png | Bin 0 -> 1226 bytes res/tw1/images/tw1_fota_progress_015.png | Bin 0 -> 1110 bytes res/tw1/images/tw1_fota_progress_016.png | Bin 0 -> 880 bytes res/tw1/images/tw1_fota_progress_017.png | Bin 0 -> 1085 bytes res/tw1/images/tw1_fota_progress_018.png | Bin 0 -> 1232 bytes res/tw1/images/tw1_fota_progress_019.png | Bin 0 -> 1308 bytes res/tw1/images/tw1_fota_progress_020.png | Bin 0 -> 1391 bytes res/tw1/images/tw1_fota_progress_021.png | Bin 0 -> 1390 bytes res/tw1/images/tw1_fota_progress_022.png | Bin 0 -> 1342 bytes res/tw1/images/tw1_fota_progress_023.png | Bin 0 -> 1243 bytes res/tw1/images/tw1_fota_progress_024.png | Bin 0 -> 1029 bytes res/tw1/images/tw1_fota_progress_025.png | Bin 0 -> 1035 bytes res/tw1/images/tw1_fota_progress_026.png | Bin 0 -> 1249 bytes res/tw1/images/tw1_fota_progress_027.png | Bin 0 -> 1332 bytes res/tw1/images/tw1_fota_progress_028.png | Bin 0 -> 1377 bytes res/tw1/images/tw1_fota_progress_029.png | Bin 0 -> 1328 bytes res/tw1/images/tw1_fota_progress_030.png | Bin 0 -> 1260 bytes res/tw1/images/tw1_fota_progress_031.png | Bin 0 -> 1197 bytes res/tw1/images/tw1_fota_progress_032.png | Bin 0 -> 1022 bytes res/tw1/images/tw1_fota_progress_bg.png | Bin 0 -> 11254 bytes res/tw1/images/tw1_fota_progress_final.png | Bin 0 -> 17677 bytes res/tw1/images/wc_fota_downloading_0.png | Bin 0 -> 1221 bytes res/tw1/images/wc_fota_downloading_1.png | Bin 0 -> 1095 bytes res/tw1/images/wc_fota_downloading_2.png | Bin 0 -> 1225 bytes res/tw1/images/wc_fota_downloading_3.png | Bin 0 -> 1274 bytes res/tw1/images/wc_fota_downloading_4.png | Bin 0 -> 1175 bytes res/tw1/images/wc_fota_downloading_5.png | Bin 0 -> 1217 bytes res/tw1/images/wc_fota_downloading_6.png | Bin 0 -> 1279 bytes res/tw1/images/wc_fota_downloading_7.png | Bin 0 -> 1188 bytes res/tw1/images/wc_fota_downloading_8.png | Bin 0 -> 1273 bytes res/tw1/images/wc_fota_downloading_9.png | Bin 0 -> 1293 bytes res/tw1/images/wc_fota_downloading_percent.png | Bin 0 -> 1384 bytes res/tw1/images/wc_fota_start_downloading.png | Bin 0 -> 3386 bytes scripts/tw1/41-tota-ua.list | 57 + src/common/fota_util.c | 127 ++ src/common/fota_util.h | 5 + src/rpi3/ua.c | 117 -- src/rpi3/ua.h | 2 - src/tw1/ua.c | 1483 ++++++++++++++++++++++++ src/tw1/ua.h | 191 +++ 64 files changed, 2748 insertions(+), 264 deletions(-) create mode 100755 fota_gui/fota_gr_direct_wc1.c create mode 100755 fota_gui/fota_gui_common.h create mode 100755 fota_gui/fota_gui_log.h create mode 100755 fota_gui/fota_gui_util.c create mode 100755 fota_gui/fota_gui_util.h delete mode 100755 fota_gui/fota_show_img.c create mode 100755 res/tw1/images/tw1_fota_progress_000.png create mode 100755 res/tw1/images/tw1_fota_progress_001.png create mode 100755 res/tw1/images/tw1_fota_progress_002.png create mode 100755 res/tw1/images/tw1_fota_progress_003.png create mode 100755 res/tw1/images/tw1_fota_progress_004.png create mode 100755 res/tw1/images/tw1_fota_progress_005.png create mode 100755 res/tw1/images/tw1_fota_progress_006.png create mode 100755 res/tw1/images/tw1_fota_progress_007.png create mode 100755 res/tw1/images/tw1_fota_progress_008.png create mode 100755 res/tw1/images/tw1_fota_progress_009.png create mode 100755 res/tw1/images/tw1_fota_progress_010.png create mode 100755 res/tw1/images/tw1_fota_progress_011.png create mode 100755 res/tw1/images/tw1_fota_progress_012.png create mode 100755 res/tw1/images/tw1_fota_progress_013.png create mode 100755 res/tw1/images/tw1_fota_progress_014.png create mode 100755 res/tw1/images/tw1_fota_progress_015.png create mode 100755 res/tw1/images/tw1_fota_progress_016.png create mode 100755 res/tw1/images/tw1_fota_progress_017.png create mode 100755 res/tw1/images/tw1_fota_progress_018.png create mode 100755 res/tw1/images/tw1_fota_progress_019.png create mode 100755 res/tw1/images/tw1_fota_progress_020.png create mode 100755 res/tw1/images/tw1_fota_progress_021.png create mode 100755 res/tw1/images/tw1_fota_progress_022.png create mode 100755 res/tw1/images/tw1_fota_progress_023.png create mode 100755 res/tw1/images/tw1_fota_progress_024.png create mode 100755 res/tw1/images/tw1_fota_progress_025.png create mode 100755 res/tw1/images/tw1_fota_progress_026.png create mode 100755 res/tw1/images/tw1_fota_progress_027.png create mode 100755 res/tw1/images/tw1_fota_progress_028.png create mode 100755 res/tw1/images/tw1_fota_progress_029.png create mode 100755 res/tw1/images/tw1_fota_progress_030.png create mode 100755 res/tw1/images/tw1_fota_progress_031.png create mode 100755 res/tw1/images/tw1_fota_progress_032.png create mode 100755 res/tw1/images/tw1_fota_progress_bg.png create mode 100755 res/tw1/images/tw1_fota_progress_final.png create mode 100755 res/tw1/images/wc_fota_downloading_0.png create mode 100755 res/tw1/images/wc_fota_downloading_1.png create mode 100755 res/tw1/images/wc_fota_downloading_2.png create mode 100755 res/tw1/images/wc_fota_downloading_3.png create mode 100755 res/tw1/images/wc_fota_downloading_4.png create mode 100755 res/tw1/images/wc_fota_downloading_5.png create mode 100755 res/tw1/images/wc_fota_downloading_6.png create mode 100755 res/tw1/images/wc_fota_downloading_7.png create mode 100755 res/tw1/images/wc_fota_downloading_8.png create mode 100755 res/tw1/images/wc_fota_downloading_9.png create mode 100755 res/tw1/images/wc_fota_downloading_percent.png create mode 100755 res/tw1/images/wc_fota_start_downloading.png create mode 100755 scripts/tw1/41-tota-ua.list create mode 100755 src/tw1/ua.c create mode 100755 src/tw1/ua.h diff --git a/CMakeLists.txt b/CMakeLists.txt index da85c2c..7a58628 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,10 @@ PROJECT(fota C) IF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_RPI3") SET(MODELDIR "rpi3") +ELSEIF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_TW1") +ADD_DEFINITIONS("-DFEATURE_SUPPORT_CAPABILITY") +ADD_DEFINITIONS("-DFEATURE_HOLD_LAST_FB") +SET(MODELDIR "tw1") ELSE() SET(MODELDIR "rpi3") ENDIF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_RPI3") diff --git a/fota_gui/CMakeLists.txt b/fota_gui/CMakeLists.txt index 619cf34..fc43642 100755 --- a/fota_gui/CMakeLists.txt +++ b/fota_gui/CMakeLists.txt @@ -2,24 +2,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) #set( CMAKE_VERBOSE_MAKEFILE on ) -SET(GUI_SRCS - fota_gui_main.c - fota_gr.c - fota_png.c - tdm-if.c - ) - -SET(SHOWIMG_SRCS - fota_show_img.c - fota_png.c - tdm-if.c - ) - SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(BINDIR "${PREFIX}/bin") SET(FOTA_GUI "fota_gui") SET(FOTA_GUI_TEST "fota_gui_test") -SET(FOTA_SHOW_IMG "fota_show_img") STRING(FIND ${CMAKE_C_FLAGS} "mfloat-abi=hard" IFFOUND1) @@ -32,6 +18,7 @@ IF("${CMAKE_BUILD_TYPE}" STREQUAL "") ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") +IF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_TW1") INCLUDE(FindPkgConfig) pkg_check_modules(gui_pkgs REQUIRED @@ -39,13 +26,41 @@ pkg_check_modules(gui_pkgs REQUIRED libtdm libpng ) +SET(GUI_SRCS + fota_gui_main.c + fota_gr.c + fota_png.c + tdm-if.c + fota_gui_util.c +) +ELSE() + +INCLUDE(FindPkgConfig) +pkg_check_modules(gui_pkgs REQUIRED + libtbm + libtdm + libpng +) +SET(GUI_SRCS + fota_gui_main.c + fota_gr.c + fota_png.c + tdm-if.c + fota_gui_util.c +) +ENDIF() FOREACH(flag ${gui_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(GUI_SRCS ${GUI_SRCS} fota_gr_direct.c) +IF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_TW1") + #ADD_DEFINITIONS("-DFEATURE_ROTATE") + SET(GUI_SRCS ${GUI_SRCS} fota_gr_direct_wc1.c) +ELSE() + SET(GUI_SRCS ${GUI_SRCS} fota_gr_direct.c) +ENDIF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_TW1") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") @@ -68,11 +83,5 @@ TARGET_LINK_LIBRARIES(${FOTA_GUI} ${gui_pkgs_LDFLAGS} ${LIBS}) ADD_EXECUTABLE(${FOTA_GUI_TEST} fota_gui_test.c) -ADD_EXECUTABLE(${FOTA_SHOW_IMG} ${SHOWIMG_SRCS}) -TARGET_LINK_LIBRARIES(${FOTA_SHOW_IMG} ${gui_pkgs_LDFLAGS} ${LIBS}) - INSTALL(TARGETS ${FOTA_GUI} DESTINATION ${BINDIR}) INSTALL(TARGETS ${FOTA_GUI_TEST} DESTINATION ${BINDIR}) -INSTALL(TARGETS ${FOTA_SHOW_IMG} DESTINATION ${BINDIR}) - - diff --git a/fota_gui/fota_gr_direct.c b/fota_gui/fota_gr_direct.c index a9d8ff9..7759840 100755 --- a/fota_gui/fota_gr_direct.c +++ b/fota_gui/fota_gr_direct.c @@ -24,6 +24,7 @@ #include "fota_common.h" #include "fota_png.h" +#include "tdm-if.h" diff --git a/fota_gui/fota_gr_direct_wc1.c b/fota_gui/fota_gr_direct_wc1.c new file mode 100755 index 0000000..10b0e21 --- /dev/null +++ b/fota_gui/fota_gr_direct_wc1.c @@ -0,0 +1,549 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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. + */ + +/***************************************************************************** +** header files +*****************************************************************************/ +#include +#include + +#include "fota_gui_common.h" +#include "fota_png.h" +#include "fota_fbinfo.h" +#include "tdm-if.h" + + + +#define COLOR_RED 0xFF0000 +#define COLOR_GREEN 0xFF00 +#define COLOR_BLUE 0x00FF +#define COLOR_WHITE 0xFFFFFF +#define COLOR_BLACK 0x0000 +#define COLOR_GRAY 0xAAAAAA +#define COLOR_LIGHTGRAY 0xDE39 + +#define MAX_PATH 256 +#define MAX_FILE_PATH 512 + +#if !defined(RESDIR) +#define RESDIR "/usr/share/fota/res" +#endif +#define IMG_BASE RESDIR "/images/" + +#define POPUP_IMG_NAME "wc_popup_line.png" +#define MAIN_IMG_NAME "wc_fota_start_downloading.png" +#define MAIN_PG_IMG_NAME "tw1_fota_progress_bg.png" +#define PROGRESS_IMG_PREFIX "wc_fota_progress_" +#define PROGRESS_BAR_IMG_PREFIX "tw1_fota_progress_" +#define PROGRESS_NUM_PREFIX "wc_fota_downloading_" +#define PERCENT_IMG_NAME "wc_fota_downloading_percent.png" + +/***************************************************************************** +** global variables +*****************************************************************************/ +FbInfo s_fbi; + +int s_percent_to_draw = 0; +#ifdef FEATURE_ROTATE +int s_degree = 0; +#endif +int s_saved_percent = -1; + + +/*----------------------------------------------------------------------------- + _gr_direct_fill_rect + ----------------------------------------------------------------------------*/ +static void _gr_direct_fill_rect(FbInfo *fbi, s32 x, s32 y, s32 w, s32 h, u32 color ) +{ + unsigned int *fb_buf_int = NULL; + unsigned int *fb_buf_cur = NULL; + s32 dx = 0; + s32 dy = 0; + s32 wb = 0; + + if (NULL == fbi) + return; + + dx = w; + dy = h; + wb = w * sizeof(u32); + + fb_buf_int = (unsigned int *)fbi->buf; + fb_buf_int += y * fbi->w + x; + fb_buf_cur = fb_buf_int; + + while (dx--) { + *fb_buf_cur++ = color; + } + + fb_buf_cur -= w; + fb_buf_cur += fbi->w; + dy--; + while (dy--) { + memcpy((void*)fb_buf_cur, (void*)fb_buf_int, wb); + fb_buf_cur += fbi->w; + } + +} + +/*----------------------------------------------------------------------------- + _gr_direct_clear_screen + ----------------------------------------------------------------------------*/ +static void _gr_direct_clear_screen(FbInfo *fbi, u32 color ) +{ + unsigned int *fb_buf_int = NULL; + unsigned int *fb_buf_cur = NULL; + s32 dx = 0; + s32 dy = 0; + s32 w = 0; + + if (NULL == fbi) + return; + + dx = fbi->w; + dy = fbi->h; + w = fbi->w * sizeof(u32); + + fb_buf_int = (unsigned int *)fbi->buf; + fb_buf_cur = fb_buf_int; + + while (dx--) { + *fb_buf_cur++ = color; + } + + dy--; + while (dy--) { + memcpy((void*)fb_buf_cur, (void*)fb_buf_int, w); + fb_buf_cur += fbi->w; + } +} + +/*----------------------------------------------------------------------------- + _gr_direct_draw_text + ----------------------------------------------------------------------------*/ +static void _gr_direct_draw_text(FbInfo *fbi, int percent) +{ + char img_name[MAX_PATH]; + int img_x; + int img_y; + int num; + + img_x = 110; + img_y = 240; + + if (percent < 10) { + img_x += 10; + } else if (percent < 100) { + img_x += 20; + } else if (percent == 100) { + img_x += 30; + } + + if (percent == 100) { + sprintf(img_name, "%s%s%d.png", IMG_BASE, PROGRESS_NUM_PREFIX, 1); + if (read_png_file(img_name) < 0) { + return; + } + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + } + + img_x += 18; + if (percent >= 10) { + num = percent / 10; + if (num == 10) + num = 0; + + sprintf(img_name, "%s%s%d.png", IMG_BASE, PROGRESS_NUM_PREFIX, num); + if (read_png_file(img_name) < 0) { + return; + } + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + } + + img_x += 18; + num = percent % 10; + + sprintf(img_name, "%s%s%d.png", IMG_BASE, PROGRESS_NUM_PREFIX, num); + if (read_png_file(img_name) < 0) { + return; + } + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + + img_x += 17; + + sprintf(img_name, "%s%s", IMG_BASE, PERCENT_IMG_NAME); + if (read_png_file(img_name) < 0) { + return; + } + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); +} + +/*----------------------------------------------------------------------------- + _gr_direct_draw_prog_text + ----------------------------------------------------------------------------*/ +static void _gr_direct_draw_prog_text(FbInfo *fbi, int percent) +{ + if (percent <= 0) { + percent = 0; + } + + if (percent > 100) { + percent = 100; + } + + _gr_direct_fill_rect(fbi, 110, 240, 100, 41, COLOR_BLACK); + _gr_direct_draw_text(fbi, percent); +} + +static void _gr_direct_draw_main_prog_img(FbInfo *fbi, int percent) +{ + int img_x = 0; + int img_y = 0; + + if (read_png_file(IMG_BASE MAIN_PG_IMG_NAME) < 0) { + return; + } + + img_x = 0; + img_y = 0; + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); +} + +/*----------------------------------------------------------------------------- + _gr_direct_draw_main_img + ----------------------------------------------------------------------------*/ +static void _gr_direct_draw_main_img(FbInfo *fbi) +{ + int img_x = 0; + int img_y = 0; + + if (read_png_file(IMG_BASE MAIN_IMG_NAME) < 0) { + return; + } + + img_x = 0; + img_y = 0; + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + +} + +static void _gr_direct_draw_text_img(FbInfo *fbi) +{ + int img_x = 0; + int img_y = 0; + + if (read_png_file("/system/opt/usr/data/fota/FotaBgImage.png") < 0) { + return; + } + + img_x = 0; + img_y = 0; + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + +} + +static void _gr_direct_draw_last_buffer_text_img(FbInfo *fbi) +{ + int img_x = 0; + int img_y = 0; + + if (read_png_file("/system/opt/usr/data/fota/FotaBgImage2.png") < 0) { + return; + } + + img_x = 0; + img_y = 0; + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + +} + +static void _gr_direct_draw_popup_img(FbInfo *fbi) +{ + int img_x = 0; + int img_y = 0; + + if (read_png_file(IMG_BASE POPUP_IMG_NAME) < 0) { + return; + } + + img_x = 0; + img_y = 0; + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + +} + +/*----------------------------------------------------------------------------- + __init_screen + ----------------------------------------------------------------------------*/ +static void __init_screen(FbInfo *fbi) +{ + _gr_direct_clear_screen(fbi, COLOR_BLACK); + + //_gr_direct_draw_text_img(fbi); + + _gr_direct_draw_main_img(fbi); + + _gr_direct_draw_main_prog_img(fbi, 0); + + _gr_direct_draw_prog_text(fbi, 0); +} + +static void _gr_direct_final_circle_progress_bar(FbInfo *fbi, int progress) +{ + char img_name[MAX_PATH]; + + // draw current progress image + sprintf(img_name, "%s%sfinal.png", IMG_BASE, PROGRESS_BAR_IMG_PREFIX); + if (read_png_file(img_name) < 0) { + LOG("ERROR \n"); + return; + } + + draw_png_img_xy(fbi, 0, 0); + release_png_res(); +} + +static void _gr_direct_circular_progress(FbInfo *fbi) +{ + char img_name[MAX_PATH]; + static int prog_cnt = 0; + static int prev_prog_cnt = -1; + + // delete previous progress image + if (prev_prog_cnt >= 0) { + sprintf(img_name, "%s%s%02d.png", IMG_BASE, PROGRESS_IMG_PREFIX, prev_prog_cnt+1); + if (read_png_file(img_name) < 0) { + return; + } + + draw_png_mask_xy(fbi, 0, 0, 0, 0, 0); + release_png_res(); + } + + // draw current progress image + sprintf(img_name, "%s%s%02d.png", IMG_BASE, PROGRESS_IMG_PREFIX, prog_cnt+1); + if (read_png_file(img_name) < 0) { + return; + } + + draw_png_img_xy(fbi, 0, 0); + release_png_res(); + + _gr_direct_draw_popup_img(fbi); + + prev_prog_cnt = prog_cnt; + + prog_cnt++; + if (prog_cnt >= 30) { + prog_cnt = 0; + } +} + +static void _gr_direct_circle_progress_bar(FbInfo *fbi, int progress) +{ + char img_name[MAX_PATH]; + + static int prog_pre = 0; + int count = 0; + + int prog_cnt = 0; + + if (progress <= 0) { + progress = 0; + } + + if (progress > 100) { + progress = 100; + } + + prog_cnt = (int)(progress * 32 / 100); + + LOG("prog_pre/prog_cnt : %d, %d \n", prog_pre , prog_cnt); + + for (; prog_pre <= prog_cnt; prog_pre++) + { + LOG("prog_pre/prog_cnt : %d, %d \n", prog_pre , prog_cnt); + + // draw current progress image + sprintf(img_name, "%s%s%03d.png", IMG_BASE, PROGRESS_BAR_IMG_PREFIX, prog_pre); + if (read_png_file(img_name) < 0) { + LOG("ERROR \n"); + return; + } + + draw_png_img_xy(fbi, 0, 0); + release_png_res(); + + count++; + + if (count > 3) + break; + } + + s_saved_percent = prog_pre; +} + +/*----------------------------------------------------------------------------- + _gr_direct_update_screen + ----------------------------------------------------------------------------*/ +static void _gr_direct_update_screen() +{ + tdm_if_buffer_update(s_fbi.buf); + +#ifdef FEATURE_ROTATE + int battery_state = is_batt_status(); + + if ((s_degree != CHG_DEGREE_0) && + (battery_state == BATT_STATE_CHARGING || battery_state == BATT_STATE_FULL)) { + fota_gr_direct_rotate_screen(s_degree); + } else +#endif + { + tdm_if_display_update(); + } +} + +static void _gr_direct_set_last_buffer() +{ + _gr_direct_clear_screen(&s_fbi, COLOR_BLACK); + _gr_direct_draw_last_buffer_text_img(&s_fbi); + _gr_direct_draw_main_prog_img(&s_fbi, 0); + _gr_direct_draw_prog_text(&s_fbi, 0); + tdm_if_buffer_update(s_fbi.buf); +} + +#ifdef FEATURE_ROTATE +void fota_gr_direct_rotate_screen(int degree) +{ + tdm_if_rotate_screen(degree); +} + +void fota_gr_rotate_value(int rotate) +{ + s_degree = rotate; +} +#endif + +/*----------------------------------------------------------------------------- + fota_gr_direct_update_progress + ----------------------------------------------------------------------------*/ +void fota_gr_direct_circular_progress(void) +{ + _gr_direct_circular_progress(&s_fbi); + + if (s_saved_percent != s_percent_to_draw) { + + LOG("fota_gr_direct_circular_progress progress : %d \n", s_percent_to_draw); + + if (s_percent_to_draw == 100) { + _gr_direct_final_circle_progress_bar(&s_fbi, 100); + _gr_direct_draw_prog_text(&s_fbi, 100); + + } else if (s_percent_to_draw > 0) { + _gr_direct_circle_progress_bar(&s_fbi, s_percent_to_draw); + _gr_direct_draw_prog_text(&s_fbi, s_percent_to_draw); + } + } + _gr_direct_update_screen(); +} + +/*----------------------------------------------------------------------------- + fota_gr_direct_update_progress + ----------------------------------------------------------------------------*/ +void fota_gr_direct_update_progress(int percent) +{ + s_percent_to_draw = percent; +} + +/*----------------------------------------------------------------------------- + fota_gr_direct_clear_screen + ----------------------------------------------------------------------------*/ +void fota_gr_direct_clear_screen(u32 color) +{ + _gr_direct_clear_screen(&s_fbi, color); + _gr_direct_update_screen(); +} + +/*----------------------------------------------------------------------------- + fota_gr_direct_init + ----------------------------------------------------------------------------*/ +int fota_gr_direct_init(void) +{ + unsigned char *buf = NULL; + + if (tdm_if_display_init() < 0) { + return -1; + } + +#if !defined(FOTA_GUI_EMBEDDED) + tdm_if_lcd_off(); +#endif + + s_fbi.w = tdm_if_display_width(); + s_fbi.h = tdm_if_display_height(); + s_fbi.sz = tdm_if_display_bufsize(); + + buf = malloc(s_fbi.sz); + if (NULL == buf) { + LOG("Not enough memory (s_fbi.sz = %d)\n", s_fbi.sz); + tdm_if_display_deinit(); + return -1; + } + s_fbi.buf = buf; + + __init_screen(&s_fbi); + + _gr_direct_update_screen(); + + tdm_if_lcd_on(); + + return 0; +} + +/*----------------------------------------------------------------------------- + fota_gr_direct_deinit + ----------------------------------------------------------------------------*/ +void fota_gr_direct_deinit(void) +{ + _gr_direct_set_last_buffer(); + + if (s_fbi.buf) { + free(s_fbi.buf); + s_fbi.buf = NULL; + } + tdm_if_display_deinit(); +} + diff --git a/fota_gui/fota_gui_common.h b/fota_gui/fota_gui_common.h new file mode 100755 index 0000000..b5c8b81 --- /dev/null +++ b/fota_gui/fota_gui_common.h @@ -0,0 +1,67 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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 __FOTA_GUI_COMMON_H__ +#define __FOTA_GUI_COMMON_H__ + + +#include +#include "fota_gui_log.h" + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; +typedef u32 size_t; + +typedef signed long sl32; +typedef unsigned long ul32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#ifdef FEATURE_ROTATE +enum { + CHG_DEGREE_0 = 0, + CHG_DEGREE_90 = 1, + CHG_DEGREE_180 = 2, + CHG_DEGREE_270 = 3, +}; + +enum { + BATT_STATE_CHARGING = 0, + BATT_STATE_FULL, + BATT_STATE_ERROR, + BATT_STATE_DISCONNECT, + BATT_STATE_LOWBATT, + BATT_STATE_OVERVOLTAGE, + BATT_STATE_OVERHEAT, + BATT_STATE_NOTCHARGE, + BATT_STATE_COLD +}; + +extern int is_batt_status(void); + +#endif + + +#endif /* __FOTA_GUI_COMMON_H__ */ diff --git a/fota_gui/fota_gui_log.h b/fota_gui/fota_gui_log.h new file mode 100755 index 0000000..f99e19a --- /dev/null +++ b/fota_gui/fota_gui_log.h @@ -0,0 +1,85 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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 __FOTA_GUI_LOG_H__ +#define __FOTA_GUI_LOG_H__ + +#include + +#define _DEBUG_LOG(fmt, args...) +#define _DEBUG_INFO(fmt, args...) +#define _DEBUG_WARNING(fmt, args...) +#define _DEBUG_EXCEPTION(fmt, args...) +#define _FUNC_ENTER +#define _FUNC_EXIT + +/* + * DEBUGGING FEATURE + */ + +extern unsigned int __log_level__; +extern FILE *__log_out_file__; + +#define LOG_INFO (1<<8) +#define LOG_REDBEND (1<<7) +#define LOG_FUNCS (1<<6) +#define LOG_GUI (1<<5) +#define LOG_DEBUG (1<<4) +#define LOG_FILE (1<<3) +#define LOG_FLASH (1<<2) + +#define LOG_PRFIX "FOTA_GUI" + +#define DEBUG_STDOUT +//#define DEBUG_FILE + +#ifdef DEBUG_STDOUT +#define LOGE(s, args...) printf(LOG_PRFIX "/ERROR(%s) " s, __func__, ##args) // Error log +#define LOGL(mask, s, args...) do{if((mask) & __log_level__) \ + printf(LOG_PRFIX "/(%s): " s,__func__, ##args);}while(0) +#define LOG(s, args...) LOGL(LOG_DEBUG, s, ##args) + +#elif defined(DEBUG_FILE) +#define LOGE(s, args...) fprintf(__log_out_file__, LOG_PRFIX "/ERROR(%s) " s, __func__, ##args) +#define LOGL(mask, s, args...) do{if((mask) & __log_level__) \ + fprintf(__log_out_file__, LOG_PRFIX "/(%s): " s ,__func__, ##args);}while(0) +#define LOG(s, args...) LOGL(LOG_DEBUG, s, ##args) + +#elif defined(DEBUG_STDOUT_FILE) // debug printf +#define LOGE(s, args...) do {\ + printf(LOG_PRFIX "/ERROR(%s) " s, __func__, ##args);\ + fprintf(__log_out_file__, LOG_PRFIX "/ERROR(%s) " s, __func__, ##args);\ + }while(0) +#define LOGL(mask, s, args...) do{ \ + if((mask) & __log_level__){\ + printf(LOG_PRFIX "/(%s): " s ,__func__, ##args);\ + fprintf(__log_out_file__, LOG_PRFIX "/(%s): " s,__func__, ##args);\ + }\ + }while(0) +#define LOG(s, args...) LOGL(LOG_DEBUG, s, ##args) + +#else +#define LOGE(s, args...) +#define LOGL(mask, s, args...) +#define LOG(s, args...) + +#endif + + +#endif /* __FOTA_GUI_LOG_H__ */ + diff --git a/fota_gui/fota_gui_util.c b/fota_gui/fota_gui_util.c new file mode 100755 index 0000000..80b6815 --- /dev/null +++ b/fota_gui/fota_gui_util.c @@ -0,0 +1,79 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int s_fd_stdin = -1; +int s_fd_stdout = -1; +int s_fd_stderr = -1; + +/*----------------------------------------------------------------------------- + set_default_stdio + ----------------------------------------------------------------------------*/ +static int set_default_stdio(int flags, int nfd) +{ + int fd, r; + + fd = open("/dev/null", flags|O_NOCTTY); + if (fd < 0) + return -errno; + + if (fd == nfd) { + return fd; + } else { + r = dup2(fd, nfd) < 0 ? -errno : nfd; + close(fd); + return r; + } +} + +/*----------------------------------------------------------------------------- + _init_stdio + ----------------------------------------------------------------------------*/ +void _init_stdio(void) +{ + s_fd_stdin = set_default_stdio(O_RDONLY, STDIN_FILENO); + + s_fd_stdout = set_default_stdio(O_WRONLY, STDOUT_FILENO); + + s_fd_stderr = set_default_stdio(O_WRONLY, STDERR_FILENO); +} + +/*----------------------------------------------------------------------------- + _exit_stdio + ----------------------------------------------------------------------------*/ +void _exit_stdio(void) +{ + if (s_fd_stdin >=0) + close(s_fd_stdin); + + if (s_fd_stdout >=0) + close(s_fd_stdout); + + if (s_fd_stderr >=0) + close(s_fd_stderr); +} + diff --git a/fota_gui/fota_gui_util.h b/fota_gui/fota_gui_util.h new file mode 100755 index 0000000..e4ec592 --- /dev/null +++ b/fota_gui/fota_gui_util.h @@ -0,0 +1,26 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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 _FOTA_GUI_UTIL_H_ +#define _FOTA_GUI_UTIL_H_ + +extern void _init_stdio(void); +extern void _exit_stdio(void); + +#endif /* _FOTA_GUI_UTIL_H_ */ + diff --git a/fota_gui/fota_show_img.c b/fota_gui/fota_show_img.c deleted file mode 100755 index c70a407..0000000 --- a/fota_gui/fota_show_img.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * tota-ua - * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fota_common.h" -#include "fota_png.h" -#include "fota_fbinfo.h" -#include "tdm-if.h" - -FbInfo s_fbi; -int s_img_x = 0; -int s_img_y = 0; -char s_img_path[1024]; - -unsigned int __log_level__ = - (LOG_DEBUG | LOG_FLASH | LOG_FILE | LOG_FUNCS | LOG_GUI | LOG_REDBEND | LOG_INFO); - -/*----------------------------------------------------------------------------- - _gr_update_screen - ----------------------------------------------------------------------------*/ -static void _gr_update_screen() -{ - tdm_if_buffer_update(s_fbi.buf); - tdm_if_display_update(); -} - -/*----------------------------------------------------------------------------- - _gr_direct_draw_main_img - ----------------------------------------------------------------------------*/ -static void _gr_draw_img(FbInfo *fbi, char *img_path, int img_x, int img_y) -{ - if (read_png_file(img_path) < 0) { - return; - } - - draw_png_img_xy(fbi, img_x, img_y); - release_png_res(); - -} - -/*----------------------------------------------------------------------------- - _gr_init - ----------------------------------------------------------------------------*/ -int _gr_init(void) -{ - unsigned char *buf = NULL; - - if (tdm_if_display_init() < 0) { - return -1; - } - - s_fbi.w = tdm_if_display_width(); - s_fbi.h = tdm_if_display_height(); - s_fbi.sz = tdm_if_display_bufsize(); - - buf = malloc(s_fbi.sz); - if (NULL == buf) { - LOG("Not enough memory (s_fbi.sz = %d)\n", s_fbi.sz); - tdm_if_display_deinit(); - return -1; - } - s_fbi.buf = buf; - - _gr_draw_img(&s_fbi, s_img_path, s_img_x, s_img_y); - - _gr_update_screen(); - - return 0; -} - -/*----------------------------------------------------------------------------- - _gr_deinit - ----------------------------------------------------------------------------*/ -void _gr_deinit(void) -{ - if (s_fbi.buf) { - free(s_fbi.buf); - s_fbi.buf = NULL; - } - tdm_if_display_deinit(); -} - -int main(int argc, char **argv) -{ - if (argc != 4) - return -1; - - s_img_x = atoi(argv[1]); - s_img_y = atoi(argv[2]); - snprintf(s_img_path, sizeof(s_img_path)-1, "%s", argv[3]); - - if (_gr_init() < 0) { - return -1; - } - - return 0; -} diff --git a/packaging/tota-ua.spec b/packaging/tota-ua.spec index 6925307..ce701d2 100755 --- a/packaging/tota-ua.spec +++ b/packaging/tota-ua.spec @@ -1,8 +1,8 @@ Name: tota-ua Summary: fota update agent ExclusiveArch: %{arm} -Version: 0.1.2 -Release: 3 +Version: 0.1.3 +Release: 4 Group: System License: Apache-2.0 Source0: %{name}-%{version}.tar.gz @@ -28,6 +28,13 @@ Provides: %{name}-compat = %{version}-%{release} %description target_rpi3 TOTA update agent binary targeting RPi3 target. +%package target_tw1 +Summary: TOTA update agent for TW1 target +Provides: %{name}-compat = %{version}-%{release} +%description target_tw1 +TOTA update agent binary targeting TW1 target. + + %prep %setup -q @@ -45,16 +52,41 @@ pushd build_rpi3 make %{?jobs:-j%jobs} popd +mkdir -p build_tw1 +pushd build_tw1 +%cmake .. \ + -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DFOTA_PARTITION_TYPE="PART_TW1" + +make %{?jobs:-j%jobs} +popd + %install rm -rf %{buildroot} pushd build_rpi3 %make_install mv %{buildroot}%{_bindir}/delta.ua %{buildroot}%{_bindir}/delta.ua.rpi3 +mv %{buildroot}%{_datadir}/fota/res/images %{buildroot}%{_datadir}/fota/res/images_rpi3 +popd + +pushd build_tw1 +%make_install +mv %{buildroot}%{_bindir}/delta.ua %{buildroot}%{_bindir}/delta.ua.tw1 +mv %{buildroot}%{_datadir}/fota/res/images %{buildroot}%{_datadir}/fota/res/images_tw1 +mkdir -p %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d +cp ../scripts/tw1/41-tota-ua.list %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/41-tota-ua.list.tw1 popd %post target_rpi3 mv %{_bindir}/delta.ua.rpi3 %{_bindir}/delta.ua +mv %{_datadir}/fota/res/images_rpi3 %{_datadir}/fota/res/images + +%post target_tw1 +mv %{_bindir}/delta.ua.tw1 %{_bindir}/delta.ua +mv %{_datadir}/fota/res/images_tw1 %{_datadir}/fota/res/images +mv %{_datadir}/initrd-recovery/initrd.list.d/41-tota-ua.list.tw1 \ + %{_datadir}/initrd-recovery/initrd.list.d/41-tota-ua.list %post @@ -64,5 +96,13 @@ mv %{_bindir}/delta.ua.rpi3 %{_bindir}/delta.ua %files target_rpi3 %defattr(-,root,root,-) -%{_prefix}/share/fota -%{_prefix}/bin/* +%{_datadir}/fota/res/images_rpi3 +%{_bindir}/delta.ua.rpi3 + +%files target_tw1 +%defattr(-,root,root,-) +%attr(700,-,-) %{_datadir}/initrd-recovery/initrd.list.d/41-tota-ua.list.tw1 +%{_datadir}/fota/res/images_tw1 +%{_bindir}/delta.ua.tw1 +%{_bindir}/fota_gui +%{_bindir}/fota_gui_test diff --git a/res/tw1/images/tw1_fota_progress_000.png b/res/tw1/images/tw1_fota_progress_000.png new file mode 100755 index 0000000000000000000000000000000000000000..823cc1414622193f057ff9fc7de2fca9475987dd GIT binary patch literal 977 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz%pVv-iJ{%>5$q5H#@%kri9SA}?I*CP#0O-@U10F#>c?^>f;s0 z8}(dLWse`i7zbgDe;`Jk%99Cy0{{NFw^9Gt&XCwO>q4flUi|T6;MdfzS9jz+w*FXT zDjyboqy4`n>)C@6`D#1AYgV5Td%gPV^{c&w>%z@f=dZebb!%|W<4p=fS?83{1OPWtaqNOlz#>i0lkfOec1}wEIQQvxgLnNqAAekNIrh%^pL^oFZ?C?*{IV|4Q8#84 z&f@R6Tyu0=@rK`jIugFlTM;L>{Ac&8lG0Vb_WVlQDe-KrTJmz9+k6buflA}o%)9%1 z_2#Q5Umf}R`bv@EpKT{|-iWdCYMc3eZoj(sf5OZ6SJkh&KVR=Zz58MRR@UU_8W|BA z3uo1@Teqtrx_+hIihFDC#p|`nhe`F!UA!Q%^;qV(|&u#xD{vS#!bS z?D5s@<`$oRzltc$*(tH_?t>UJ2gk!)y_aj2?ApI;@vg1AikctWuZ~+87p>P8Z*DQ& z6ljy$W0Uwe*;Rbu<#Yer>}b6B{Fe2KYq zEB)cy|DOFceOhmdKI;Vst0EK5^j{pDw literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_002.png b/res/tw1/images/tw1_fota_progress_002.png new file mode 100755 index 0000000000000000000000000000000000000000..a991089612ce37112c70c7f2a5bc8158689a8ebb GIT binary patch literal 1257 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz39T{Np<+x* zu}J-9rC7r(dU z1iB3s_=K#?tzY@}Tj=uy%e$+X86InGy*uGah}ru0!k%&dpRQdfuU}&#QM^0lDr3V% z+ew?d*GEsR!40Q*M1Z=z5GxN^Q}V zve-%an|~a7y;?)*2+n`bmOwRLK5jh**oq00G`;@?S<^=g%-Cl4-sUl(g8Exv3)qHoUM z7u(HGHmYpbwS4zn<-A(u<@y!d`jpZx6kO~>-pWfgzk+V4+4t+bd9lnBe( zZG4hDa@`7l^-A57#m@KtnmOrg)5v(>6S#lMlRnjBHS<%FU+m_0<7{nWJEyhvt#6UR z$#ts7Y;3;Vy*N>6t*QAchW`@3-u+cEPyak|slBejqmW7EZoFHMty$3cS!-+T%#{Dv zUUx~}FZ+I>Ts}X3)z?J}8o7buv!4V^V*mgAin8;4+kMOvueCL?r3Gc(p8TX>((H4^ zKaQ*HZrk@eH9gpOwrxg&8Zc-kJ-Mdhum1DzoWs(mDr>?n9JsS>o^7qg$-SQUWPjz| v?^0&`kiT@>@9lD@SWpwrC~qi+K=#Z0-WR=}mY&Qo1UcW+)z4*}Q$iB}Ki+mt literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_003.png b/res/tw1/images/tw1_fota_progress_003.png new file mode 100755 index 0000000000000000000000000000000000000000..0c5deeb8b045f2b7c43e70a0e5a78dd469bedfb7 GIT binary patch literal 1364 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzH4n5m@TsI1XEN!ibqcn3-vV+IMXAy72gchHBbMDQbCzYpmem;0wL|;Dr-5pP$ z(}(~K*_vD5&MIw7y>!-!VS|iU?(Io){6B?G5_Z1-*XFSY_xrX;c7|!kiapEJD>Y7f zt$h2V=d+HDw8@6VrQ7y;o>RS9bakn*=e!NR>-%}7ZcGTe-Rl{5+Wxeq=R5zReOJm- zii368S$T7=T=x9-@A%ibp7->(?hVblz0Y&zv?gV~gu7n3yC<(vxoP$21iz=8^sjfP zUoMT3Gs{R&_DlUz2e2YqCA1|LQBme8&_LIw^Vz{Jc>$|t>%FaB~}b6_g1cgm9o7s|CS zdz#h*{UN+`o2{pvPtk9QXINz_en;Y`^s35xmFa~R9r^JVypW(jM_N4mKZO%X) z@jxBM&i7+|iZoW+XGvbYrn1~S_xQ5OS#=hV7@j$;eCsl4y78|^6^18efeFB9Z^-7< zX0~UCE|jlVv7Gbd6G#63IZsX)O)pLYiu$a~jSu^uQ+9p-o~Pec+S~X2&iEX3wvAV6 zhPLzlx!y(Tlisf{{OL7m@pWfQbzs0cXZvryJ^#t<)q1x3zNs@_XJzF*vvlEmJ(Zo> zC&jb%Z7sjty=~mXa^U{dTid4IlABq|M@0G^RWb-dV8*un46S`jjGByhT?9GD)78&q Iol`;+0A=@{R{#J2 literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_004.png b/res/tw1/images/tw1_fota_progress_004.png new file mode 100755 index 0000000000000000000000000000000000000000..4a0547d40383ec08dd8763a29e423b3bcec634a3 GIT binary patch literal 1359 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz4 z;Nlc}c%$QoMo5Q3Q-_uY7v8 z=F^rX3mRK5eto>y^Pb)LaDASwGB;n_tkuj&P%QadVQ_L|PMyi_64kW}8h2j*n(X_j zZj$$QiP%+>!Y&+$dHt&}e$x3#F?NL~A1<7BUE1xIab6+A=XbkR;&YP!ZCxiXpDmiE zf76kU|+rzg$vD0+WH_4y;_2_QmA3*e95{5-(R03E(dmHG zFUwYz&2M58yHw>_KOyD+5!L%?x$1wzcZcjgZEBsM$h&opXHosK_=CF@PgcKveuLW) zXk7M+r}I_5tNcuRG>O?$>{+5JE3eL$h12XO-SjZ-303q^;KTe`3o0fYbfH&an*cG6yb6Wc}1S zc{uX6V*b-rD(buI_H4>sH8=Refgs7Omy>Ob3;+C5d0+O|V)}AUU@%xY>*lLeW;3MN zY|InC}2D@X=l^EO;P4cSPBdX_iO9!=iXWHZ^Dy_3#YA5pZx02n+1(ijjnw1oD^}PA|Onx#clAU2j{9@syYAw literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_005.png b/res/tw1/images/tw1_fota_progress_005.png new file mode 100755 index 0000000000000000000000000000000000000000..418e74d1c52b6930dbdb5988d119a2f363e97662 GIT binary patch literal 1348 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dzo{NpOpKbCiprLXv9Jw=O4+MZP&Kfoob6 zW|#;~$X4}WVSOvaq?CDSMTRj8tE*vLH}9k)d$xbBvCeP(yRYcy#^)jJhv)9K<^;No zF2HBem2I1^e2ZN9_Q0lU&q;YVc^Ur5Pq`)M|EX@0^`sb&P5Cc&&!2wtGVf^}z707` zx6Ss>eXnLY^=5(Jq}`ME?A^02E$704Q(9Z!`V|?Syl1M^-oDRzXRB`P(FV4#pp|cT zs^qKgOr3jULdy9I<@R~L;o-$c7}v}Ry3Ol3@7%A$mY!adzAttXVx7LORhu3acspEO58@a{a-KdTM{ zExOz7Stl{kIwY&QSHh(9;LV3MfWu42HWh%#)y#jh;N8iHt z`%dim|I#8P>$bfsKby&cTX9~WZg<>KiQdAiGjjAuciSJ&O+sqbm{6hJDHA^F*fMRvjtbmtWF*-PD-D2$No#~Z694}lLNmG<)_ uwCrNci0(%Lc!D3&t;ucLK6T!w4Uq$ literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_006.png b/res/tw1/images/tw1_fota_progress_006.png new file mode 100755 index 0000000000000000000000000000000000000000..eecd8c0a2b84ecbcd85d62fef077a7e49867e2f2 GIT binary patch literal 1241 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dzx;TbZ z%z1lf<7=@}8TJp~XL|G5zbMEI*tB7R<8+NVN<{*e7p5$5DiUlG6JNa3e!*JDTc_As zl@2Xdn8;MPQ8QzMq7v7lHfMF_!^J-$z0ZH%{l56Tto@1W-1DC9d;h%HeDBYqJF!ea zmklQ1v*gx0ZiXNBD{t48PulFcuGIJISF6ose#M>){M&cE{jO#?{fW;c_sKEdo5CD# zJ2J0XnD;w<@}AjGdjFJP{_S)<#QfN~ZOv>FKw)Ojd)`Glr_Fc2SE($0V_DYoSNVW* zUi_rTH-GsZ>D={pzC<+>E3d)1rz-Y*DP<~^)o(aOOb&3w2H*AmROk4`=kB-N$L2UY zGWV1#o}AA-^Z2AWQpPbr?iJIk@t)_zUEJ?J3%J1W+H(GrcMi`I?tVMJ-YNp*pzKxm zC)b1t)Mj73$t9IgD=(4~xB7Nn^3;Vuo^Nb$tpBIO4msgw_sw*cEnr;sG12ka*-$pE zjE2k@kD_#i;uU$nmwU4V`J5%brP?Q#vtGQs)L7KyK#85!i8-ro?|b3B2xySieU+c3 z3Y*POE}WDIZt$7_3b;Q~grYo=Gvd+w9&cu{bnr=l9^fJ`?Y+MHuJ__oyt3Yj?8CXuWmZ?(3KtNu|4a=QsUxD0)T=*r^ZkE zvnAzcf6hL!eIK|hxbuCO4OXu9oOdcsvHth@_XnrHXSktPdfPs7``>?W_wfy;q&rmH b^5c4~*_!NL&FBAkKu-2_^>bP0l+XkKb+27v literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_007.png b/res/tw1/images/tw1_fota_progress_007.png new file mode 100755 index 0000000000000000000000000000000000000000..308bef51f5ab130313e15104eaf6f0e9b9cecbf2 GIT binary patch literal 1095 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz%Jb*uB0zROTT0#;eK3nXMa1L)$2|3)K__Bn$7^IXaP9K^tbKB_)0-^ox8Ki- z0o^rkdF#(c74dX#R^9;rl?x{CJTC(hO=mWmp3VNE_?AzY@GicIe5G%-0{iG()G52>fN}6Xh2u}HT zbfU^}Q4@z+c{ZST9CGh2x#{(3vp{s{1%}5rw9edJz~~nA>&(VQ3mA`G6n(a~iA}W^{(cVcg^cq zr;9w-_xmcSrzi-tbcBEpzpJi_GyHhZw)muz%Nqar|GpG^E@0&1ahv?O!=mTAgnqqY zW!#HzUJO28m6M*ge?Gc%T^`c`_VSw!3mCI(QkWarR(zbn%ObVlSgn~rMuQuti9_%0 z9EA%Ey+RP)VxU|g6Ym9$Mz)M84$N0(oM&U=4M;YX<}h&p$sG%?zx2NmC;`&F7Hr_g zX&?jL#9pWaO`o{;Q3X&+YWB&W5kM<*RG*sz^(+5ot5vpS3j3^ HP6;;B5-Iymn z2x{z9kz`$ZvFL!dcS3eZub080pb zun&0qm674w>|Jlqt6I)^(tq{w`*kbl^%rwVE!eQ@ZN7@--fdq^PX67a@n-(6Ww$H> z{$()yzE{2Y>%pt{Hq;xRJeKX+&$8kC)!hGSlaz%w-kS-x;z97bN^=Gw{;)Pgw18#*l{=aE@bum!ANbvT*2Ytl9+){dfA*X)x8@ZwIZ(83#>AbwE;|6N2YM&jv(NWPUb*kr>weBa!+Z48Q}*4;eb z@oLYRsdw9eZj%(B9CPm4^%vVdE1c}#z1QLECV!R#+@-hoPh2a%dd~T4?QQvM-K1lK zV{g3O35>=GfsygAX1&^NYbS&y0Ss25J*WP$9@dHZuruCbCCH7Qu6{1-oD!M<9G6X= literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_010.png b/res/tw1/images/tw1_fota_progress_010.png new file mode 100755 index 0000000000000000000000000000000000000000..b22d512ec384a7815a392bee33c58aebaa737f56 GIT binary patch literal 1253 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz74C{lwgCi z1GC^|6IoPNHuWksaWo}tWbAGbknR56@_{2i{d*qAvG=dv-8-DW&5CFG?#-M)cZ~u{ zL%=+wd~-g-gRm>pqbB{C^`vA{{;`F-t;*Y)*dik1Uom^u?Rs|UsY<-M<>V)CEK2IP zov|!oe#iUZ|GS^H^WS?GDS3K+s*Zp4ymqB^u(OECfnVRmzifTyRb+GW;Yvj=sRY;B zmHcWmZ^{0j_T+ZIl34eUyudQg%1qSVx-nLV=HQ8M?@^@rj^So2#yMIcZ zXVJdY89?jLceb4oe|+KUv_zmethFo4pFgP2|MPnDwV6P^>~7C@Gfu=vw7)xktr5i6 zH%qabX&m6loU>B@>qQlQ|0C;EEG^U5HL=~er_DQaGSEuH^c6s!Q~ax1&w1G$bvEVO zfZTK5o_X_6)R^<#-CoSDozc+xE9kw?ry}Psi&a01nj9!PKKYLI#GP}VoK`&y&F6KWR=}vLP$)g$4RwXR7p@xZKaJOfKgJYF()RbsJFi z{_}^9?^^Hf$m~)L#S0k4ZdmhI qnV&poQL_Hto8O=UVj#hT{ZHkK^QyNiOz6H0a)+m@pUXO@geCxNiDr-h literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_011.png b/res/tw1/images/tw1_fota_progress_011.png new file mode 100755 index 0000000000000000000000000000000000000000..ebb6134ee3c6fbfa5f81db7f15bb255f29c6a8b4 GIT binary patch literal 1342 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz_LH0Ya`#!R*s5=_qLtxX@M+I=o<-r4 z&U>4$nUZHwB*1;!k@-#H=Zs|Cld8An{!V^UGD-aRwx4US{VKb_P+hHRecIAf&u`O| zC+(MbPj3|qzre6t<8FcfB=_{5*m+OBMM;X7957odt>;ygb>zi;&v~n-Is*;dGUdrL z!D98_+bpBCTc)=#L{G`vp?A{UQ*XB6uk1e!2_Nwrli+=8r^^vhwPd18_x9q8w|>2eI)fQe&E$>BSB hE0}4O@E?5mEv|iXror=r7282}c)I$ztaD0e0s!TmqND%- literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_012.png b/res/tw1/images/tw1_fota_progress_012.png new file mode 100755 index 0000000000000000000000000000000000000000..628052f61f99c55a50ffda813519830a211aa655 GIT binary patch literal 1344 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzhhmqaqHOyO?Q+YY}^sP!)4vgy*F>py!+ec={uQ<)zc5>pP%Uqbk-;s zWFe5SKg-+p!nCTAH!{~B?b^u9!1E+!l5y_J<+p?KC9KcHnIy9_L~Pl1W%}ej`yMam z_MG>2_p|L2mELwXv0d|u&YJ$@@t<<155<#~|5~?m$Dfeu#S0p@UYz#JVbc0ZcXpgs zu2-$x_kLFKY45G&X%`MeWq9vZKl$@b+&Ryp;z^rxSFYDlzq&Q>!huuS-g}KtrhC4d zQF!uML!sEQ4(5o=+?Ctaep;RUYphqf`~9rxY&}~H%799MPC*UWia^v_`P^v_FG{MQ9pssojFWqR+m zJL&G(cV@?v?<(!T*Zs`g5psA#Gh3Kj^s7dd_i5jX?wz^zbjnoi=PH&KWeg3GIsK+~ z9-qGSc1yANwMGXv#ecHQyyTl3_htL>ie#=7F){GWU0I&`I_YF>u}<~Y_p`RM zb!{o}D`c2_d0Lgm$?Y@u&xx1TxTFD8sF}NxU+t&f$%U5F*2Y?@>#brCzBH{$<>bsi z|Fxahm*mVnCS`rok$EyO5^YZIJQIFS`gPQ~PFWL!P1~+Cd*1UfIsGI&fb1nL%9?z8Ypfd{^ zFMf$F);wu^Qz|m%tiGq*J^iP1G%^xWZny3(oO)bOt#ZZtS@P2bGL3)^-L)_Kp691$ zdhzuWpIqFRT^F0Q#53T+fsi>KpPq`&pL>eypYW+g7DpLvLo* qg&6(=BXzs(*UpWga*QnS`?P)fj>XI7=Sp{i^n1GcxvXwAcFGF~*f^S2 zv{5j`Lg0`8%C`wC-@Xir-u^=8_Qid!>SD7qet%rcnzJ+L z_C%HClVU0l9{pHi|8}3nVh{4(_+o7Q&sZSEUgZIxa=t>@$23D!r-?tX%`M?c;%L- z8D-zgv7GPyDP+>_sh_ieqN$o&Wqm$*O=3@%s53ixapC)YlIB<6Em+VvbFGcwkFZIr z(#^6K?`9?b*r{?}wX*QV?$3+aZl?krzcuLgK9zp8O1stH zFV47j-m{Olwmj`h!tN| z;@-Azx4UJ(vm&bG@Z{n>DC?*7(oqDjN^=PI}+myuQ<~KKdPPqk|nI$dU=zLjZ za#gBlmcj0mIvScw*39wn4ca4CE|fLP`thCO^Ls!4d~?q7{m-wr=hXY3|2%Iy&{?Bk zn1n#X=h?aCj0t;r9+yOxE~u(EobP-4?(?9sn`Pn**Nz+bv9G#(_2a7tX4iK=+D6$1->nf8+#hPL`)u?3=}|qOH#N1zW=Sl6y?XiT<*Q!*bH5UrE2Chy zttT#L9wYDWGX{R;TMei1hlT4XewzI1tLl@2#+e0GD+wC*X z+eHM)iJxd_lYRAO;eFeykFPdgo$B57Z&TGmt8FvR|BDGy6F&%)O_Nw&n=A86c2!h7!B-9O(v5h}jP#AdQ)`{S#%-Y0%8wF=t1YsUF~(N1#O3Ej-s zZW#EPhuD{V+{HS7ciZ2sr-=T=w+%dWl`aVC9!uCI33K{56< z`@i41(_k05H&Qkh7!`TBs$mDYq^{jD@T*?E{`|*}+ppff8VxjP_0*|Jsu0&(#ojIY z_Ow6uPG{kkUsrUCc2C#kyCK;ZQhobIwB18~Ris3{X7PRoCy{z(<>GDYLBgJ{elF{r G5}E+UY;H&Z literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_015.png b/res/tw1/images/tw1_fota_progress_015.png new file mode 100755 index 0000000000000000000000000000000000000000..23967d23167ad729a6b08391a1b5a908d92128d6 GIT binary patch literal 1110 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz$%r|-U?q`Sdp^)poNHt$(svFmUlyKqiw@&fN z(V|^ztzvCM=dPT$((ljt(|d#VZd{rnBj|Tw11r$}Jyk2Jwp8t@+Ele>SF(5XocP|u z!qL0L+*_L3q&GzPZQs7H^1H*=gwj=2J4!9(zt~@@4uAaNG2{D#ib+QprFEuVzWM6v zwZ)ynSMQ!J-%z=;s(9JnnT<_tXZ^z0pOsy-E9$RhIY*hdL+?*==?rZkfy03X(?`6rXdsmRpr^w1XTQrcg=8d~2to@5#O?pVCR&am3B+Nim!&xPM# zbL`=I-Q$nNp0V)$-hFAm_?Iic+#X%ODt`5O^=sG1TzS))+W!6x_#09iU%P#K+$z1W k>0ysQ+^)IE&@lJ6v_f?p^KDnF^Pm*y>FVdQ&MBb@09B76ZvX%Q literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_016.png b/res/tw1/images/tw1_fota_progress_016.png new file mode 100755 index 0000000000000000000000000000000000000000..8061447e551a4c145f86c604a4b58b5dd2630e46 GIT binary patch literal 880 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzYHyd zO2`A{L`)VhTaY=kDea1giEj2&*)Q3*sv-=8bZZpb-guvRU$$Sp`fB#uuUTL3metKz{_s}c_vYEtASzZ? zl{cf8NR|1kZ~^Wo=1&xe%1%RF5gW~#Nx@A5xq-L1X4_iC%z_g(h$mp|OPwCK>Je+(-hL~6MwcB+Gtny0Iu%Q~lo FCIEG6B!B<_ literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_018.png b/res/tw1/images/tw1_fota_progress_018.png new file mode 100755 index 0000000000000000000000000000000000000000..6096166554657ac8f69f6ab7ceb6c346aea8e3b1 GIT binary patch literal 1232 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzL z)G6lP!on)JHF(Mc_9dSG8XO%1K0c0k)3oHnu9I_b-mU&#d1~(5@3n~!k3T#!(--Kp zQ827Rpdok4tzDt#8FcQKu9jnAO1{d@n5^oZSIS;z9b;OS#=7^|v)hv5lVol_ z%dS_cG(VZ`e7|`f1XbHJ;`SNlXIL=HB+DLRe8@}`~5J>*G5^P z3%eawzRj5Qe3H$Kl>02Y`}{v8PMY=P^TPN4<}6?@n9A}+FDT1;#*>>W{;D_a182{l zG{?V4@8r*g@AZ7Iu>X)}suI`QdUwW6Zk_WgJ98hEiBGn9z^JSRQZ!sVpX%TV*|p z>L)$+eCJp6`Ol?p=lgrNY&w{5m@{LY!F{fqUPbwn_}ljVE<36WDujUGK-v#>!@`D7 SyEZdNfcT!SelF{r5}E)?n_@`- literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_019.png b/res/tw1/images/tw1_fota_progress_019.png new file mode 100755 index 0000000000000000000000000000000000000000..9de21f2aaac260b0fa769d2c710c9fadc9c77adb GIT binary patch literal 1308 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzAVZwEV2Fn?Y;kh+kgKY`SWw4kh3(ptRXZcYq!zKiz>_8_We%3S=mr{Yx^69)yuAI(?4158RxkvF3Wn$6ORKP znlE13PJi<5?EP{z%jhiYO-F1Fc-(w6!)fK)bt?1KZ`Mydob5SJ=GVLDvb?N4)0*Z5 ztX!*NIs3^gUBBOUCxxBw*KRUi*N?0Ab;Zn;XO z{mD|}n19uio=@Im_~q{X?lY`C)0^f2o%Bg1U$wI2m|(oRrP-Ie;@#e?JyV@owx)T( zE8lKZS+A;T-1kHAcsz$He?`exy zte=&9Cfw7Hr}q2Jq#(xCUXJ<^E8lKX(O0X~691oee95)RbG{s5e-q19HG9gfJikw6 zlWsqk**fpZ(uMEs=Gu#H@DllAcI!{u@ryY&YYPj`6=pl%x3#I)N(imES}o06d%bO6 zwfV_j&p6*t*JU1G6Q9f#AsTkUdc~D8=SkBi+gLnZYOl7l?#1rU-Ttg^!hkXvFLvj* z@3WrtWSh$6JAbNUEf3#IX5H(ublYLiIFF*!V$1)|dU9*w`?}jRLk{F60%d@aHRs7S z6@FFA@Ak{*hMn7B9_jdAXz8}Uo^qZ=N+*41*Z-gS1rgJ$=mg y$Yalazyxq(k}_k#!l3BztlcFyEpcRxW3S?)Jf{a7brO^Zsql35b6Mw<&;$TX>Wv)$ literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_020.png b/res/tw1/images/tw1_fota_progress_020.png new file mode 100755 index 0000000000000000000000000000000000000000..e555006ce5d11b92a414c9651b3421f276a4e800 GIT binary patch literal 1391 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz~}{kk=~dQ zx>~_;O~FOSMN%3}oVT`WP0SK*I;glNbjtFhXKp-x^4O;Q*-pDV)$!|}KKG7RRA?nJU%Qi zorb+P76936e^q|Hm)!Sf%da)QQa4nsoO^IXw=U>}i>0dpo zE>pRwD!`L@cf#`b3#MoONH1Mj^|M9!`%^!u8-muc7eY^)*aX%VHczbn%ptddxoqEp z)zdP6)P4QHru=;M{NB&M`gC2Hb|h8@f>p-VmNrkcUL6lK{T)bL(fY6Q!)(dtU$w7p zHp8P=V?Ct9*M=#sdZL}mEb z*@bcTdzX4JNZ&r)v@UAdL+h)~bN>kLF%S0#n!ohzQYMR?dv`bQyJfLHennlt-puBW z@5A`@FMoLdb_vstZF}`!tO6Pk`getQ^e4~QHFo=b4sV(p!m$3m0@tprIoJC`i@%=Z zJvMLsyVzw9`EPr&7VO!(7ib#Lg<<8P^>-8AYbXS`7N`}621L-fK)9*{$hL`79 z{L1+H6&Mx8zg9B*yMIu$n!?!j$WFzYTx#U zFMhuI{&>$k`@cZ@%O*&F34FXKZiQU-X8qOESLcV_k689_$@xg;oF@wAFBSvCx9n@@ ztM}49b64BNtc~VmoxuA`6d2$8t9I@B%W^z^#XF$-{M){)GMk$3FIW%c^j~#fJwN90 zizwR#a~gAlFSzSm{?Pxb`08})f3kA@K+b7%J<);{F@-Y8K#zypugSCh^f7<6_1?wI z70Mbft{a|vtsATLa`)=#tN8UUe|WwbXf_vXEicf?tM`T3ZudDHoIaPG#LU!C`#GMm WWc9D#X~$zhT0LF;T-G@yGywp!>C_nj literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_021.png b/res/tw1/images/tw1_fota_progress_021.png new file mode 100755 index 0000000000000000000000000000000000000000..a2cdbe4a786d9ec7b0980ace511cdc74a4272b5f GIT binary patch literal 1390 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzR!_J}h{ zIx}>Z@nxnMN@u1uuZf7zTr5*BHsz#D_jmvGi@xj3sh(H;{Bz{J-)n!z{;m3Tw|M?+ zpwmXdfP_H6Mx*k^Wzt@g+$X(xfBVymJGBg1hOZm)c0IhMlI@vyv*KmK{b~GZYght$ zBiTwW^X{HxGylm^mEGI+ma3iHw@=sp{6+2sYT`P-m}lo%OnB0*qW^sUVN1_%DwV|- z=Q3n%xgZSGv_9?cl|7TU<)3a3{?54K<|6+K%iW&c1KP34b2dXr-a_VG`KLds9Cvg1 zu2z}-$ciB}`UjuYNn_7nf;-!1o^`qh4?N82=p1U2pJ}YlW)+sxNt+O7p z%-yH!K1oJiaIeY9i_4_-=4=yms7;f+AT8(r>2k-Ne?8Tom=l(s`Rjei+4G*fpzZW0 z-}dRw_lx0NAZ2>zXral;hk_T4J@andNMv5K$1+@I_B@|YcRTLPQ+a>Oo%wn9P4<%e z)9z2Qne$}5;K%66dyI0G8?4UQEttF{|8%-%oRnn!!k2Bo)z&Zvv}&<^X}dnD#>l98 z$;-Ca%XF9xw%^>Za%bJkw!4x0U*^5<__5tHugFw$!>TMR$L0B_`#t5({7Nph-l=wS zBhcZqwuv6FStWJB^V0UGDaZaBJl(b8 z*x4%I)9*}g6IXu;3_pm>*9N~y`*hVO*;pIxvp#v;*F459QMI9UMb*)bv6p$XJ>{e& z|7)FW+^4(WFM=~6=<56h+bgY3c22zcdh#B_MDd1`x@Up0Qe<{=p-OyT$NWC;e~qf! zO|<)bfhJ9S@>wPPpZk-PNxRpYH>7SiQGelE8@T&E#%D l@?~D{?cVIv%`q17e|T$u&)@n>OkEUYvZt$`%Q~loCIAt;y<7kQ literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_022.png b/res/tw1/images/tw1_fota_progress_022.png new file mode 100755 index 0000000000000000000000000000000000000000..e0807ab9b6b526105dd43a807eedc4c30513142c GIT binary patch literal 1342 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz{4_VuoVzT;MB4My@)NI8maY*AGU1-oIc0_kw^EANl)E{9 zA~ojTxH0pSx~8jF=Zqk+_D|`}-y`;X?>&0D_TA3sF~!g8>`oW&|6Waoa~wQ*K_L?PR{jw=T($Y_Vcfb z`m{CN36FL6G_AY+Z;#4$m7Ufn&sO(*jJzJw?zVzAVX^L&1+TZ=_xcq2FHZOW?Cjmk ztW0-kF>K18Sa3b0UZrxoLRCtHCBvJj6^`fk#7x+^HShOd=3{ILX%E@%nqGDHw3{nz zZ60=!!CP`uli#H2Tt?ro*6rS2@)z3i9T$=R$I+uP1DZa6t@@81t4j?Z50 zdYd0nB-hZpIRs?FVU_oyF8#X3{0G#e9y8txW}W$Z?IK1oW4Goy>yyt}cP1;JVclRj zE$>2X@K?`1aTk!J!8N(3*C*EmPN*(g@{{3Q)nbzu>sD@?Y!fK3cU4~X??sGUJ(Z{4 z_o~E;J?XQK+&K1^Y$)&ytU~?Zt3lKb5~x5*LkPj=Jl)m+^bN&DDU@L&eseP z-jhv%F5Tz%DaP?jm&$kFQ1%16W<61S2y}`5sdEpfdOvfi_bdX&=6&Bt{sUGszqrI- z53yIT+@VmFI7xij8rFonYaX5WdQwIH%*hhZdr^+M4B5$-qGfi!+GaoJ$zzr0Z$5rr z?fLHgtXJ)!SC}^Fgzopr0FX+kf&c&j literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_023.png b/res/tw1/images/tw1_fota_progress_023.png new file mode 100755 index 0000000000000000000000000000000000000000..c58fe1d16dc07b02a20b633a9aa744233a890bbe GIT binary patch literal 1243 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzZvE6V!%J!8^k&vU%7#ZTE%nSaFJw*GP9+vAfe>z_wy-rt@2@1qKr)C0B~ z(Z6fbCz*47?pLj>-f6)gvm^EG=W@?F{WJ6947eGx|LMM1nElV|lW*cbpWFT0^`to) zQmUH#CavfCT&_}?vQUR%%}t#b`dVf4qLerof@ibtjo#=0j9WS{-cROfotrLp zis`^CPe=Y(W3`Di9!Yo*26<^lba#q}#_(tK{?<+ti; zD%xxq)`)OdmCkM_8S3j3^P6wV`j*TPB7%=Ny>dXfX3`Sj=N`pl_Ar3*)oV3>yvt1y{^!w7b2Bl|ed-t?Cwp z{uT3Cj3LM10)zD`m7jJK3@=T^tOxTbcLTN3V&g zWi?oIt8t#n&Wk&^8Dw8K*2PWSdvg;|9>@%wxc4rU898z9RS;9vbK2*Vg_F#gZ|;8k znqkAWy(ZsoI($2qv+-7TBwK^<-Nrhr33HF-^EF)bu|DtbS6M&hN#P`SPrl&tJa&fv y4&@8@C)u2NuNcSwY4y_@qY^*%;gr}8)ISn0*kzX8_u>LLA9=d^xvXoFtvxx=<1Z)U6B7XCj`qq=#5+CCoTn?^Su%LTUtB|6ZWLaD3 z&dYahKB$w|@hR*ImaXI2%n7u5n1KIVBfoFhUA|}XlgvraJ?E+1^#4?0IA7Q73U9*d zuk63#CW-$)vFG&32=&S>GtTp=y<*#NwXEtq|Fx97d4J^8EPav|FscPqoqx@?>wV;E zB?ca#o;uZPk?Y0>QhqVlZl7cuaVFhe_cX(XkVz@!?|;NhlAikJ^tV!m7bW6f=6>1t zBI0rAV?Bm1CCstadnfJy8g`ZU%Ui)nagzfryBhbID*fJ-D#*}wjPJ|wqcz`lmr62B z1F~;lb7hdw+FgA-eNxQ&C--~;*&3EkdJ^?&{ta2b3#<+E@)l&0Qe|h<$(osqI2fE&PcHR( z_E`jEg{NMakzPgvuZE{yh|&FJ8XzN!_D%X}=L$5@YtrVaJ={_W%wD#WbP0l+XkKYWeaJ literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_026.png b/res/tw1/images/tw1_fota_progress_026.png new file mode 100755 index 0000000000000000000000000000000000000000..52b228e27f19260e0b9d6ee12e73ec1d27ffc35a GIT binary patch literal 1249 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzBAp%du z*n~bY3rQO)E@+)_D8#I9qoB^0TRxkNAHTb^**abAg`NLq?&5u?qxaUFIXBM}=&nHv ze)wna{#S7O>v{V(G7SIAf0r2+>z#bN?REZ^*#B|2zxH3{V|BRn<_Sw} zr#*SB^8EPXXUDs4GJM-IH}Asxlx=e+KS`Lh*|RQV_rIvyU)P6uvTZp2cFThM@)dul zsXlg!&U}9ySiC$)jzO)B>(|$&^c(XS!xC03xUW%hY`SR^gF*J~*KW7h)mxoB&-~fG z*Zu6oT@x8R#PTmJ=YF<-l_*O?WH;BZtxZ4IXR|UUT$={+UZcu#wzPWxPq|-R7*uZ7 zHP>056lUHm4h*dIrz#m{+*r53U+hd>upv7`@ifgB+@i${2G8T=Hv?nfqRRJ4Hk%UO zovXNFvwKqrL(Wde`6nI~`AzcHKEZTg%37|f#R>0<-YPJhxs~e}zj6+9gQf9%NB?!= ze@#ywWHr85&lb`AllRw79lhr&J2x)UVepx$|3aKQZQXh$4u;LoxPQ4E?BSJ4;03aN z9QbKJ=|@pSgK0&;g~{BL;v_8UPydx>cwLzA>ib_$JC7orlNV2(|H(ahUv#iugKhrp z{1DGc+g{Hz`MT-G@yGywqL CdThr4 literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_027.png b/res/tw1/images/tw1_fota_progress_027.png new file mode 100755 index 0000000000000000000000000000000000000000..75aed04b246772ec8f1865e5cb4c3eaa081990e7 GIT binary patch literal 1332 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzbC&WuArDw-)9J}eKA>E7GQcE<0S{>;12HK$LvTy9l;$%Ur==c7( zI{lNMeMA2kh08N|8$M_I8}-k6&g3U0lZt`L&64FAx(!aV#a??mQRV)VPx&13>Nhi2 zJ$fW#%NX-o?f!z(yL2b*xw`P0uxFp&UH$_>XFduZpX@33V#4n=E4%!c<*_Abs>xme zx@OXoUcQU*li&E<mhp?bS_Sj{xWlo{JE2_p0qvWDd_Yxd$B36U-joE=P!qsY5DnHWIk}ocdO(4 zmlJ;4o-7u=${w-jB6~^XcJ)a%HxzeW4>{_ee4YJ<$YMUAHh$I0z0O~pChaxMX3m+l z(fq|^&v&mU+|FI~X!}H<$drq0Uk-lzQ`G)q=bCjgtPhNi-C5wTwsW_0-u9JU``y=Y zZ)_hJUM8b|oiYVYyL~oO>a5`*U&kRqPu+vgKc3zus9l`^i1ii<^Bz zZEUv49oQz3+-x`R>tRdJILU=#2d+sZJM6!pSiEgzm%iHy)(xg?ydWPfyS<(*UN(q5 zL7MmOg86SJ{M@y&>pc54#v4|9LEdSfY;#ZX*3(BS40?ts&G$Tu?#?>%Q)NEi3dRjv zt3U?idll_+{^Gk|isi-f_iVLVC)Z{h*{lCt@cc95wz&I@e|_4|>;}g2#m_$(qThFc zjQpPdcj}^gwaVS$?hGm~w>#QTSrR+>=ZckG-L~_14>W4aUGNQkqqQ-O_C1c|{quL3);r0C<_&AjPSsxU47&DK)^ncUC+A>MzkE8U f`VnDW!PY;_JVnj^JKHaDgFNi%>gTe~DWM4flZTsb literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_028.png b/res/tw1/images/tw1_fota_progress_028.png new file mode 100755 index 0000000000000000000000000000000000000000..dacce447139c2f3df2ce4ecedb4432e08d945976 GIT binary patch literal 1377 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz~$3f zs%}%cueP)5$d8pO?aYEUc2?k`xl+QP`=-HHdlgNH^^VxR4nHdKK+wEsd}n$fnl_dqk5&@ z$ynudexP#>Pf28Wwyi_AFX;9^X$GRyWiZU?Z)fo*!zDv zw4{+iEa_X5->0leZxa@St?Ib%diB=@c>+sscMR(A7OuPk`6TUgkgDWc~l z*RMAdcU^by+i&vau6Xb>#)w&#;TQ7NcBUPRZnVv zW6eB$(Ny`(*1NZUtes?(RP+Br`FlSZ&V-52A{_HmVl4MBpVR1l(+gys?#Z*tZuNej zo*XG;5X)W4YWwBxNfmRoO4XD9-)h^NeYv}SwI}NapUt+fVzX|~eA268eSYVcYZuD< z*Vzdk*mS1sOx}y#$)0(>pM1{!nV&G}&!i_WcN#Gk0K?&1&~5dl+kOMnB-PUWs6ix$ cz?${-j9tqYtdTfX%mdQw>FVdQ&MBb@00sZ6+W-In literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_029.png b/res/tw1/images/tw1_fota_progress_029.png new file mode 100755 index 0000000000000000000000000000000000000000..d7ca410cddebe4a7276ec6d3bb2015db598c18b7 GIT binary patch literal 1328 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzznVEIx<|tPI6FE9Mz2lj zRCvZL$lTS@>bP-}z*bR5J&ub?33lB#6FP40C^s)pPk&Z<>Za|7u=jIpKX2v)x{Czx zIWWsQB5QZ%J|$QlH9WT;sCngnSNo}Ol2`oii=0Wj+xPv>yY9@W?dlkx^0;N=v?ou`Y2n}^W>Uf zGCzN9dD0?}16`XP)it-;PIyvsY-;f&nfVHQ4nnMRgKl5;wDT;w+p)3ObDn=u%A^2> z$cMu2D|727ZJ%UgS@h+)%5k7e{+wFQ^y9jh*q3A7jjuiVdS(79oxHg4eckRy3mNn_ z6{+_H-ELHgPpz@sKk13xQ=T`|rruiMox45t+sOmW%E!*BRF=Hh-M`F}wIEYF_`=d{ z)syD<6#ebkIDfK?+^=`-nL&&>d8&RgOSc{Nv^%|{$ZqNry{9~9PG1r)S@||%lCbAG zIm2&dli1t$NdwLJ@PFE`BY|1fHYcrb{t~{pQzhH^{$9gat%kLcx0>{}u2rqfJ#r%6 zQ%>^NIzJK4gegmPUIg9V>=`Fz_^EnQd)q#1+d!3ui__LE*dBOpzlx>Fm%IMLu1q(k zEv=eZApP`D?WE>Yk~g}ir8VnqwVnFpte|pydfBxf$%{M~tc!N)FO8R2x=r1vI{Qx8 z+*51joc94*aa^npsQB*0C$n?@#uOW!oVf7)Ilt*#3D3p;vDtpPyWKPH&ZG6(=?RHC zf7oi{R=%Bi=HK)OY1fQ@Us8U`qtmif^Mwj9W~M#4`{%oU^H-JQZTo&#e-CENIUgii zGHJ@KKDA2wlcCc5me~y4nJ>AlJiT&j)1p8B+bP0l+XkK`k<7` literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_030.png b/res/tw1/images/tw1_fota_progress_030.png new file mode 100755 index 0000000000000000000000000000000000000000..ae0384d8e5f3219d7ce9c65f67ad7714f24b20cb GIT binary patch literal 1260 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{DzNekhR(WgY&N;8%oSwUTHz&|lSitNn zXJi}xhwZwhQfYD0zV>#FS-D)od(9WR!MmyyPCoYZQ@5P-N{mxTvF>Sw^^ix?7F2^ zX?=LgpZa&NZ$G=#rpy?9gvGY`($(t8b9_HN;Od|2_31^L5aaC=EPLC%!uiuQo*j3y ziJN@q=JvDaFE3--cC~RQa}2jvc)m`o?c^uRd$gaY{4l7^+!bot|(?soCJ*VR{7`iEctIWHLKDj+z} zxar1gwj1$ng;pVVgYJgjjoiB_N-yr-?R5_lthQX|-SEAwaM!Y3%cH`|L)_0*{rv6a za9B>@0{aC6zwT?npO~-iy?XX}ZY$Lf5?K^4hDxR}Wu(DA{kdElO|SjE!~$e8OME zfQA&j{(AKC-2ZIH)M_HQ|5t;+6!Hyp39|coqwKub!ukc&y`jCtJYiX1!|o4 zQszNC#|zzpwBC<7UlU4i^0?Q;?Ty_VUArYpuWt53o`mTvU+m0!F5kUceD$N`srs0? ztNeC8=J`EY_RGJrJ!jiKt6zP6ReJT)N2__Sv8E+7-8&8ps8zp~?Rr!{<>$7lwO{AU z&76|h&GDi(Phz?Fs`Rp-H_l(3ef8w4W?+yUKPJtbroQ0&&cr!=+xERGQ+&O`fA#cL z;o+x`_HQ<0JLBh&-Ky`m%aM+N;du% iC{d1r;S~Y}4u3fnHWaZl_Nr-teCFxu=d#Wzp$Pz>Mq=au literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_032.png b/res/tw1/images/tw1_fota_progress_032.png new file mode 100755 index 0000000000000000000000000000000000000000..b725184841a55745448f7d473b32b289ba23be5f GIT binary patch literal 1022 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4mO}j)zieQK#H@#BeEDsGlDRqh0+%XAVZ}p zB%;K*C^fMpzledMVotHoNq?`<0v~Np-Jk+rZ*N~cO*RI{Dz<$K96i8)P5)ygT z_=L$(Iq7o626mByTc?)vzx!+R;VHZEnKRX2jQ*sxC9rj0tyo|cH+Rmn&95T9zBD<$ z%72+ELdE$Itt9!yX@e zl~cOzS5egY(B)}8tnY1E&t^xiIkxcEqF>9b;%lR8V`b+Vi@$N@n$;_|`eVRt)jzSN ziL?6Cd0BtAG(B4i6g&Rv_p8M-7a!R7<=`F0isgUj7PZ~f$S~V!QqFMWd`{tplUF6@ z?F_Y@^UU#U_}3LxHf#Oo&0d!L_}%fA?dSdf=4^@R-5(Oa_h9tB_3y&=hksx8vpDMg z`ss%coBza+D&<^^7O^Q5S>@bJ(2Rr6QR zUp4#c`m1lh7X2s}-*j-^vIRF!PJOk1UTwg?#k<1pX6&9&AFbcMwsO(IdujZ$WP#r1 s&wVc$AFtnDUHlvrt)pOghd|ls;4dLQajx1w+(91oboFyt=akR{0E=M$rT_o{ literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_bg.png b/res/tw1/images/tw1_fota_progress_bg.png new file mode 100755 index 0000000000000000000000000000000000000000..10161e19cdd5eed4e6c3b7d9dac69ec4bd92c072 GIT binary patch literal 11254 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 R3t)CZhPo!m%B#)^{|~?=FyjCK literal 0 HcmV?d00001 diff --git a/res/tw1/images/tw1_fota_progress_final.png b/res/tw1/images/tw1_fota_progress_final.png new file mode 100755 index 0000000000000000000000000000000000000000..7959b95bcacfdf3bd6558a9f38624498a3ae34a0 GIT binary patch literal 17677 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 literal 0 HcmV?d00001 diff --git a/res/tw1/images/wc_fota_downloading_0.png b/res/tw1/images/wc_fota_downloading_0.png new file mode 100755 index 0000000000000000000000000000000000000000..9f1733c86d79ff3979582efa952cf9510883b685 GIT binary patch literal 1221 zcmbVMZD`zN9FNR8d+x?&WvC1c867)qE_w2HN$lC(CAaogub$WAdf*(FOP*^(FE2~d zUaqpW)E739I)=McRva6S#~zMh7#7cus3kOSM{nZZd(ii5^`eZXhk{%+7$OYF`PQY^OiOV zOHeb~hdzgc7`Dka%hjM-cv99KE2%{?$R;HHr# zCintfa1}UZj?8&*d~U3)&rR!+K@2^C4~8-#uwbC!q1Ci~IZP9)yfRux#}t9DiUiYX zV$G;(p@=Jv2XQ{hk~$3lE(l4$@qz#baE1m9MWZ2*fRlMaW>R?PA&@rDXvigXUq=_( zrHQE^aAk^WwOYv*n{>QM3P_R^aWD*tBuKw)2UA3Vq!(-N1BgJYv-9&PIb<+cl{67-!JPe=J^?COG1 z?Cz{65=7R>PkAOviq=#eea3=zkXO?Lx=9+QA+rJt0nkMfNSaP^OkE>2rY@4a2pb&3 zNSpwc( zDmhkRXh8%(WSC4gD=A7Q%d@7x|>?fH^ zo8$9dFZtP(`wsm5et7%p+t-^5yT2Pf-UrTRk8-n#rI!z%=D2Qhubnyi=#`y!SG3r3{a+pI-E#HQGXr~F{`EhWPTzRyjuYd6n7O5LZ7>-s%wu)6mYN0TV2nuGildmSBYu!z@y5QDjyU;}tnoXwN*i9xT({8#a z?LkyL2;RJih#(670R=%&^x#4CAc6>@C|<;SQ78LRJ(L~{N#-N(^E~goAGuPVKCvq` zl42NUSMj7-q2nI<9NDp*zTcQnbvhg%g&LW`^Q2{kh{-v)jzH0~7ElFQ&dT|hXo6t| ze79O7wbCiw#$MV=Y|^n8P&C6#OvZs_FCqf!Xu@4m)`aOvE}R@DQ;;>^1#JkF#utSEuu2n`c4Cge+#+u2Z#A85lT3Ku(LC zoq-T2N*YSCqQIj-$UuS5&|Bf4q|1sfjDz0AQnk>T*DK~!Pm8XyY=e+M=lNEvm2Qb? z94_!s)3k&`5IAbVMJqnBV$P2a_8CkR*`XT{7yBS#wCZ??WLfHI_Xu84Dy!`XCAijbkycF6rAM*$MU>dv4g%U&Rjea_GX;Q4F ziR~p1`J`xOS^6dIxQ;F=B7)FXIjC7SCkb_nvxK_J$ts$c1VNJ&B=vbV#Anokra(y( zrxXYak}8ZtO@>lIHlV4hW*=MhBVzeB>TA1+b{8vdiq(w}Sp{;-sC!})h3+zPrb6t2PK|zh-Z4 z0l$s{W$f9Zo#oQ=K~y=Sz-VH literal 0 HcmV?d00001 diff --git a/res/tw1/images/wc_fota_downloading_2.png b/res/tw1/images/wc_fota_downloading_2.png new file mode 100755 index 0000000000000000000000000000000000000000..e9aca8e31e86611e2edc3eab60193509aa405448 GIT binary patch literal 1225 zcmbVMZD`zN91rW(ZQY6;3|SA+G?igtN$$y8lkCoVm)y0dyIZ*)?3jp`OP=;(FE1vk zcP)ZlDaE-H{Ll)DU~zS*l)*r7GDIv`7_Q2wli~-NQ2k=D6hZwU*5}&0>W8uqh9u8R z{=eVv|NLKac`(!8-WF=ZFswZ_pk~o{0zExPTG4w|U6Rqz86@(-kTV=qG!J4i!zn^M zWoaWY3pHc>#oI7~VJ)_q%Ln=NIazlsN~_yYRm(+a42$$tT}>Z_0bYb7rX3|VZ+%YS zrV%AB@ab^cRba^+nDF4xL?)+CjOvm>^gW43sxl(5V4&eut8DvnHA?L8%4lBSrU`t< zBp8hnyH4fPgSg^&5a%hD)WZPafx^2_ z84IEW@^tqImYYuR5!-$vP$*<{RdZ=Tg=x#GpKHh353=xIH}VhcO>GltH?Z6T zv9jVpEpWV?}GR-tFU1dXKUSoltiWph7$ zmhFwjl?1CWVL=2yWSCeyE-6YZ&a=Fz5Dl#Hf8$0Yhv<5d{HJJ|Tc{H2)4dizi@hd- zHtHM?waB&Bm6NEwwo+;=SN*>D*Y#gnSFV22&adBq0yXWAi3oWlcH-Gbyk2+hwzRw(-t|)xr zw`=&@G4tl}uIaDtE*(CTdEw-{i7TI7dZtX}SKE*NsMQ|6_w+*RBDi=bxPPTsUOV)B zsB8HRkE0if*^Rqf=eQQx{qV~<=9~GS<_2G;POl%R-AUHE%!Sb8O2@kQ`0N@t{pg%{ z^~7Vz%ZO|%62E+ns zEd}vNUdq5Yl+vTmd=6VNY>TQS`mDZa7cXmhmsGKF74temV_56HqAtlFciG6K&Ymr9;d1y&^F`rXSzUU{`czHCh zY?B1OW@2Ui#JW>`(QaJO42XMOv{QBifHRB>c)Sb)T5!q@DAJ8?#tA&Um*FWNUcCsU zW~2xCxEQW#p_QK)vMik^$wHyvD$p*?$dG{JxC#eFIgy3a991o;=v2*y8iNQ;*-&&# z(Nw&`D5bO!%TFLr*N>3bqtOjw)vN{zg^VmpItg5EGM}%UYt7oU;_zQLHnlbrqdFwx z(9}i@8RcWJp$0~=yR%Tm5P8ENFcg#&DJN?3NFJ(IMD!Eriz}_9d77ai05aHixy5;;UxisU~%QziykqG&#_I zy^bB9oNFlCS8e>=*SzIJj_y~PzkY5!W?LxzFqzr&cGuA>u7hte)4N_@_1`eIotSMZ z9lzPRaPRZYw$c+HJ-T${!tV!G=JXck9be?9E~@<8NxhdHPQ0}EWz)&tmDA2_vtwyb z)7CB9uQA-?BQIx8hhw|HnYn##|H6uKG5Nu-k6bu5_389?rT(s?MzQ^huWcfuw_lo{ zeQ*N*^QqS^PnTPFH_bHW4(7^J9g8;=@yx|-O0LYG|I9JH_{Qzt2kiH^amx)``&&AP zvyUZzj5&_@51k5UXXos1?yp@$jjquYU2H g@O{VMoxf}!z#hIe^Yug{_DAJ!6bZ$|`QX6#KgY+l`~Uy| literal 0 HcmV?d00001 diff --git a/res/tw1/images/wc_fota_downloading_4.png b/res/tw1/images/wc_fota_downloading_4.png new file mode 100755 index 0000000000000000000000000000000000000000..081e84e031e4d079211aba222d0eb2e3cea0498f GIT binary patch literal 1175 zcmbVMOKj9e7&b|Pb|FeVnh(QjfdEC;?;fZ{lNLjV#8asSf^ung0@_OxV(=W2$Vy2 z5>=7w&t6zVgB;fz1+_Y@S3a^l9ExsgBeuhsp*e1Fs2#iB6r!MkCW9!)KmFl84+1~O zpVKPYN^GNMP?{rXY;L6H%}sfx&kvmhgKdiugowJJ9ZpAy)z0x-ycV0M+Y%49Oz2dO z-*&2A83i^b2xy`rcv%R6u8UCBbRB*GEW339s+Oi(@&M>uJX0h7gjIEhJ6dd& z;2Gkvd`ukef?4cd zE|eNFZ>*0=z>?xlJJ_2EQAEp5j%Qy)KkzL@R}h4rAwbjh1XXUhf-5%+K{L>VD$Ay- zBel!38(xNrqUIgPREBj3i>e_HKvRQiQL~|A7)}>kjuPrd9_nfbOuK`%Uy8MCf?SG8 z4ddx<6^u49#Yq##z#h}V@pD1s<5qGaP0{v=9Yli9kv~ju2)1Hu1-t1h%0Rwg7ZqF1 z>IQ^{EawXa)3);kP0$g{H3->PfKUwfEn%}QCgKu8zKmF<6+gGj*+FZ{;?%CNJa`V8-7wNB} MTpV$}D~vDv1J71_;s5{u literal 0 HcmV?d00001 diff --git a/res/tw1/images/wc_fota_downloading_5.png b/res/tw1/images/wc_fota_downloading_5.png new file mode 100755 index 0000000000000000000000000000000000000000..f015a4e732ba2e1eede16c7318f21ebae50efc60 GIT binary patch literal 1217 zcmbVMTWs4@7dRpEO?U3-;;a zh8Jkjq=8x?#HMwyJr$wBfHByGi^?>KOT`Nt5@H~vF)^e~li15N9=IL1N#UW|1D5S` z@&A3_fBuX2jSLTTc5Lb(2%_eLEPb3r7|k#pHvLjj_Z+4JhVNGCWyZ6p{E<;5Rnx)W;rS9w@*H! zNXtx7qe4EB_f%N31{*#sHik<^W89EUYWw44U#MUL8zP+y?FlDP!W6a4tKfOG%~0gB z2^vpPD^8X3Bc$s3kQCw^Z6p97MKKO|K@`DbB%1&%lfbt~16~nCg-w#pi^6KYSyc*J ze^U#uQdA8gPhpsPy&kV~an~PXfGo=q2g}mff)1t}q=&QsJl>jurU6`j`EibM+% ztnw@?^CIM1JZs?r%ZebIlw_`71R%>xY!b)<;Io1XG)dB0*qjp}-7#QG+rrvSZ1T2P zMfIVMT)*VH6Rj#3skz7vYOY7BMUmV(YB{D`4|<{$t(;hczO@IM{l06H%Q050HS}4I zOQthwmQ&e;C;=d`Y&w&XRW+RvI6+dWCf5AFabvJUOjIQQDVo+6uEc1%+5&j7+C+I}r`IdanJx3%UVYfu^kx68 z7aM-V5sMzYqOi*n%#fq(fb-N zv|XEisdjKSSV&AEIPAsJH}wc>%H`P?H#R4d)KlWJD0A|>Ida|_jEnid*SZ3 zc1`$#LIQCT78#ltCa|a>2Apw5qhv7SU=a*5qY=>$#!OTa6XOTJ>C>&9epvY6ZNaL_CmQ1uY@`^PgF zswyEY?MsjeQvi9jr)+`#a&Jm556YZ^bw7>%T8qyeW+kq0QGsixJ*(M%Ca7c@v$uR7)p~AO_1V-iyOUdy` zF;>-rs}PoV9Fr%AVzKBcdOe0UKu{dVRXAuGhZeX!qB~Lv*X?aJ1`*h@rJ9av=xBve z${IsX2!oz3A3-w{i4|hqt_BK*j3`MaL3v0*(<sA;QE zyNdPR7t0G4kQ~EG8AhR21$}wLG3>lyqC!85?o6w?VifJpN{W_GECNd%21?8_G;}G( zyt;}$?e+S@5h3aoXp#+3RDh<#kq9RU;fT-c3kX;htNh=%5zrx`QY8N=n%Wku#L9G~ z1>j<(iGU6}$AT^L#6=hE*9UgQ#c-;0``*6q+%J$DUp&7-S-0<+>*=;#@2=T(v*C8b z-Sy5|KC*jFOPf21wR8;M{q0=ic(3c2J$2*2S?7x_6LS~-iWJ(rv2QP4`?9s`ovp3k zMCT?q*H2%)fy;m9gQ@F@mecI+Q^!50+GH%-+sTYc}#9^#6P*!^vBDMM<+LYwJMCB>t?;)TfmL;nC%5~|ez literal 0 HcmV?d00001 diff --git a/res/tw1/images/wc_fota_downloading_7.png b/res/tw1/images/wc_fota_downloading_7.png new file mode 100755 index 0000000000000000000000000000000000000000..023aa8e9e491d000af66b8834fd19019536b953e GIT binary patch literal 1188 zcmbVMTWB0r7@oK)A!(qELTid}n7mkZF6Yc;XNGLk-I!AlDRlD zaX0b7O$BL0r0v%FQba+;DirgkZAC0qq6i{QL5m_*5q*;SpgxH8Op=X0gg!XT%(=|} zegAj<%dAXIJT}lb)JIX&K$tM9O%85yssHoG%`Gp6zj=!Fq1UR2vd0{urMfj z<}9vY(^-7-Q#?XZ8Q-nelX`hvvjdMcQyaGBg#=AeBcrX*wC8XFEIjM_Ir`U2AJV{e za&%29^W{*-4fpU;gr}D#s`k>HtvdARK`_$N2!V$a6STZ}Kh|0~dV^OZ^K_e|!G=jP zm!mgD)yq>r4@2$8zyexgOt& zVs~dpsUcCLO-3$BiaBot_JW7~q-5l1@`ZI=M-yZLLue}uR85-^k!3O_vJ^&A@QjF% zD#}>w^6Z3%2+6RRhN2i*YgEQkQANX!aDyqZX6NBrA6|eqUmmtN=&EQEkG9AO@w{Y zIT2}*p39H_MB3}~l98{rZdiZazCD_GqrI}+cWnLSYu4H`=-vM7N3R^edI3}>)!qGf z-O7Q3{kJmw*PZsYzlRSEji0+ebNBL}?0Q>Ri(cPXdGW`-z0t0o_isM9-v0LI->!Z# zF(mT&SMSr$8ntgee)G8%tG4@>!TJlApS}3J^YXsT>fo6VhE9Cf>GbHQzIr-*oBrq# z<@)#W%HZkR?QleaiMVR_&;@#hvEPL literal 0 HcmV?d00001 diff --git a/res/tw1/images/wc_fota_downloading_8.png b/res/tw1/images/wc_fota_downloading_8.png new file mode 100755 index 0000000000000000000000000000000000000000..37f59ec85dd0808be24309d42d4ddcfff92a8883 GIT binary patch literal 1273 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 literal 0 HcmV?d00001 diff --git a/scripts/tw1/41-tota-ua.list b/scripts/tw1/41-tota-ua.list new file mode 100755 index 0000000..db9e593 --- /dev/null +++ b/scripts/tw1/41-tota-ua.list @@ -0,0 +1,57 @@ +# ---- Target contents ----------------------------------------------------- # +VERBATIMS=" +/usr/share/fota/res/images/wc_fota_downloading_0.png +/usr/share/fota/res/images/wc_fota_downloading_1.png +/usr/share/fota/res/images/wc_fota_downloading_2.png +/usr/share/fota/res/images/wc_fota_downloading_3.png +/usr/share/fota/res/images/wc_fota_downloading_4.png +/usr/share/fota/res/images/wc_fota_downloading_5.png +/usr/share/fota/res/images/wc_fota_downloading_6.png +/usr/share/fota/res/images/wc_fota_downloading_7.png +/usr/share/fota/res/images/wc_fota_downloading_8.png +/usr/share/fota/res/images/wc_fota_downloading_9.png +/usr/share/fota/res/images/wc_fota_downloading_percent.png +/usr/share/fota/res/images/tw1_fota_progress_000.png +/usr/share/fota/res/images/tw1_fota_progress_001.png +/usr/share/fota/res/images/tw1_fota_progress_002.png +/usr/share/fota/res/images/tw1_fota_progress_003.png +/usr/share/fota/res/images/tw1_fota_progress_004.png +/usr/share/fota/res/images/tw1_fota_progress_005.png +/usr/share/fota/res/images/tw1_fota_progress_006.png +/usr/share/fota/res/images/tw1_fota_progress_007.png +/usr/share/fota/res/images/tw1_fota_progress_008.png +/usr/share/fota/res/images/tw1_fota_progress_009.png +/usr/share/fota/res/images/tw1_fota_progress_010.png +/usr/share/fota/res/images/tw1_fota_progress_011.png +/usr/share/fota/res/images/tw1_fota_progress_012.png +/usr/share/fota/res/images/tw1_fota_progress_013.png +/usr/share/fota/res/images/tw1_fota_progress_014.png +/usr/share/fota/res/images/tw1_fota_progress_015.png +/usr/share/fota/res/images/tw1_fota_progress_016.png +/usr/share/fota/res/images/tw1_fota_progress_017.png +/usr/share/fota/res/images/tw1_fota_progress_018.png +/usr/share/fota/res/images/tw1_fota_progress_019.png +/usr/share/fota/res/images/tw1_fota_progress_020.png +/usr/share/fota/res/images/tw1_fota_progress_021.png +/usr/share/fota/res/images/tw1_fota_progress_022.png +/usr/share/fota/res/images/tw1_fota_progress_023.png +/usr/share/fota/res/images/tw1_fota_progress_024.png +/usr/share/fota/res/images/tw1_fota_progress_025.png +/usr/share/fota/res/images/tw1_fota_progress_026.png +/usr/share/fota/res/images/tw1_fota_progress_027.png +/usr/share/fota/res/images/tw1_fota_progress_028.png +/usr/share/fota/res/images/tw1_fota_progress_029.png +/usr/share/fota/res/images/tw1_fota_progress_030.png +/usr/share/fota/res/images/tw1_fota_progress_031.png +/usr/share/fota/res/images/tw1_fota_progress_032.png +/usr/share/fota/res/images/tw1_fota_progress_bg.png +/usr/share/fota/res/images/tw1_fota_progress_final.png +/usr/share/fota/res/images/wc_fota_start_downloading.png +" + +WITHLIBS=" +/usr/bin/fota_gui +/usr/bin/fota_gui_test +/usr/lib/libtdm-mgr.so +/usr/lib/bufmgr/libtbm_default.so +" diff --git a/src/common/fota_util.c b/src/common/fota_util.c index b5a6a3d..5c38e25 100755 --- a/src/common/fota_util.c +++ b/src/common/fota_util.c @@ -16,16 +16,25 @@ * limitations under the License. */ +#include +#include +#include #include #include +#include #include #include #include +#include "fota_common.h" + int s_fd_stdin = -1; int s_fd_stdout = -1; int s_fd_stderr = -1; +/*----------------------------------------------------------------------------- + set_default_stdio + ----------------------------------------------------------------------------*/ static int set_default_stdio(int flags, int nfd) { int fd, r; @@ -43,6 +52,9 @@ static int set_default_stdio(int flags, int nfd) } } +/*----------------------------------------------------------------------------- + _init_stdio + ----------------------------------------------------------------------------*/ void _init_stdio(void) { s_fd_stdin = set_default_stdio(O_RDONLY, STDIN_FILENO); @@ -52,6 +64,9 @@ void _init_stdio(void) s_fd_stderr = set_default_stdio(O_WRONLY, STDERR_FILENO); } +/*----------------------------------------------------------------------------- + _exit_stdio + ----------------------------------------------------------------------------*/ void _exit_stdio(void) { if (s_fd_stdin >=0) @@ -63,3 +78,115 @@ void _exit_stdio(void) if (s_fd_stderr >=0) close(s_fd_stderr); } + +/*----------------------------------------------------------------------------- + _system_cmd_wait + ----------------------------------------------------------------------------*/ +int _system_cmd_wait(const char *command) +{ + + int pid = 0; + int status = 0; + char* const environ[2] = {"DISPLAY=:0", NULL }; + + if (command == NULL) + return -1; + + pid = fork(); + + if (pid == -1) + return -1; + + if (pid == 0) { + char *argv[4]; + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = (char*)command; + argv[3] = 0; + execve("/bin/sh", argv, environ); + exit(127); + } + + do { + if (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) + return -1; + } else { + return status; + } + } while(1); +} + +/*----------------------------------------------------------------------------- + _system_cmd_nowait + ----------------------------------------------------------------------------*/ +int _system_cmd_nowait(const char *command) +{ + + int pid = 0; + char* const environ[2] = {"DISPLAY=:0", NULL }; + + if (command == NULL) + return -1; + + pid = fork(); + + if (pid == -1) + return -1; + + if (pid == 0) { + char *argv[4]; + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = (char*)command; + argv[3] = 0; + execve("/bin/sh", argv, environ); + exit(127); + } + + return 0; +} + +/*----------------------------------------------------------------------------- + check_existence + ----------------------------------------------------------------------------*/ +long check_existence(const char *file_path) +{ + struct stat statbuf; + char filename[MAX_FILE_PATH]; + + LOG("%s: %s\n",__func__ , file_path); + if (strncpy(filename, file_path, strlen(file_path) + 1) == NULL) { + LOG("strncpy error=%s\n", filename); + return 0; + } + if (stat(filename, &statbuf)) { + if (ENOENT == errno) { + LOG("stat %s: %s\n", filename, strerror(errno)); + return 0; + } + } + LOG("%s: statbuf.st_size = %d\n",__func__ , (int)statbuf.st_size); + return statbuf.st_size; +} + +/*----------------------------------------------------------------------------- + make_temp_file + ----------------------------------------------------------------------------*/ +void make_temp_file(char *temp_file, int file_size) +{ + FILE *fp; + int i = 0, temp = 0; + + LOG("Make %s file\n", temp_file); + + fp = fopen(temp_file, "wb"); + if (!fp) { + LOGE("failed to fopen\n"); + return; + } + for (i = 0; i < file_size; i++) + fwrite(&temp, sizeof(int), 1, fp); + fclose(fp); +} + diff --git a/src/common/fota_util.h b/src/common/fota_util.h index 932247c..184ef65 100755 --- a/src/common/fota_util.h +++ b/src/common/fota_util.h @@ -21,6 +21,11 @@ extern void _init_stdio(void); extern void _exit_stdio(void); +extern int _system_cmd_wait(const char *command); +extern int _system_cmd_nowait(const char *command); +extern long check_existence(const char *file_path); +extern void make_temp_file(char *temp_file, int file_size); + #endif /* _FOTA_UTIL_H_ */ diff --git a/src/rpi3/ua.c b/src/rpi3/ua.c index efbc570..51e986e 100644 --- a/src/rpi3/ua.c +++ b/src/rpi3/ua.c @@ -112,121 +112,6 @@ FILE *__log_out_file__; static void save_result(int result); static void save_cause(int cause); static int get_last_update_status(void); -/*----------------------------------------------------------------------------- - _system_cmd_wait - ----------------------------------------------------------------------------*/ -int _system_cmd_wait(const char *command) -{ - - int pid = 0; - int status = 0; - char* const environ[2] = {"DISPLAY=:0", NULL }; - - if (command == NULL) - return -1; - - pid = fork(); - - if (pid == -1) - return -1; - - if (pid == 0) { - char *argv[4]; - argv[0] = "sh"; - argv[1] = "-c"; - argv[2] = (char*)command; - argv[3] = 0; - execve("/bin/sh", argv, environ); - exit(127); - } - - do { - if (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) - return -1; - } else { - return status; - } - } while(1); -} - -/*----------------------------------------------------------------------------- - _system_cmd_nowait - ----------------------------------------------------------------------------*/ -int _system_cmd_nowait(const char *command) -{ - - int pid = 0; - char* const environ[] = { - "DISPLAY=:0", - "TBM_DISPLAY_SERVER=1", - "XDG_RUNTIME_DIR=/run", - NULL }; - - if (command == NULL) - return -1; - - pid = fork(); - - if (pid == -1) - return -1; - - if (pid == 0) { - char *argv[4]; - argv[0] = "sh"; - argv[1] = "-c"; - argv[2] = (char*)command; - argv[3] = 0; - execve("/bin/sh", argv, environ); - exit(127); - } - - return 0; -} - -/*----------------------------------------------------------------------------- - check_existence - ----------------------------------------------------------------------------*/ -long check_existence(const char *file_path) -{ - struct stat statbuf; - char filename[MAX_FILE_PATH]; - - LOG("%s: %s\n",__func__ , file_path); - if (strncpy(filename, file_path, strlen(file_path) + 1) == NULL) { - LOG("strncpy error=%s\n", filename); - return 0; - } - if (stat(filename, &statbuf)) { - if (ENOENT == errno) { - char err[1024]; - LOG("stat %s: %s\n", filename, strerror_r(errno, err, sizeof(err))); - return 0; - } - } - LOG("%s: statbuf.st_size = %d\n",__func__ , (int)statbuf.st_size); - return statbuf.st_size; -} - -/*----------------------------------------------------------------------------- - make_temp_file - ----------------------------------------------------------------------------*/ -void make_temp_file(char *temp_file) -{ - FILE *fp; - int i = 0, temp = 0; - - LOG("Make %s file\n", temp_file); - - fp = fopen(temp_file, "wb"); - if (!fp) { - LOGE("failed to fopen\n"); - return; - } - for (i = 0; i < TEMP_SIZE; i++) - fwrite(&temp, sizeof(int), 1, fp); - fclose(fp); -} /*----------------------------------------------------------------------------- fota_gui_update_progress @@ -1628,7 +1513,6 @@ int main(int argc, char **argv) case UPI_FIXNV2_VERIFY_ERROR: case UPI_PARAM_VERIFY_ERROR: case UPI_ROOTFS_VERIFY_ERROR: - case UPI_CSC_VERIFY_ERROR: case UPI_KERNEL_VERIFY_ERROR: case UPI_MODULE_VERIFY_ERROR: case UPI_MODEM_VERIFY_ERROR: @@ -1643,7 +1527,6 @@ int main(int argc, char **argv) case UPI_FIXNV2_UPDATE_ERROR: case UPI_PARAM_UPDATE_ERROR: case UPI_ROOTFS_UPDATE_ERROR: - case UPI_CSC_UPDATE_ERROR: case UPI_KERNEL_UPDATE_ERROR: case UPI_MODULE_UPDATE_ERROR: case UPI_MODEM_UPDATE_ERROR: diff --git a/src/rpi3/ua.h b/src/rpi3/ua.h index a2870d8..1ef619e 100644 --- a/src/rpi3/ua.h +++ b/src/rpi3/ua.h @@ -63,7 +63,6 @@ #define UPI_FIXNV2_VERIFY_ERROR 0xFDC3 #define UPI_PARAM_VERIFY_ERROR 0xFDC6 #define UPI_ROOTFS_VERIFY_ERROR 0xFDC7 -#define UPI_CSC_VERIFY_ERROR 0xFDC8 #define UPI_KERNEL_VERIFY_ERROR 0xFDC9 #define UPI_MODULE_VERIFY_ERROR 0xFDCA #define UPI_MODEM_VERIFY_ERROR 0xFDCB @@ -78,7 +77,6 @@ #define UPI_FIXNV2_UPDATE_ERROR 0xFDD3 #define UPI_PARAM_UPDATE_ERROR 0xFDD6 #define UPI_ROOTFS_UPDATE_ERROR 0xFDD7 -#define UPI_CSC_UPDATE_ERROR 0xFDD8 #define UPI_KERNEL_UPDATE_ERROR 0xFDD9 #define UPI_MODULE_UPDATE_ERROR 0xFDDA #define UPI_MODEM_UPDATE_ERROR 0xFDDB diff --git a/src/tw1/ua.c b/src/tw1/ua.c new file mode 100755 index 0000000..6e25c32 --- /dev/null +++ b/src/tw1/ua.c @@ -0,0 +1,1483 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SS_Common.h" +#include "fota_common.h" +#include "ua.h" +#include "mmc_io.h" +#include "fota_cfg.h" +#include "fota_tar.h" +#include "fota_util.h" + +#define MAX_CFG_LEN 4096 + +#define BOTA0_DEV "/dev/mmcblk0p1" + +#define FOTA_GUI_INTERFACE "/usr/bin/fota_gui_test" +#define FOTA_GUI_MAIN "/usr/bin/fota_gui" + +int ua_op_mode = UA_OP_MODE_FG; + +static char fota_result[MAX_FILE_PATH]; +static char fota_cause[MAX_FILE_PATH]; +static char fota_status_path[MAX_FILE_PATH]; +static char delta_folder[MAX_FILE_PATH]; +static char delta_path[MAX_FILE_PATH]; +static char log_folder[MAX_FILE_PATH]; +static char result_folder[MAX_FILE_PATH]; +static char temp_folder[MAX_FILE_PATH]; + + +static ua_part_info_t def_part_info[UA_PARTI_MAX] = { + {"ROOTFS", "delta.rootfs", "", 0}, + + {"BOOT", "delta.boot", "", 0}, + {"RAMDISK1", "delta.ramdisk1", "", 0} +#ifdef SS_RECOVERYRAMDISK + ,{"RAMDISK2", "delta.ramdisk2", "/dev/mmcblk0p4", 0} +#endif +}; + + +static ua_update_cfg_t def_update_cfg[UA_PARTI_MAX] = { + {DELTA_FS, UA_ROOTFS, 0, 0}, + {DELTA_IMG, UA_BOOT, 0, 0}, + {DELTA_IMG, UA_RAMDISK1, 0, 0} +#ifdef SS_RECOVERYRAMDISK + ,{EXTRA, UA_RAMDISK2, 0, 0} +#endif +}; + +static ua_part_info_t s_part_info[UA_PARTI_MAX]; + +static ua_update_cfg_t s_update_cfg[UA_PARTI_MAX]; + +static ua_update_data_t s_update_data[UA_PARTI_MAX] = { + {0, 0, 0, 0, 0, 0, NULL, NULL}, + {0, 0, 0, 0, 0, 0, NULL, NULL}, + {0, 0, 0, 0, 0, 0, NULL, NULL} +#ifdef SS_RECOVERYRAMDISK + ,{0, 0, 0, 0, 0, 0, NULL, NULL} +#endif +}; + +static int g_verify_error[] = { + UPI_ROOTFS_VERIFY_ERROR, + UPI_BOOT_VERIFY_ERROR, + UPI_RAMDISK1_VERIFY_ERROR, + UPI_RAMDISK2_VERIFY_ERROR +}; + +static int g_update_error[] = { + UPI_ROOTFS_UPDATE_ERROR, + UPI_BOOT_UPDATE_ERROR, + UPI_RAMDISK1_UPDATE_ERROR, + UPI_RAMDISK2_UPDATE_ERROR +}; + +static int s_part_num = 0; +static ua_delta_info_t s_delta_info; + +unsigned int __log_level__ = + (LOG_DEBUG | LOG_FLASH | LOG_FILE | LOG_FUNCS | LOG_GUI | LOG_ENGINE | LOG_INFO); +FILE *__log_out_file__; + +static void save_result(int result); +static void save_cause(int cause); +static int get_last_update_status(void); + +/*----------------------------------------------------------------------------- + fota_gui_update_progress + ----------------------------------------------------------------------------*/ +void fota_gui_update_progress(int percent) +{ + int ret = 0; + char cmd[1024]; + + snprintf(cmd, sizeof(cmd)-1, "%s %d", FOTA_GUI_INTERFACE, percent); + + ret = _system_cmd_wait(cmd); + LOG("ret = %d\n", ret); +} + +/*----------------------------------------------------------------------------- + fota_gui_update_end + ----------------------------------------------------------------------------*/ +void fota_gui_update_end(void) +{ + int ret = 0; + char cmd[1024]; + + snprintf(cmd, sizeof(cmd)-1, "%s %d", FOTA_GUI_INTERFACE, -1); + + ret = _system_cmd_wait(cmd); + LOG("ret = %d\n", ret); +} + +/*----------------------------------------------------------------------------- + fota_gui_progress + ----------------------------------------------------------------------------*/ +void fota_gui_progress(void * pbUserData, unsigned long uPercent) +{ + int percent; + ua_dataSS_t *ua_data = (ua_dataSS_t *)pbUserData; + ua_update_data_t *ua_update_data = ua_data->update_data; + + if (ua_op_mode == UA_OP_MODE_BG) { + return; + } + + LOGL(LOG_FUNCS|LOG_GUI, "%s: ++ uPercent(%lu%%), config->weight=%lu\n", __func__, + uPercent, (long unsigned int)ua_update_data->weight); + + if(uPercent == 100) { + percent = ua_update_data->weight_offset + ua_update_data->weight; + } else { + percent = ua_update_data->weight_offset + (ua_update_data->weight * uPercent / 100); + } + + /* re-arrange progress percentage betwen scout & update */ + if (ua_data->ua_operation == UI_OP_SCOUT) { + percent = percent / 5; + } else if ((ua_data->ua_operation == UI_OP_SCOUT_UPDATE) + || (ua_data->ua_operation == UI_OP_UPDATE)) { + percent = 20 + percent * 4 / 5; + } + + fota_gui_update_progress(percent); /* update progress bar and text */ + + LOGL(LOG_FUNCS|LOG_GUI, "-- uPercent=%lu, Print Percent(%d%%)\n", uPercent, percent); +} + +/*----------------------------------------------------------------------------- + _launch_fota_gui_process + ----------------------------------------------------------------------------*/ +void _launch_fota_gui_process(void) +{ + _system_cmd_nowait(FOTA_GUI_MAIN); + sleep(1); +} + +/*----------------------------------------------------------------------------- + write_data_to_blkdev + - blk_start : start sector number + - blk_cnt : number of sectors to write + - data length should be blk_cnt x SECTOR_SIZE + ----------------------------------------------------------------------------*/ +static int write_data_to_blkdev(char* dev_name, int blk_start, int blk_cnt, char* data) +{ + int fd_mmc; + + LOG("%s: entered start offset=%d sectos, size=%d sectos\n", dev_name, blk_start, blk_cnt); + /* destination MMC device open */ + fd_mmc = mmc_dev_open(dev_name, O_RDWR); + if (fd_mmc < 0) { + LOG("mmc_dev_open() fail ...\n"); + return FAIL; + } + + if (mmc_dev_sector_write(fd_mmc, blk_start, blk_cnt, data) < 0) { + LOG("mmc_dev_sector_write() fail ...\n"); + mmc_dev_close(fd_mmc); + return FAIL; + } + + mmc_dev_close(fd_mmc); + LOG("%s: leaved\n", __func__); + + return SUCCESS; +} + +/*----------------------------------------------------------------------------- + write_full_image + ----------------------------------------------------------------------------*/ +static int write_full_image(ua_data_t* ua_data, int part_idx) +{ + int ret = SUCCESS; + int blk_start = 0; + int blk_cnt = 0; + int read_count = 0, data_length = 0; + char* data = NULL; + int bin_size = 0, offset = 0; + ua_part_info_t *ua_part_info = ua_data->parti_info; + ua_update_data_t *ua_update_data = ua_data->update_data; + + FILE *fp; + + LOG("ua_delta_path=%s, ua_subject_name=%s\n", ua_update_data->ua_delta_path, ua_part_info->ua_subject_name); + + fp = fopen(ua_update_data->ua_delta_path, "r"); + if (!fp) { + LOGE("open file %s failed.\n", ua_update_data->ua_delta_path); + return FAIL; + } + + bin_size = tar_get_item_size(ua_update_data->ua_delta_path, ua_part_info->ua_subject_name); + if (bin_size <= 0) { + LOGE("bin_size=%d\n", bin_size); + fclose(fp); + return FAIL; + } + offset = tar_get_item_offset(ua_update_data->ua_delta_path, ua_part_info->ua_subject_name); + if (offset < 0) { + LOGE("offset=%d\n", offset); + fclose(fp); + return FAIL; + } + + blk_cnt = ((bin_size-1)/SECTOR_SIZE)+1; + data_length = blk_cnt * SECTOR_SIZE; + LOG("bin_size=%d, data_length=%d\n", bin_size, data_length); + + if (fseek(fp, offset, SEEK_SET) < 0) { + LOGE("fseek() fail\n"); + fclose(fp); + return FAIL; + } + + data = malloc(data_length); + if (data) { + read_count = fread(data, 1, bin_size, fp); + LOG("read file read_count=%d byte, blk_cnt=%d\n", read_count, blk_cnt); + if (read_count != bin_size) { + LOGE("error in read size\n"); + if (data) { + free(data); + } + if (fp) { + fclose(fp); + } + return FAIL; + } + + if (write_data_to_blkdev(ua_part_info->ua_blk_name, + blk_start, blk_cnt, data) != SUCCESS) { + LOGE("error in write_data_to_blkdev()\n" ); + ret = FAIL; + } + + if (data) { + free(data); + } + } + + if (fp) { + fclose(fp); + } + + LOG("%s leaved\n", __func__); + + return ret; +} + +/*----------------------------------------------------------------------------- + verify_Full_Image + ----------------------------------------------------------------------------*/ +int verify_Full_Image(int part_idx) +{ +int ret = SUCCESS; +ua_dataSS_t ua_dataSS; +int last_update_status = UP_START_NONE; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + ua_delta_info_t *ua_delta_info= &s_delta_info; + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.ua_operation = UI_OP_SCOUT; + ua_dataSS.ui_progress = fota_gui_progress; + last_update_status = get_last_update_status(); + + if (ua_update_data->ua_delta_path != NULL){ + ret = SUCCESS;//SS_IMGVerfiyPartition(&ua_dataSS); + fota_gui_progress(&ua_dataSS, 100); + } +return ret; +} + +/*----------------------------------------------------------------------------- + update_Full_Image + ----------------------------------------------------------------------------*/ +int update_Full_Image(int part_idx) +{ + int ret = FAIL; + ua_dataSS_t ua_data; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + + ua_data.parti_info = ua_part_info; + ua_data.update_cfg = ua_update_cfg; + ua_data.update_data = ua_update_data; + ua_data.ui_progress = fota_gui_progress; + ua_data.ua_operation = UI_OP_UPDATE; + + LOG("%s entered\n", __func__); + + ret = write_full_image(&ua_data, part_idx); + if(ret != SUCCESS) + { + LOGE("%s entered\n", __func__); + goto CleanUp; + } + + fota_gui_progress(&ua_data, 100); /* display completion of update_Sbl */ + + CleanUp: + + LOG("%s leaved ret=%d\n", __func__, ret); + return ret; +} + +/*----------------------------------------------------------------------------- + verify_Delta_FS + ----------------------------------------------------------------------------*/ +int verify_Delta_FS(int part_idx) +{ + int ret = SUCCESS; + int last_update_status = UP_START_NONE; + ua_dataSS_t ua_dataSS; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + ua_delta_info_t *ua_delta_info= &s_delta_info; + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.ua_operation = UI_OP_SCOUT; + ua_dataSS.ui_progress = fota_gui_progress; + last_update_status = get_last_update_status(); + //if(last_update_status <= part_idx) // Should build nodes again, unless this partition already updated. + + if (ua_update_data->ua_delta_path != NULL) { + LOG("Verifying %s \n", ua_dataSS.parti_info->ua_parti_name); + ret = SS_FSVerifyPartition(&ua_dataSS, part_idx); + } + + return ret; +} + +/*----------------------------------------------------------------------------- + update_Delta_FS + ----------------------------------------------------------------------------*/ +int update_Delta_FS(int part_idx, unsigned long ui32Operation) +{ + int ret = SUCCESS; + ua_dataSS_t ua_dataSS; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + ua_delta_info_t *ua_delta_info= &s_delta_info; + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.ua_operation = ui32Operation; + ua_dataSS.ui_progress = fota_gui_progress; + + if (ua_update_data->ua_delta_path != NULL) { + ret=SS_FSUpdatemain(&ua_dataSS,part_idx); + } + + return ret; +} + +/*----------------------------------------------------------------------------- + verify_Delta_IMG + ----------------------------------------------------------------------------*/ +int verify_Delta_IMG(int part_idx) +{ + int ret = SUCCESS; + ua_dataSS_t ua_dataSS; + int last_update_status = UP_START_NONE; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + ua_delta_info_t *ua_delta_info= &s_delta_info; +#if defined(PT_FOTA_USE_LOCAL_TEMP)// NOT sure for TOTA, shd check this + size = check_existence(ua_update_data->ua_temp_path); + if (size == 0) + make_temp_file(ua_update_data->ua_temp_path, TEMP_SIZE); +#endif + + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.ua_operation = UI_OP_SCOUT; + ua_dataSS.ui_progress = fota_gui_progress; + last_update_status = get_last_update_status(); + + if (ua_update_data->ua_delta_path != NULL){ + ret = SS_IMGVerfiyPartition(&ua_dataSS); + } + + return ret; + } + +/*----------------------------------------------------------------------------- + update_Delta_IMG + ----------------------------------------------------------------------------*/ +int update_Delta_IMG(int part_idx, unsigned long ui32Operation) +{ + int ret = SUCCESS; + ua_dataSS_t ua_dataSS; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + +#if defined(PT_FOTA_USE_LOCAL_TEMP) + size = check_existence(ua_update_data->ua_temp_path); + if (size == 0) + make_temp_file(ua_update_data->ua_temp_path, TEMP_SIZE); +#endif + ua_delta_info_t *ua_delta_info= &s_delta_info; + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.ua_operation = ui32Operation; + ua_dataSS.ui_progress = fota_gui_progress; + ua_dataSS.write_data_to_blkdev=write_data_to_blkdev; + if (ua_update_data->ua_delta_path != NULL) { + ret = SS_IMGUpdatemain(&ua_dataSS, DELTA_IMG); + } + return ret; +} + +#ifdef SS_RECOVERYRAMDISK +int verify_RecoveryDelta_IMG(int part_idx) +{ + int ret = SUCCESS; + ua_dataSS_t ua_dataSS; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + ua_delta_info_t *ua_delta_info= &s_delta_info; + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.ua_operation = UI_OP_SCOUT; + ua_dataSS.ui_progress = fota_gui_progress; + if (ua_update_data->ua_delta_path != NULL) { + ret = SS_IMGVerfiyPartition(&ua_dataSS); + } + return ret; +} + + +int update_RecoveryDelta_IMG(int part_idx, int update_type) +{ + int ret = SUCCESS; + ua_dataSS_t ua_dataSS; + ua_part_info_t *ua_part_info = &s_part_info[part_idx]; + ua_update_cfg_t *ua_update_cfg = &s_update_cfg[part_idx]; + ua_update_data_t *ua_update_data = &s_update_data[part_idx]; + ua_delta_info_t *ua_delta_info= &s_delta_info; + ua_dataSS.parti_info = ua_part_info; + ua_dataSS.update_cfg = ua_update_cfg; + ua_dataSS.update_data = ua_update_data; + ua_dataSS.update_delta=ua_delta_info; + ua_dataSS.update_data->ua_temp_path = malloc(MAX_FILE_PATH); + ua_dataSS.ua_operation = UI_OP_SCOUT_UPDATE; + ua_dataSS.ui_progress = fota_gui_progress; + //ua_dataSS.update_data.ua_temp_path = + + if (ua_update_data->ua_delta_path != NULL && ua_dataSS.update_data->ua_temp_path) { + sprintf(ua_dataSS.update_data->ua_temp_path, "%s/fota_temp_%s", delta_folder, ua_dataSS.parti_info->ua_parti_name); + LOG("update_RecoveryDelta_IMG() [%s] temp path [%s]\n", ua_dataSS.parti_info->ua_parti_name,ua_dataSS.update_data->ua_temp_path); + ret = SS_IMGUpdatemain(&ua_dataSS, update_type); //PASS temp path whr file has to be written, Once written it should be UNLINKED after upgrade. + } + return ret; +} +#endif + + +/*----------------------------------------------------------------------------- + set_data_weight + ----------------------------------------------------------------------------*/ +/* set data weight using data size minimum:1 total: 100 */ +static void set_data_weight(unsigned int total_data_size) +{ + int i = 0, big = 0, weight = 0, total_weight = 0; + + LOG("%s entered, total_data_size=%u\n", __func__, total_data_size); + + for (i = 0; i < s_part_num; i++) { + if(s_update_data[i].exist_check) + { + s_update_data[i].weight = 100 * (unsigned long long)s_update_data[i].data_size / total_data_size; + + if(s_update_data[i].weight == 0) { + s_update_data[i].weight = 1; + } + + if(weight < s_update_data[i].weight) { + weight = s_update_data[i].weight; + big = i; + } + + total_weight += s_update_data[i].weight; + } + + LOG("[%d] exist_check=%d, weight=%u total_weight=%u\n", + i, s_update_data[i].exist_check, s_update_data[i].weight, total_weight); + } + + if(total_weight < 100) { + s_update_data[big].weight += (100 - total_weight); + } else { + s_update_data[big].weight -= (total_weight - 100); + } + + LOG("[big: %d] weight=%u\n", big, s_update_data[big].weight); + + LOG("%s leaved\n", __func__); +} + +/*----------------------------------------------------------------------------- + set_data_weight_offset + ----------------------------------------------------------------------------*/ +static void set_data_weight_offset(void) +{ + int i = 0, k = 0; + + LOG("%s entered\n", __func__); + + for (i = 0; i < s_part_num; i++) { + for(k = 0; k < i; k++) { + s_update_data[i].weight_offset += s_update_data[k].weight; + } + LOG("s_update_data[%d].weight_offset=%u\n", i, s_update_data[i].weight_offset); + } + + LOG("%s leaved\n", __func__); +} + +/*----------------------------------------------------------------------------- + read_from_file + ----------------------------------------------------------------------------*/ +int read_from_file(const char *path, char *buf, size_t size) +{ + int fd; + ssize_t count; + + if (!path) + return -1; + + if (size == 0) { + return 0; + } + + fd = open(path, O_RDONLY, 0); + LOG("open '%s'\n", path); + if (fd == -1) { + LOG("Could not open '%s'", path); + return -1; + } + + count = read(fd, buf, size); + if (count > 0) { + count = (count < (ssize_t)size) ? count : ((ssize_t)size - 1); + while (count > 0 && buf[count - 1] == '\n') + count--; + buf[count] = '\0'; + } else { + buf[0] = '\0'; + } + LOG("read '%s'\n", buf); + + close(fd); + + return (int)count; +} + + +/*----------------------------------------------------------------------------- + write_to_file + ----------------------------------------------------------------------------*/ +/* size is the contents size, not buf size + buf size should be larger than contents size */ +int write_to_file(const char *path, char *buf, size_t size) +{ + int fd; + ssize_t count; + + if (!path) + return -1; + + fd = open(path, O_WRONLY | O_CREAT, S_IRWXU); + LOG("open '%s'\n", path); + + if (fd == -1) { + LOG("Could not open '%s'\n", path); + return -1; + } + + count = write(fd, buf, size); + LOG("write '%s'\n", buf); + + if (fsync(fd) < 0) { + LOG("fsync failed.\n"); + } + + close(fd); + + if (size != count) { + LOG("Could not write to '%s'\n", path); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------- + write_num_to_file + ----------------------------------------------------------------------------*/ +int write_num_to_file(const char *path, int num) +{ + char num_str[16]; + + sprintf(num_str, "%d", num); + return write_to_file(path, num_str, strlen(num_str)); +} + +/*----------------------------------------------------------------------------- + remove_last_update_status + ----------------------------------------------------------------------------*/ +static void remove_last_update_status(void) +{ + /* + remove status file. + */ + int ret = -1; + ret = unlink(fota_status_path); + LOGL(LOG_DEBUG, "delete %s return %d\n", fota_status_path, ret); +} + +/*----------------------------------------------------------------------------- + get_last_update_status + ----------------------------------------------------------------------------*/ +static int get_last_update_status(void) +{ + /* + if status file does not exist, status = UP_START_NONE. + if status file exist, read status from file. + */ + char buf[256]; + int status = UP_START_NONE; + + if (check_existence(fota_status_path) == 0) { + return UP_START_NONE; + } + + if (read_from_file(fota_status_path, buf, sizeof(buf)) < 0) { + return UP_START_NONE; + } + + status = atoi(buf); + if ((status > UP_START_NONE) && (status < UP_START_MAX)) { + return status; + } else { + return UP_START_NONE; + } +} + +/*----------------------------------------------------------------------------- + set_last_update_status + ----------------------------------------------------------------------------*/ +static void set_last_update_status(int status) +{ + /* + if status file exist, write status to file. + if status file does not exist, create file and write status to file. + */ + write_num_to_file(fota_status_path, status); +} + +/*----------------------------------------------------------------------------- + get_time_stamp + ----------------------------------------------------------------------------*/ +static char ts[256]; +static void get_time_stamp(void) +{ + struct timeval tv; + int sec, msec; + + gettimeofday(&tv, NULL); + sec = (int) tv.tv_sec; + msec = (int) (tv.tv_usec / 1000); + sprintf(ts, "%06d.%03d", sec % 100000, msec); +} + +/*----------------------------------------------------------------------------- + update_all + ----------------------------------------------------------------------------*/ +int update_all() +{ + int i, data_count = 0, ret = FAIL; + unsigned long total_data_size = 0; + int cause = 0; + int item_size = 0; + int last_update_status = UP_START_NONE; + int update_status = UP_START_NONE; + int part_idx = UA_PARTI_MAX; + int err_idx = UA_PARTI_MAX; + unsigned int update_type = 0; + unsigned long ui32Operation = UI_OP_SCOUT; + + LOG("%s entered\n", __func__); + + data_count = 0; + + for (i = 0; i < s_part_num; i++) { + item_size = tar_get_item_size(s_update_data[i].ua_delta_path, s_part_info[i].ua_subject_name); + if(item_size > 0) { + s_update_data[i].data_size = (unsigned int)item_size; + } else { + s_update_data[i].data_size = 0; + } + LOGL(LOG_DEBUG, "s_update_data[%d].data_size=%lu, ua_delta_path=%s, " + "ua_blk_name = %s, ua_subject_name=%s\n", + i, + (long unsigned int)s_update_data[i].data_size, + s_update_data[i].ua_delta_path, + s_part_info[i].ua_blk_name, + s_part_info[i].ua_subject_name); + + if (s_update_data[i].data_size) { + data_count++; + + s_update_data[i].exist_check = 1; + total_data_size += s_update_data[i].data_size; + + LOGL(LOG_DEBUG, + "Check Delta : part_idx(%d), file_path(%s), total data cnt(%lu)\n", + i, s_update_data[i].ua_delta_path, + (long unsigned int)data_count); + } + } + + LOG("data_count=%lu, total_data_size=%lu\n", + (long unsigned int)data_count, (long unsigned int)total_data_size); + if (data_count == 0) { + ret = UPI_DELTACOUNT_ERROR; + sleep(3); + + goto CleanUp; + } + LOG(" set weight to draw progressive bar.....\n"); + set_data_weight(total_data_size); + set_data_weight_offset(); + + for (i = 0; i < s_part_num; i++) { + LOG("s_part_info[%s].ua_delta_path = %s ua_subject_name=%s\n", + s_part_info[i].ua_parti_name, + s_update_data[i].ua_delta_path, + s_part_info[i].ua_subject_name); + } + + last_update_status = get_last_update_status(); + LOG("Updatea_all() Last Update status To start with [%d] \n", last_update_status); + /* Verify */ + if (last_update_status == UP_START_NONE) + { + for (part_idx = 0; part_idx < s_part_num; part_idx++) { + if (s_update_data[part_idx].data_size > 0) { + get_time_stamp(); + LOG("[%s] Verify %s ..............................................................\n", ts, + s_part_info[part_idx].ua_parti_name); + + update_type = s_update_cfg[part_idx].update_type; + if (update_type == FULL_IMG) + ret = verify_Full_Image(part_idx); + else if (update_type == DELTA_IMG) + ret = verify_Delta_IMG(part_idx); + else if (update_type == DELTA_FS) + ret = verify_Delta_FS(part_idx); + else if (update_type == EXTRA) + ret = verify_RecoveryDelta_IMG(part_idx); + else + ret = -1; + + if (ret != OK) { + cause = ret; + err_idx = s_update_cfg[part_idx].part_idx; + ret = g_verify_error[err_idx]; + LOG("%s verify fail", s_part_info[part_idx].ua_parti_name); + goto CleanUp; + } + s_update_data[part_idx].verify_check = 1; + } + } + + } + + get_time_stamp(); + LOG("[%s] Verify End ..............................................................\n", ts); + + /* Update */ + for (part_idx = 0; part_idx < s_part_num; part_idx++) { + update_status = part_idx; + if (last_update_status <= update_status) { + if (last_update_status == update_status) { + ui32Operation = UI_OP_SCOUT_UPDATE; + } else { + ui32Operation = UI_OP_UPDATE; + } + + if (s_update_data[part_idx].data_size > 0) { + get_time_stamp(); + LOG("[%s] Update %s ..............................................................\n", ts, + s_part_info[part_idx].ua_parti_name); + + set_last_update_status(update_status); + + update_type = s_update_cfg[part_idx].update_type; + if (update_type == FULL_IMG) + ret = update_Full_Image(part_idx); + else if (update_type == DELTA_IMG) + ret = update_Delta_IMG(part_idx, ui32Operation); + else if (update_type == DELTA_FS) + ret = update_Delta_FS(part_idx, ui32Operation); + else if (update_type == EXTRA) //TOTA + ret = update_RecoveryDelta_IMG(part_idx, FULL_IMG); + else + ret = -1; + + if (ret != OK) { + cause = ret; + err_idx = s_update_cfg[part_idx].part_idx; + ret = g_update_error[err_idx]; + LOG("%s update fail", s_part_info[part_idx].ua_parti_name); + goto CleanUp; + } + s_update_data[part_idx].update_check = 1; + } + } + } + + get_time_stamp(); + LOG("[%s] Update End ..............................................................\n", ts); + + CleanUp: + if(ret != OK) + save_cause(cause); + + return ret; +} + +/*----------------------------------------------------------------------------- + log_init + ----------------------------------------------------------------------------*/ +void log_init(void) +{ + char log_file[MAX_FILE_PATH]; + + memset(log_file, 0x00, sizeof(log_file)); + sprintf(log_file, "%s%s", log_folder, LOG_FILE_PATH); + + __log_out_file__ = fopen(log_file, "w"); + if (__log_out_file__ == NULL) { + perror("file open error\n"); + return; + } + + get_time_stamp(); + LOG("===== log start [%s] =====\n", ts); +} + +/*----------------------------------------------------------------------------- + log_deinit + ----------------------------------------------------------------------------*/ +void log_deinit(void) +{ + get_time_stamp(); + LOG("===== log end [%s] =====\n", ts); + + if(__log_out_file__) + { + fclose(__log_out_file__); + __log_out_file__ = NULL; + } + + sync(); +} + +/*----------------------------------------------------------------------------- + print_error_cause + ----------------------------------------------------------------------------*/ +static void print_error_cause(int error) +{ + switch(error) { + case E_SS_PKG_CORRUPTED: + case E_SS_SOURCE_CORRUPTED: /* not used */ + LOG("Corrupted firmware update package, did not store correctly. Detected, for example, by mismatched CRCs between actual and expected."); + break; + case E_SS_BAD_PARAMS: + LOG("Wrong Firmware Update Package delivered to device based on current device characteristics"); + break; + case E_SS_INVALID_DP_HEADER: + case E_SS_INVALID_DP_WRONG_SIGNATURE: + LOG("Failure to positively validate digital signature of firmware update package"); + break; + case E_SS_PKG_TOO_LONG: /* not used */ + LOG("Firmware Update Package is Not Acceptable"); + break; + case E_SS_NOT_ENOUGH_RAM: + LOG("The update fails because there isn't sufficient memory to update the device."); + break; + default: + LOG("another error"); + break; + } +} + +/* + +Corrupted firmware update package, did not store correctly. Detected, for example, by mismatched CRCs between actual and expected. +E_RB_PKG_CORRUPTED(0x8000000D) +E_RB_PKG_NOT_AUTHORIZED(0x8000000E): not used + + +Wrong Firmware Update Package delivered to device based on current device characteristics +E_RB_BAD_PARAMS(0x800000002) +E_RB_WRONG_UPI_VER(0x80000011):not used +E_RB_WRONG_UPI_UPDATE(0x80000012): not used +E_RB_UPDATE_SECTOR_SIG(0x80000013): not used + + +Failure to positively validate digital signature of firmware update package +E_RB_NON_DP_FORMAT_NOT_SUPPORTED(0x8001001A) +E_RB_INVALID_DP_HEADER(0x80010025) +E_RB_INVALID_DP_WRONG_SIGNATURE(0x80010026) +E_RB_INVALID_DP(0x80010027) + + +Firmware Update Package is Not Acceptable +E_RB_PKG_TOO_SHORT(0x8000000B) not used +E_RB_PKG_TOO_LONG(0x8000000C) not used +E_RB_PKG_NOT_AUTHORIZED(0x8000000F) + + +The update fails because there isn\A1\AFt sufficient memory to update the device. +E_RB_NOT_ENOUGH_RAM(0x8000001E) +*/ +/*----------------------------------------------------------------------------- + save_cause + ----------------------------------------------------------------------------*/ +void save_cause(int cause) +{ + char return_char[20]; + FILE *result_fp; + + LOG("%s entered, 0x%x\n", __func__, cause); + + print_error_cause(cause); + + if ((result_fp = fopen(fota_cause, "w")) == NULL) { + LOG("cause file open fail\n"); + return; + } + + sprintf(return_char, "%x", cause); + fwrite(return_char, strlen(return_char), 1, result_fp); + fclose(result_fp); + + LOG("%s leaved!\n", __func__); +} + +/*----------------------------------------------------------------------------- + save_result + ----------------------------------------------------------------------------*/ +void save_result(int result) +{ + char return_char[20]; + FILE *result_fp; + + LOG("%s entered, result=0x%x\n", __func__, result); + + if ((result_fp = fopen(fota_result, "w")) == NULL) { + LOG("result file open fail\n"); + return; + } + + sprintf(return_char, "%x", result); + fwrite(return_char, strlen(return_char), 1, result_fp); + fclose(result_fp); + + LOG("%s leaved!\n", __func__); + + return; +} + +/*----------------------------------------------------------------------------- + fota_path_init + ----------------------------------------------------------------------------*/ +int fota_path_init(void) +{ + int i; + + if (strlen(delta_folder) > MAX_FILE_PATH - 15) { + LOG("FOTA path is too long\n"); + return FAIL; + } + + for(i = 0; i < s_part_num; i++) { + s_update_data[i].ua_delta_path = malloc(MAX_FILE_PATH); + sprintf(s_update_data[i].ua_delta_path, "%s/%s", delta_folder, DEFAULT_DELTA_NAME); + //will be filled by UA if required (eg : RAMDISK case in TOTA) + //s_update_data[i].ua_temp_path = malloc(MAX_FILE_PATH); + //sprintf(s_update_data[i].ua_temp_path, "%s/fota_temp_%s", delta_folder, s_part_info[i].ua_parti_name); + } + + sprintf(fota_result, "%s/%s", result_folder, "result"); + sprintf(fota_cause, "%s/%s", result_folder, "cause"); + sprintf(fota_status_path, "%s/%s", result_folder, UP_STATUS_FILE); + + for(i = 0; i < s_part_num; i++) { + LOG("s_part_info[UA_%s].ua_delta_path=%s\n", + s_part_info[i].ua_parti_name, + s_update_data[i].ua_delta_path); + } + + return SUCCESS; +} + +/*----------------------------------------------------------------------------- + fota_path_deinit + ----------------------------------------------------------------------------*/ +void fota_path_deinit(void) +{ + int i; + for(i = 0; i < s_part_num; i++) { + if(s_update_data[i].ua_delta_path) { + free(s_update_data[i].ua_delta_path); + s_update_data[i].ua_delta_path = NULL; + } + if(s_update_data[i].ua_temp_path) { + free(s_update_data[i].ua_temp_path); + s_update_data[i].ua_temp_path = NULL; + } + } +} + +/*----------------------------------------------------------------------------- + check_ua_op_mode + ----------------------------------------------------------------------------*/ +int check_ua_op_mode(int argc, char **argv) +{ + if (argc == 3) { + ua_op_mode = UA_OP_MODE_FG; + return 0; + } else if (argc == 4) { + if (argv[3][0] == '0') { + ua_op_mode = UA_OP_MODE_FG; + return 0; + } else if (argv[3][0] == '1') { + ua_op_mode = UA_OP_MODE_BG; + return 0; + } + } + + return -1; +} + +/*----------------------------------------------------------------------------- + remove_temp_files + ----------------------------------------------------------------------------*/ +void remove_temp_files(void) +{ + int ret = 0; + int i; + char *ua_temp_path; + struct stat sbuf; + + for(i = 0; i < s_part_num; i++) { + ua_temp_path = s_update_data[i].ua_temp_path; + if (NULL == ua_temp_path) + continue; + + ret = lstat(ua_temp_path, &sbuf); + if (ret < 0) { + ret = stat(ua_temp_path, &sbuf); + if (ret < 0) { + LOG("stat failed with return value: %d errno: %d\n", ret, errno); + continue; + } + } + + if (S_ISDIR(sbuf.st_mode)) { + ret = rmdir(ua_temp_path); + if (ret < 0) { + LOG("rmdir(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno); + } + } else { + ret = unlink(ua_temp_path); + if (ret < 0) { + LOG("unlink(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno); + } + } + } +} + +/*----------------------------------------------------------------------------- + get_update_type + ----------------------------------------------------------------------------*/ +int get_update_type(char* part_name) +{ + if (strcmp(part_name, "FULL_IMG") == 0) + return FULL_IMG; + if (strcmp(part_name, "DELTA_IMG") == 0) + return DELTA_IMG; + if (strcmp(part_name, "DELTA_FS") == 0) + return DELTA_FS; + + return EXTRA; +} + +/*----------------------------------------------------------------------------- + get_part_idx + ----------------------------------------------------------------------------*/ +int get_part_idx(char* part_name) +{ + int i; + + for(i = UA_ROOTFS; i < UA_PARTI_MAX; i++) { + if (strcmp(part_name, def_part_info[i].ua_parti_name) == 0) { + return i; + } + } + + return UA_PARTI_MAX; +} + +/*----------------------------------------------------------------------------- + fota_blkid_update + ----------------------------------------------------------------------------*/ +int fota_blkid_update(void) +{ + char part_tbl_path[MAX_FILE_PATH]; + FILE *fp; + int num_part; + int i, j; + int id; + char part_name[256]; + char blk_name[256]; + + memset((void*)part_tbl_path, 0x00, sizeof(part_tbl_path)); + snprintf(part_tbl_path, sizeof(part_tbl_path)-1, "%s/%s", temp_folder, PART_TBL_FILE); + + fp = fopen(part_tbl_path, "r"); + if (fp == NULL) { + LOG("fail to open partition table\n"); + return -1; + } + + if ((fscanf(fp, "%d", &num_part)<0)||(num_part<=0)||(num_part>=MAX_PART_TBL_ITEM)) { + LOG("fail to fscanf() or num_part is 0\n"); + fclose(fp); + return -1; + } + for (i=0; i 0) { + s_part_num = ret; + } else { + LOG("Update Configuration fail. Use default.\n"); + memcpy(s_part_info, def_part_info, sizeof(s_part_info)); + memcpy(s_update_cfg, def_update_cfg, sizeof(s_update_cfg)); + s_part_num = UA_PARTI_MAX; + } + + /* load block device number at run-time */ + ret = fota_blkid_update(); + if (ret < 0) { + LOG("fota_blkid_update() fail\n"); + ret = UPI_PARTINFO_ERROR; + goto Results; + } + + ret = fota_path_init(); + if (ret == FAIL) { + ret = UPI_DELTA_PATH_LENGTH_ERROR; + goto Results; + } + + LOG("<<<<<<<<<<< log_init >>>>>>>>>>>>\n"); + + /* UPI version check */ + /* + if(S_RB_SUCCESS == RB_GetUPIVersion((unsigned char*)ver_str)) { + LOG("<<<<<<<<< RedBend Update Agent %s >>>>>>>>>>>>\n", ver_str); + } else { + LOG("[RB_GetUPIVersion fail] \n"); + ret = UPI_VERSION_ERROR; + goto Results; + } +*/ + /* Main Update Routine : Scout & Update */ + ret = update_all(); + LOG("[update_all ret=%d]\n", ret); + + Results: + LOG("Result=%d\n", ret); + save_result(ret); + remove_last_update_status(); + //remove_temp_files(); // TOTA + + switch (ret) { + /* GUI not initialized */ + case UPI_INVALID_PARAM_ERROR: + case UPI_DELTA_PATH_ERROR: + log_deinit(); + _exit_stdio(); + return -1; + case UPI_GUI_INIT_ERROR: + fota_path_deinit(); + log_deinit(); + _exit_stdio(); + return -1; + /* GUI initialized */ + case UPI_VERSION_ERROR: + case UPI_DELTACOUNT_ERROR: + + case UPI_ROOTFS_VERIFY_ERROR: + case UPI_BOOT_VERIFY_ERROR: + + case UPI_ROOTFS_UPDATE_ERROR: + case UPI_BOOT_UPDATE_ERROR: + + sleep(1); + fota_gui_update_end(); + fota_path_deinit(); + log_deinit(); + _exit_stdio(); + return -1; + case SUCCESS: + sleep(1); + fota_gui_update_end(); + fota_path_deinit(); + log_deinit(); + _exit_stdio(); + sleep(1); + return 0; + default: + LOG("!!! Not expected ret (= %d)\n", ret); + } + + _exit_stdio(); + return -1; +} diff --git a/src/tw1/ua.h b/src/tw1/ua.h new file mode 100755 index 0000000..6a9f16e --- /dev/null +++ b/src/tw1/ua.h @@ -0,0 +1,191 @@ +/* + * tota-ua + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed 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 __UA_H__ +#define __UA_H__ + +#include + +/* + * FEATURE + */ + +//#define USE_POST_UPDATE +//#define USE_DELTA_DOWNLOAD +//#define USE_DUALSBL + +#define LOG_FILE_PATH "/last_update.log" +#define MAX_FILE_PATH 512 + +#define PART_TBL_FILE "part_tbl.txt" +#define MAX_PART_TBL_ITEM 50 + +/* + * FOTA Adaptaion header + */ + +#define ERROR -1 // 0XFFFFFFFF + +#define INVALID 0 +#define VALID 1 +#define TRUE 1 +#define FALSE 0 +#define OK 0 +#define SUCCESS 0 +#define FAIL 1 +#define RESTORING 2 + +#define UPI_DELTA_PATH_ERROR 0xFDAA +#define UPI_DELTA_PATH_LENGTH_ERROR 0xFDAB + +#define UPI_GUI_INIT_ERROR 0xFDBA +#define UPI_VERSION_ERROR 0xFDBB + +#define UPI_ROOTFS_VERIFY_ERROR 0xFDC7 +#define UPI_BOOT_VERIFY_ERROR 0xFDC9 +#define UPI_RAMDISK1_VERIFY_ERROR 0xFDCC +#define UPI_DELTA_VERIFY_ERROR 0xFDCD +#define UPI_RAMDISK2_VERIFY_ERROR 0xFDCE + +#define UPI_ROOTFS_UPDATE_ERROR 0xFDD7 +#define UPI_BOOT_UPDATE_ERROR 0xFDD9 +#define UPI_RAMDISK1_UPDATE_ERROR 0xFDDC +#define UPI_RAMDISK2_UPDATE_ERROR 0xFDDE + +#define UPI_INVALID_PARAM_ERROR 0xFDEA +#define UPI_STATUSFLAG_ERROR 0xFDEB +#define UPI_DELTACOUNT_ERROR 0xFDEC +#define UPI_PARTINFO_ERROR 0xFDED + +/* UPI_NO_DELTA_ERROR and UPI_NO_UA_ERROR may be set by ua launching script */ +#define UPI_NO_DELTA_ERROR 0xFDFA +#define UPI_NO_UA_ERROR 0xFDFB + +#define TEMP_SIZE 0x40000 + +#define DEFAULT_DELTA_NAME "delta.tar" +#define UPDATTE_CFG_FILE "update.cfg" + +#define UI_OP_SCOUT_UPDATE 0 +#define UI_OP_SCOUT 1 +#define UI_OP_UPDATE 3 +#define SS_RECOVERYRAMDISK +enum { + UA_OP_MODE_FG = 0, + UA_OP_MODE_BG +}; + +typedef enum { + UA_ROOTFS = 0, + UA_BOOT, + UA_RAMDISK1, +#ifdef SS_RECOVERYRAMDISK + UA_RAMDISK2, +#endif + UA_PARTI_MAX +} UA_PART_IDX; + +#define UP_STATUS_FILE "UP.STATUS" +typedef enum { + UP_START_NONE = 0, + UP_START_ROOTFS, + UP_START_BOOT, + UP_START_RAMDISK1, +#ifdef SS_RECOVERYRAMDISK + UP_START_RAMDISK2, +#endif + UP_START_MAX +} UP_STATUS; + +typedef enum { + FULL_IMG, + DELTA_IMG, + DELTA_FS, + EXTRA +} UA_DATA_FORMAT; + +typedef enum{ + UA_MODE_SCOUT_UPDATE, + UA_MODE_SCOUT, + UA_MODE_VERIFYTARGET, + UA_MODE_UPDATE, + UA_MODE_SUPPLYIMFOM=200 +} UA_OPERATION_MODE; + +typedef struct _ua_update_data_t { + unsigned int exist_check; + unsigned int verify_check; + unsigned int update_check; + unsigned int weight; // the sum of weight should be 100 + unsigned int weight_offset; // start offset + unsigned int data_size; // byte + char *ua_delta_path; // it will be allocated to copy delta file path, need to free memory + char *ua_temp_path; // it will be allocated to copy delta file path, need to free memory +} ua_update_data_t; + +typedef struct _ua_update_cfg_t { + unsigned int update_type; + unsigned int part_idx; + int skip_verify; + int skip_update; + int soure_img_size;//TOTA + int target_img_size; + char *soure_sha1; + char *target_sha1; +} ua_update_cfg_t; + +typedef struct _ua_part_info_t { + char *ua_parti_name; + char *ua_subject_name; + char *ua_blk_name; + int ua_blk_offset; +} ua_part_info_t; + +// User data structure +typedef struct _ua_data_t { // partition operations + ua_part_info_t *parti_info; + ua_update_cfg_t *update_cfg; + ua_update_data_t *update_data; + unsigned long ua_operation; + + int (*ua_op_read_block)(void *, unsigned char*, unsigned long, unsigned long); + int (*ua_op_write_block)(void *, unsigned char*, unsigned long); + void (*ui_progress)(void *, unsigned long); +} ua_data_t; + + +typedef struct _ua_delta_info_t { + char ua_patch_path[MAX_FILE_PATH]; + char ua_patch_info[MAX_FILE_PATH]; + char ua_delta_path[MAX_FILE_PATH]; + char ua_attrib_path[MAX_FILE_PATH]; +} ua_delta_info_t; + + +typedef struct _ua_dataSS_t { // partition operations + ua_part_info_t *parti_info; + ua_update_cfg_t *update_cfg; + ua_update_data_t *update_data; + ua_delta_info_t *update_delta; + unsigned long ua_operation; + void (*ui_progress)(void *, unsigned long); + int (*write_data_to_blkdev)(char* , int , int , char* ); +} ua_dataSS_t; +void log_deinit(void); + +#endif -- 2.7.4