From 1d1a3ac3a3739b71e7575438f73c26d1b6e7a930 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Thu, 13 Jul 2017 10:44:28 +0900 Subject: [PATCH] Initial codes of tota-ua Change-Id: Iffdb362865f9dfbef2aeccf79cf760e09634c4c3 --- CMakeLists.txt | 100 +++ LICENSE | 204 ++++++ fota_gui/CMakeLists.txt | 78 +++ fota_gui/fota_common.h | 44 ++ fota_gui/fota_fbinfo.h | 30 + fota_gui/fota_gr.c | 73 ++ fota_gui/fota_gr.h | 31 + fota_gui/fota_gr_direct.c | 379 ++++++++++ fota_gui/fota_gr_direct.h | 29 + fota_gui/fota_gui_main.c | 214 ++++++ fota_gui/fota_gui_test.c | 199 ++++++ fota_gui/fota_log.h | 78 +++ fota_gui/fota_png.c | 411 +++++++++++ fota_gui/fota_png.h | 31 + fota_gui/fota_show_img.c | 120 ++++ fota_gui/tdm-if.c | 324 +++++++++ fota_gui/tdm-if.h | 72 ++ packaging/tota-ua.spec | 68 ++ packaging/tota.spec | 31 - res/rpi3/images/dummy.png | 1 + sign_verify/CMakeLists.txt | 56 ++ sign_verify/verify_delta.c | 454 ++++++++++++ src/common/fota_cfg.c | 32 + src/common/fota_cfg.h | 41 ++ src/common/fota_common.h | 55 ++ src/common/fota_log.c | 95 +++ src/common/fota_log.h | 78 +++ src/common/fota_tar.h | 29 + src/common/fota_util.c | 65 ++ src/common/fota_util.h | 26 + src/common/mmc_io.c | 201 ++++++ src/common/mmc_io.h | 52 ++ src/rpi3/ua.c | 1676 ++++++++++++++++++++++++++++++++++++++++++++ src/rpi3/ua.h | 210 ++++++ ss_engine/SS_FSUpdate.c | 1244 ++++++++++++++++++++++++++++++++ ss_engine/SS_FSUpdate.h | 407 +++++++++++ tota-ua.manifest | 9 + 37 files changed, 7216 insertions(+), 31 deletions(-) create mode 100755 CMakeLists.txt create mode 100755 LICENSE create mode 100755 fota_gui/CMakeLists.txt create mode 100755 fota_gui/fota_common.h create mode 100755 fota_gui/fota_fbinfo.h create mode 100755 fota_gui/fota_gr.c create mode 100755 fota_gui/fota_gr.h create mode 100755 fota_gui/fota_gr_direct.c create mode 100755 fota_gui/fota_gr_direct.h create mode 100755 fota_gui/fota_gui_main.c create mode 100755 fota_gui/fota_gui_test.c create mode 100755 fota_gui/fota_log.h create mode 100755 fota_gui/fota_png.c create mode 100755 fota_gui/fota_png.h create mode 100755 fota_gui/fota_show_img.c create mode 100755 fota_gui/tdm-if.c create mode 100755 fota_gui/tdm-if.h create mode 100755 packaging/tota-ua.spec delete mode 100644 packaging/tota.spec create mode 100644 res/rpi3/images/dummy.png create mode 100755 sign_verify/CMakeLists.txt create mode 100755 sign_verify/verify_delta.c create mode 100755 src/common/fota_cfg.c create mode 100755 src/common/fota_cfg.h create mode 100755 src/common/fota_common.h create mode 100755 src/common/fota_log.c create mode 100755 src/common/fota_log.h create mode 100755 src/common/fota_tar.h create mode 100755 src/common/fota_util.c create mode 100755 src/common/fota_util.h create mode 100755 src/common/mmc_io.c create mode 100755 src/common/mmc_io.h create mode 100644 src/rpi3/ua.c create mode 100644 src/rpi3/ua.h create mode 100755 ss_engine/SS_FSUpdate.c create mode 100755 ss_engine/SS_FSUpdate.h create mode 100755 tota-ua.manifest diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..683cee5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,100 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(fota C) + +IF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_RPI3") +SET(MODELDIR "rpi3") +ELSE() +SET(MODELDIR "rpi3") +ENDIF("${FOTA_PARTITION_TYPE}" STREQUAL "PART_RPI3") + +SET(SRCS + src/common/fota_cfg.c + #src/common/fota_tar.c + src/common/fota_util.c + src/common/fota_log.c + src/common/mmc_io.c + ss_engine/SS_FSUpdate.c + src/${MODELDIR}/ua.c +) + + + +STRING(FIND ${CMAKE_C_FLAGS} "mfloat-abi=hard" IFFOUND1) +STRING(FIND ${CMAKE_C_FLAGS} "mhard-float" IFFOUND2) + +IF(${IFFOUND1} GREATER 0 OR ${IFFOUND2} GREATER 0) + MESSAGE("hard") + SET(LIBS + libtota.a + ) +ELSE(${IFFOUND1} GREATER 0 OR ${IFFOUND2} GREATER 0) + MESSAGE("soft") + SET(LIBS + libtota.a + ) +ENDIF(${IFFOUND1} GREATER 0 OR ${IFFOUND2} GREATER 0) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/common) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/${MODELDIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/ss_engine) +LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/ss_engine) + + +SET(VENDOR "samsung") +SET(PACKAGE ${PROJECT_NAME}) +SET(PKGNAME "${PACKAGE}") +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(BINDIR "${PREFIX}/bin") +SET(PKGDIR "${PREFIX}/share/fota") +SET(RESDIR "${PKGDIR}/res") +SET(CFGDIR "${PKGDIR}/config") +SET(EXECNAME "delta.ua") + + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + libsmack + tota + openssl +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + + + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"") +ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"") +ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +ADD_DEFINITIONS("-DRESDIR=\"${RESDIR}\"") + +#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") + +ADD_EXECUTABLE(${EXECNAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${EXECNAME} ${pkgs_LDFLAGS} ${LIBS}) + +INSTALL(TARGETS ${EXECNAME} DESTINATION ${BINDIR}) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/${MODELDIR}/images DESTINATION ${RESDIR}) +# LICENSE file +ADD_SUBDIRECTORY(fota_gui) + diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..9c13a9b --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/fota_gui/CMakeLists.txt b/fota_gui/CMakeLists.txt new file mode 100755 index 0000000..619cf34 --- /dev/null +++ b/fota_gui/CMakeLists.txt @@ -0,0 +1,78 @@ +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) +STRING(FIND ${CMAKE_C_FLAGS} "mhard-float" IFFOUND2) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + + +INCLUDE(FindPkgConfig) +pkg_check_modules(gui_pkgs REQUIRED + libtbm + libtdm + libpng +) + +FOREACH(flag ${gui_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + + +SET(GUI_SRCS ${GUI_SRCS} fota_gr_direct.c) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-D${FOTA_PARTITION_TYPE}") + +#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") + +ADD_EXECUTABLE(${FOTA_GUI} ${GUI_SRCS}) +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_common.h b/fota_gui/fota_common.h new file mode 100755 index 0000000..b8de243 --- /dev/null +++ b/fota_gui/fota_common.h @@ -0,0 +1,44 @@ +/* + * 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_COMMON_H__ +#define __FOTA_COMMON_H__ + + +#include +#include "fota_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; + +#define UNUSED(x) (void)(x) + +#endif /* __FOTA_COMMON_H__ */ diff --git a/fota_gui/fota_fbinfo.h b/fota_gui/fota_fbinfo.h new file mode 100755 index 0000000..4b87fea --- /dev/null +++ b/fota_gui/fota_fbinfo.h @@ -0,0 +1,30 @@ +/* + * 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_FBINFO_H__ +#define __FOTA_FBINFO_H__ + +typedef struct _FbInfo { + unsigned char *buf; + unsigned sz; + int w; + int h; +} FbInfo; + +#endif /* __FOTA_FBINFO_H__ */ + diff --git a/fota_gui/fota_gr.c b/fota_gui/fota_gr.c new file mode 100755 index 0000000..8787e34 --- /dev/null +++ b/fota_gui/fota_gr.c @@ -0,0 +1,73 @@ +/* + * 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 "fota_gr.h" +#if defined(USE_CAIRO) +#include "fota_gr_cairo.h" +#else +#include "fota_gr_direct.h" +#endif + +/*----------------------------------------------------------------------------- + fota_gr_init + ----------------------------------------------------------------------------*/ +int fota_gr_init(void) +{ +#if defined(USE_CAIRO) + return fota_gr_cairo_init(); +#else + return fota_gr_direct_init(); +#endif +} + +/*----------------------------------------------------------------------------- + fota_gr_deinit + ----------------------------------------------------------------------------*/ +void fota_gr_deinit(void) +{ +#if defined(USE_CAIRO) + fota_gr_cairo_deinit(); +#else + fota_gr_direct_deinit(); +#endif +} + +/*----------------------------------------------------------------------------- + fota_gr_clear_screen + ----------------------------------------------------------------------------*/ +void fota_gr_clear_screen(u32 color) +{ +#if defined(USE_CAIRO) + fota_gr_cairo_clear_screen(color); +#else + fota_gr_direct_clear_screen(color); +#endif +} + +/*----------------------------------------------------------------------------- + fota_gr_update_progress + ----------------------------------------------------------------------------*/ +void fota_gr_update_progress(int percent) +{ +#if defined(USE_CAIRO) + fota_gr_cairo_update_progress(percent); +#else + fota_gr_direct_update_progress(percent); +#endif +} + diff --git a/fota_gui/fota_gr.h b/fota_gui/fota_gr.h new file mode 100755 index 0000000..fff1337 --- /dev/null +++ b/fota_gui/fota_gr.h @@ -0,0 +1,31 @@ +/* + * 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_GR_H__ +#define __FOTA_GR_H__ + +#include "fota_common.h" + +extern int fota_gr_init(void); +extern void fota_gr_deinit(void); +extern void fota_gr_update_progress(int percent); +extern void fota_gr_clear_screen(u32 color); + + +#endif /* __FOTA_GR_H__ */ + diff --git a/fota_gui/fota_gr_direct.c b/fota_gui/fota_gr_direct.c new file mode 100755 index 0000000..a9d8ff9 --- /dev/null +++ b/fota_gui/fota_gr_direct.c @@ -0,0 +1,379 @@ +/* + * 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_common.h" +#include "fota_png.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 G_OFFSET_X 100 +#define G_OFFSET_Y 200 + +#define PROGRESSBAR_WIDTH 400 +#define PROGRESSBAR_HEIGHT 25 + +#define PROGRESSBAR_START_X (40 + G_OFFSET_X) +#define PROGRESSBAR_START_Y (550 + G_OFFSET_Y) + + +#define MAX_PATH 256 + +#if !defined(RESDIR) +#define RESDIR "/usr/share/fota/res" +#endif +#define IMG_BASE RESDIR "/images/" + +#define MAIN_IMG_NAME "A07_firmware_update.png" +#define PROGRESS1_IMG_NAME "A07_progress_bar.png" +#define PROGRESS2_IMG_NAME "A07_progress_bg.png" +#define NUM_IMG_PREFIX "A07_num_" +#define PERCENT_IMG_NAME "A07_percent.png" + +/***************************************************************************** +** global variables +*****************************************************************************/ +FbInfo s_fbi; +FbInfo s_fbi_local; + +/*----------------------------------------------------------------------------- + _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 x1, int y1, char* str, int len) +{ + int i = 0; + int w = 0; + char ch; + char img_name[256]; + + for (i=0; i= '0') && (ch <= '9')) { + sprintf(img_name, "%s%s%c.png", IMG_BASE, NUM_IMG_PREFIX,ch); + w = 20; + } else if (ch == '%') { + sprintf(img_name, "%s%s", IMG_BASE, PERCENT_IMG_NAME); + w = 29; + } else { + continue; + } + + if (read_png_file(img_name) < 0) { + continue; + } + + draw_png_img_xy(fbi, x1, y1); + release_png_res(); + + x1 += w; + } +} + +/*----------------------------------------------------------------------------- + _gr_direct_draw_prog_text + ----------------------------------------------------------------------------*/ +static void _gr_direct_draw_prog_text(FbInfo *fbi, int percent) +{ + char str_percent[256]; + + if (percent <= 0) { + percent = 0; + } + + if (percent > 100) { + percent = 100; + } + + sprintf(str_percent, "%d%%", percent); + _gr_direct_fill_rect(fbi, 320, 751, 200, 32, COLOR_BLACK); + _gr_direct_draw_text(fbi, 320, 751, str_percent, strlen(str_percent)); +} + +/*----------------------------------------------------------------------------- + _gr_direct_draw_prog_img + ----------------------------------------------------------------------------*/ +static void _gr_direct_draw_prog_img(FbInfo *fbi, int percent) +{ + int img_x = 0; + int img_y = 0; + int x; + int shaft_max; + int shaft; + + if (read_png_file(IMG_BASE PROGRESS1_IMG_NAME) < 0) { + return; + } + + if (percent <= 0) { + return; + } + + if (percent > 100) { + percent = 100; + } + + /* left part */ + img_x = 36; + img_y = 696; + draw_png_img_clip_xy(fbi, img_x, img_y, 0, 0, 17, 27); + + /* middle part */ +#if 0 + for (x=36+17; x<=648+17; x+=2) { + draw_png_img_clip_xy(fbi, x, img_y, 17, 0, 2, 27); + } +#endif + + /* drawing range calculation : 0(1%), max(100%)*/ + shaft_max = 648 - 17 - 17; + shaft = shaft_max * (percent - 1) / 99; + + for (x=36+17; x<(36+17+shaft); x+=2) { + draw_png_img_clip_xy(fbi, x, img_y, 17, 0, 2, 27); + } + + /* right part */ + img_x = 36+17+shaft; + img_y = 696; + draw_png_img_clip_xy(fbi, img_x, img_y, 19, 0, 17, 27); + + release_png_res(); +} + + +/*----------------------------------------------------------------------------- + _gr_direct_draw_prog_bg_img + ----------------------------------------------------------------------------*/ +static void _gr_direct_draw_prog_bg_img(FbInfo *fbi) +{ + int img_x = 0; + int img_y = 0; + int x; + + if (read_png_file(IMG_BASE PROGRESS2_IMG_NAME) < 0) { + return; + } + + img_x = 36; + img_y = 696; + draw_png_img_xy(fbi, img_x, img_y); + + img_x = 648; + img_y = 696; + draw_png_img_xy(fbi, img_x, img_y); + + for (x=36+17; x<=648+17; x+=2) { + draw_png_img_clip_xy(fbi, x, img_y, 17, 0, 2, 27); + } + + 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 = (fbi->w - 456)/2; + img_y = 212; + + draw_png_img_xy(fbi, img_x, img_y); + release_png_res(); + +} + +/*----------------------------------------------------------------------------- + _gr_direct_update_screen + ----------------------------------------------------------------------------*/ +static void _gr_direct_update_screen() +{ + tdm_if_buffer_update(s_fbi.buf); + tdm_if_display_update(); +} + +/*----------------------------------------------------------------------------- + __init_screen + ----------------------------------------------------------------------------*/ +static void __init_screen(FbInfo *fbi) +{ + _gr_direct_clear_screen(fbi, COLOR_BLACK); + + _gr_direct_draw_main_img(fbi); + + _gr_direct_draw_prog_bg_img(fbi); + + _gr_direct_draw_prog_text(fbi, 0); + + _gr_direct_update_screen(); +} + +/*----------------------------------------------------------------------------- + fota_gr_direct_update_progress + ----------------------------------------------------------------------------*/ +void fota_gr_direct_update_progress(int percent) +{ + _gr_direct_draw_prog_img(&s_fbi, percent); + _gr_direct_draw_prog_text(&s_fbi, percent); + _gr_direct_update_screen(); +} + +/*----------------------------------------------------------------------------- + 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; + } + + tdm_if_lcd_off(); + + 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) +{ + if (s_fbi.buf) { + free(s_fbi.buf); + s_fbi.buf = NULL; + } + tdm_if_display_deinit(); +} + diff --git a/fota_gui/fota_gr_direct.h b/fota_gui/fota_gr_direct.h new file mode 100755 index 0000000..9bfd890 --- /dev/null +++ b/fota_gui/fota_gr_direct.h @@ -0,0 +1,29 @@ +/* + * 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_GR_DIRECT_H__ +#define __FOTA_GR_DIRECT_H__ + +#include "fota_common.h" + +extern int fota_gr_direct_init(void); +extern void fota_gr_direct_deinit(void); +extern void fota_gr_direct_clear_screen(u32 color); +extern void fota_gr_direct_update_progress(int percent); + +#endif /* __FOTA_GR_DIRECT_H__ */ diff --git a/fota_gui/fota_gui_main.c b/fota_gui/fota_gui_main.c new file mode 100755 index 0000000..8c92ac5 --- /dev/null +++ b/fota_gui/fota_gui_main.c @@ -0,0 +1,214 @@ +/* + * 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 "fota_common.h" +#include "fota_gr.h" + + +#define SERV_PATH "/tmp/FotaGuiSocket" + + +unsigned int __log_level__ = + (LOG_DEBUG | LOG_FLASH | LOG_FILE | LOG_FUNCS | LOG_GUI | LOG_REDBEND | LOG_INFO); +FILE *__log_out_file__; + +int s_prog_percent = 0; +int s_last_prog_percent = 0; + + +typedef struct { + char cmd_name[64]; + int argc; + char argv[3][64]; +}sock_cmd; + +typedef struct { + int ack; + char ack_desc[256]; +}sock_ack; + +#define CMD_SUCCESS 0 +#define CMD_ERROR -1 +#define MISSING_PARAM -2 + +int do_exit = 0; +int run_command(sock_cmd * recvbuff, sock_ack * sendbuff, int connfd) +{ + char cmd[100]; + int argc = 0, ret = -1; + int val = 0; + + memset(cmd, 0x00, sizeof(cmd)); + strncpy(cmd, recvbuff->cmd_name, sizeof(cmd)-1); + argc = recvbuff->argc; + + if (!strcmp(cmd, "draw_progress")) { + LOG("draw_progress selected\n"); + if (argc != 1) { + sendbuff->ack = MISSING_PARAM; + strcpy(sendbuff->ack_desc, "Missing parameter"); + ret = send(connfd, sendbuff, sizeof(sock_ack), 0); + } else { + LOG("argv[0]: %s\n", recvbuff->argv[0]); + ret = CMD_SUCCESS; + sendbuff->ack = ret; + strcpy(sendbuff->ack_desc, "Command recieved"); + ret = send(connfd, sendbuff, sizeof(sock_ack), 0); + + val = atoi(recvbuff->argv[0]); + if (val < 0) + val = 0; + else if (val > 100) + val = 100; + + s_prog_percent = val; + fota_gr_update_progress(s_prog_percent); + s_last_prog_percent = s_prog_percent; + } + } else if (!strcmp(cmd, "draw_end")) { + LOG("draw_end selected\n"); + if (argc != 0) { + sendbuff->ack = MISSING_PARAM; + strcpy(sendbuff->ack_desc, "Missing parameter"); + ret = send(connfd, sendbuff, sizeof(sock_ack), 0); + } else { + LOG("argv[0]: %s\n", recvbuff->argv[0]); + ret = CMD_SUCCESS; + sendbuff->ack = ret; + strcpy(sendbuff->ack_desc, "Command recieved"); + ret = send(connfd, sendbuff, sizeof(sock_ack), 0); + do_exit = 1; + } + } else { + LOG("Command Not Found \n"); + sendbuff->ack = MISSING_PARAM; + strcpy(sendbuff->ack_desc, "Command Not found"); + ret = send(connfd, sendbuff, sizeof(sock_ack), 0); + } + + return ret; +} + +int main(int argc, char **argv) +{ + int connfd = 0, sockfd = 0; + socklen_t slen, clen; + struct sockaddr_un saddr, caddr; + int cnt, done; + sock_cmd *recvbuff = NULL; + sock_ack *sendbuff = NULL; + + if (fota_gr_init() < 0) { + LOG("fota_gr_init() failed.\n"); + return -1; + } + + fota_gr_update_progress(s_prog_percent); + s_last_prog_percent = s_prog_percent; + + recvbuff = malloc(sizeof(sock_cmd)); + if (recvbuff == NULL) { + LOG("memory allocation failed:\n"); + return -1; + } + + sendbuff = malloc(sizeof(sock_ack)); + if (sendbuff == NULL) { + LOG("memory allocation failed:\n"); + return -1; + } + + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd <= 0) { + LOG("invalide sockfd\n"); + return -1; + } + + memset((char *)&saddr, 0, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + strcpy(saddr.sun_path, SERV_PATH); + saddr.sun_path[sizeof(SERV_PATH)] = '\0'; + slen = sizeof(saddr); + + unlink(SERV_PATH); + if (bind(sockfd, (const struct sockaddr *)&saddr, slen) < 0) { + LOG("bind fail\n"); + return -1; + } + + if (chmod(SERV_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) /* 0777 */ + LOG("failed to change the socket permission"); + + if (listen(sockfd, 5) < 0) { + LOG("listen fail\n"); + return -1; + } + + while(1) { + clen = sizeof(caddr); + connfd = accept(sockfd, (struct sockaddr *)&caddr, &clen); + if (connfd < 0) { + LOG("accept! \n"); + return -1; + } + + LOG("Client Connected...\n"); + + done = 0; + do { + cnt = 0; + cnt = recv(connfd, recvbuff, sizeof(sock_cmd), 0); + if (cnt <= 0) { + if (cnt < 0) { + perror("recv!"); + } + done = 1; + } + + if (!done) { + if (run_command(recvbuff, sendbuff, connfd) < 0) + done = 1; + } + + } while (!done); + + close(connfd); + + if (do_exit) + break; + } + + close(sockfd); + + fota_gr_deinit(); + + return 0; +} diff --git a/fota_gui/fota_gui_test.c b/fota_gui/fota_gui_test.c new file mode 100755 index 0000000..b6f775d --- /dev/null +++ b/fota_gui/fota_gui_test.c @@ -0,0 +1,199 @@ +/* + * 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 + +#define LOG printf + +#define SERV_PATH "/tmp/FotaGuiSocket" + +typedef struct { + char cmd_name[64]; + int argc; + char argv[3][64]; +}sock_cmd; + +typedef struct { + int ack; + char ack_desc[256]; +}sock_ack; + +#define CMD_SUCCESS 0 +#define CMD_ERROR -1 +#define MISSING_PARAM -2 + +int sockfd = 0; +int initcomplete = 0; +sock_cmd *sendbuff = NULL; +sock_ack *recvbuff = NULL; + +int sock_init(void) +{ + int len, ret; + struct sockaddr_un serv_addr; + + LOG("\n sock_init \n"); + sendbuff = malloc(sizeof(sock_cmd)); + if (sendbuff == NULL) { + LOG("memory allocation failed:%s\n", __FUNCTION__); + return -1; + } + + recvbuff = malloc(sizeof(sock_ack)); + if (recvbuff == NULL) { + LOG("memory allocation failed:%s\n", __FUNCTION__); + return -1; + } + + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd < 0) { + perror("\n Error : socket Failed \n"); + return -1; + } + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, SERV_PATH); + len = sizeof(serv_addr); + + ret = connect(sockfd, (struct sockaddr *)&serv_addr, len); + if (ret < 0) { + LOG("\n Error : Connect Failed \n"); + return -1; + } + + initcomplete = 1; + return ret; +} + +void sock_deinit(void) +{ + LOG("%s \n", __func__); + + close(sockfd); + free(sendbuff); + free(recvbuff); + initcomplete = 0; +} + +int sock_cmd_progress(int percent_progress) +{ + int result = 0; + + LOG("%s \n", __func__); + if (!initcomplete) { + LOG("sock_init unsuccessful \n"); + return -1; + } + + memset(sendbuff, 0, sizeof(sock_cmd)); + memset(recvbuff, 0xFF, sizeof(sock_ack)); + + strcpy(sendbuff->cmd_name, "draw_progress"); + sendbuff->argc = 1; + snprintf(sendbuff->argv[0], 63, "%d", percent_progress); + LOG("sendbuff->argv[0] = %s \n", sendbuff->argv[0]); + + result = write(sockfd, sendbuff, sizeof(sock_cmd)); + if (result < 0) { + LOG(" Write Failed! \n"); + return -1; + } + + result = read(sockfd, recvbuff, sizeof(sock_ack)); + recvbuff->ack_desc[255] = 0x00; + if (recvbuff->ack != CMD_SUCCESS || result < 0) { + LOG(" Fail %s ret(%d)\n", recvbuff->ack_desc, recvbuff->ack); + return -1; + } else + LOG("%s ret(%d)\n", recvbuff->ack_desc, recvbuff->ack); + + return recvbuff->ack; +} + +int sock_cmd_end(void) +{ + int result = 0; + + LOG("%s \n", __func__); + if (!initcomplete) { + LOG("sock_init unsuccessful \n"); + return -1; + } + + memset(sendbuff, 0, sizeof(sock_cmd)); + memset(recvbuff, 0xFF, sizeof(sock_ack)); + + strcpy(sendbuff->cmd_name, "draw_end"); + sendbuff->argc = 0; + + result = write(sockfd, sendbuff, sizeof(sock_cmd)); + if (result < 0) { + LOG(" Write Failed! \n"); + return -1; + } + + result = read(sockfd, recvbuff, sizeof(sock_ack)); + recvbuff->ack_desc[255] = 0x00; + if (recvbuff->ack != CMD_SUCCESS || result < 0) { + LOG(" Fail %s ret(%d)\n", recvbuff->ack_desc, recvbuff->ack); + return -1; + } else + LOG("%s ret(%d)\n", recvbuff->ack_desc, recvbuff->ack); + + return recvbuff->ack; +} + +int main(int argc, char **argv) +{ + int ret = -1; + int percent = 0; + + if (argc != 2) { + LOG("Invalid argc = %d\n", argc); + return -1; + } + + if (sock_init() < 0) { + LOG("sock_init() failed\n"); + return -1; + } + + percent = atoi(argv[1]); + if (percent == -1) { + ret = sock_cmd_end(); + } else { + ret = sock_cmd_progress(percent); + } + LOG("ret = %d\n", ret); + + sock_deinit(); + + return 0; +} + + diff --git a/fota_gui/fota_log.h b/fota_gui/fota_log.h new file mode 100755 index 0000000..b02af3c --- /dev/null +++ b/fota_gui/fota_log.h @@ -0,0 +1,78 @@ +/* + * 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_LOG_H__ +#define __FOTA_LOG_H__ + +#include + +/* + * 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_LOG_H__ */ + diff --git a/fota_gui/fota_png.c b/fota_gui/fota_png.c new file mode 100755 index 0000000..a31a70f --- /dev/null +++ b/fota_gui/fota_png.c @@ -0,0 +1,411 @@ +/* + * 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 "fota_common.h" +#include "fota_png.h" + +int png_img_width; +int png_img_height; +/* clear screen based on img size */ +//int png_img_width_batt_normal; +//int png_img_height_batt_normal; + +png_byte color_type; +png_byte bit_depth; + +png_structp png_ptr; +png_infop info_ptr; +int number_of_passes; +png_bytep *row_pointers; + +/*----------------------------------------------------------------------------- + read_png_file() + ----------------------------------------------------------------------------*/ +int read_png_file(char *file_name) +{ + char header[8]; /* 8 is the maximum size that can be checked */ + int y; + size_t rn; + + /* open file and test for it being a png */ + FILE *fp = fopen(file_name, "rb"); + if (!fp) { + LOG("[read_png_file] File %s could not be opened" + " for reading \n", file_name); + return -1; + } + + rn = fread(header, 1, 8, fp); + if (rn != 8) { + LOG("fread() read num mismatch\n"); + } + if (png_sig_cmp((png_bytep)header, 0, 8)) { + fclose(fp); + LOG("[read_png_file] File %s is not recognized" + " as a PNG file \n", file_name); + return -1; + } + + /* initialize stuff */ + png_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(fp); + LOG("[read_png_file] png_create_read_struct failed \n"); + return -1; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + fclose(fp); + LOG("[read_png_file] png_create_info_struct failed \n"); + return -1; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + LOG("[read_png_file] Error during init_io \n"); + return -1; + } + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + png_img_width = png_get_image_width(png_ptr, info_ptr); + png_img_height = png_get_image_height(png_ptr, info_ptr); + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + number_of_passes = png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + /* read file */ + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + LOG("[read_png_file] Error during read_image \n"); + return -1; + } + + row_pointers = (png_bytep *) malloc(sizeof(png_bytep)*png_img_height); + for (y = 0; y < png_img_height; y++) + row_pointers[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); + + png_read_image(png_ptr, row_pointers); + + fclose(fp); + + return 0; +} + +/*----------------------------------------------------------------------------- + draw_png_img_clip_xy() + - x1, y1 : cordinate on canvas (fb) + - cx, cy, cw, ch : image clip (rect on image) + ----------------------------------------------------------------------------*/ +void draw_png_img_clip_xy(FbInfo *fbi, int x1, int y1, int cx, int cy, int cw, int ch) +{ + unsigned int *fb_buf_cur = NULL; + int bpp; + int x, y; + /* temp patch - lcd resoultion for qualcomm */ + + fb_buf_cur = (unsigned int *)fbi->buf; + + /* check out range */ + if ((x1 + cw > fbi->w) || + (y1 + ch > fbi->h)) { + LOG("[%s] output range exceeds frame buffer range \n", __func__); + return; + } + + if ((cw > png_img_width) || (ch > png_img_height)) { + LOG("[%s] clip range exceeds image range \n", __func__); + return; + } + + if (color_type == PNG_COLOR_TYPE_RGB) + bpp = 3; + else if (color_type == PNG_COLOR_TYPE_RGBA) + bpp = 4; + else { + LOG("[draw_png_img_xy] png type does not match RGB or RGBA \n"); + return; + } + /* temp patch - lcd resoultion for qualcomm */ + fb_buf_cur += (y1 * (fbi->w)); + fb_buf_cur += x1; + for (y = 0; y < ch; y++) { + png_byte *row = (png_byte *) row_pointers[cy + y]; + if (bit_depth == 8) { + row += (bpp * cx); + } else if (bit_depth == 16) { + row += (bpp * 2 * cx); + } + for (x = 0; x < cw; x++) { + if (bpp == 3) { + if (bit_depth == 8) { + (*fb_buf_cur) = ((*fb_buf_cur)&0xff000000) | + (row[0] << 16) | (row[1] << 8) | (row[2]); + row += bpp; + } else if (bit_depth == 16) { + (*fb_buf_cur) = ((*fb_buf_cur)&0xff000000) | + (row[0] << 16) | (row[2] << 8) | (row[4]); + row += bpp*2; + } + } else if (bpp == 4) { + if (bit_depth == 8) { + if (row[3] != 0) { + char r1, g1, b1, a1; + char r2, g2, b2, a2; + char r3, g3, b3, a3; + // background pixel + b1 = ((*fb_buf_cur)&0x000000ff); + g1 = ((*fb_buf_cur)&0x0000ff00)>>8; + r1 = ((*fb_buf_cur)&0x00ff0000)>>16; + a1 = ((*fb_buf_cur)&0xff000000)>>24; + // new pixel + r2 = row[0]; + g2 = row[1]; + b2 = row[2]; + a2 = row[3]; + // blended pixel + r3 = (r2 * a2 + r1 * (0xff - a2)) >> 8 ; + g3 = (g2 * a2 + g1 * (0xff - a2)) >> 8; + b3 = (b2 * a2 + b1 * (0xff - a2)) >> 8; + a3 = a1; + (*fb_buf_cur) = (a3 << 24) | + (r3 << 16) | (g3 << 8) | (b3); + } + row += bpp; + } else if (bit_depth == 16) { + if (row[6] != 0) { + short r1, g1, b1, a1; + short r2, g2, b2, a2; + char r3, g3, b3, a3; + // background pixel + b1 = ((*fb_buf_cur)&0x000000ff)<<8; + g1 = ((*fb_buf_cur)&0x0000ff00); + r1 = ((*fb_buf_cur)&0x00ff0000)>>8; + a1 = ((*fb_buf_cur)&0xff000000)>>16; + // new pixel + r2 = (row[0]<<8) + row[1]; + g2 = (row[2]<<8) + row[3]; + b2 = (row[4]<<8) + row[5]; + a2 = (row[6]<<8) + row[7]; + // blended pixel + r3 = (r2 * a2 + r1 * (0xffff - a2)) >> 24; + g3 = (g2 * a2 + g1 * (0xffff - a2)) >> 24; + b3 = (b2 * a2 + b1 * (0xffff - a2)) >> 24; + a3 = a1 >> 8; + (*fb_buf_cur) = (a3 << 24) | + (r3 << 16) | (g3 << 8) | (b3); + } + row += bpp*2; + } + } + fb_buf_cur++; + } + fb_buf_cur -= cw; + fb_buf_cur += fbi->w;/* temp patch - lcd resoultion for qualcomm */ + } + +} + +/*----------------------------------------------------------------------------- + draw_png_img_xy() + ----------------------------------------------------------------------------*/ +void draw_png_img_xy(FbInfo *fbi, int x1, int y1) +{ + unsigned int *fb_buf_cur = NULL; + int bpp; + int x, y; + /* temp patch - lcd resoultion for qualcomm */ + + fb_buf_cur = (unsigned int *)fbi->buf; + + /* check out range */ + if ((x1 + png_img_width > fbi->w) || + (y1 + png_img_height > fbi->h)) { + LOG("[draw_png_img_xy] output range exceeds frame buffer range \n"); + return; + } + + if (color_type == PNG_COLOR_TYPE_RGB) + bpp = 3; + else if (color_type == PNG_COLOR_TYPE_RGBA) + bpp = 4; + else { + LOG("[draw_png_img_xy] png type does not match RGB or RGBA \n"); + return; + } + /* temp patch - lcd resoultion for qualcomm */ + fb_buf_cur += (y1 * (fbi->w)); + fb_buf_cur += x1; + for (y = 0; y < png_img_height; y++) { + png_byte *row = (png_byte *) row_pointers[y]; + for (x = 0; x < png_img_width; x++) { + if (bpp == 3) { + if (bit_depth == 8) { + (*fb_buf_cur) = ((*fb_buf_cur)&0xff000000) | + (row[0] << 16) | (row[1] << 8) | (row[2]); + row += bpp; + } else if (bit_depth == 16) { + (*fb_buf_cur) = ((*fb_buf_cur)&0xff000000) | + (row[0] << 16) | (row[2] << 8) | (row[4]); + row += bpp*2; + } + } else if (bpp == 4) { + if (bit_depth == 8) { + if (row[3] != 0) { + char r1, g1, b1, a1; + char r2, g2, b2, a2; + char r3, g3, b3, a3; + // background pixel + b1 = ((*fb_buf_cur)&0x000000ff); + g1 = ((*fb_buf_cur)&0x0000ff00)>>8; + r1 = ((*fb_buf_cur)&0x00ff0000)>>16; + a1 = ((*fb_buf_cur)&0xff000000)>>24; + // new pixel + r2 = row[0]; + g2 = row[1]; + b2 = row[2]; + a2 = row[3]; + // blended pixel + r3 = (r2 * a2 + r1 * (0xff - a2)) >> 8 ; + g3 = (g2 * a2 + g1 * (0xff - a2)) >> 8; + b3 = (b2 * a2 + b1 * (0xff - a2)) >> 8; + a3 = a1; + (*fb_buf_cur) = (a3 << 24) | + (r3 << 16) | (g3 << 8) | (b3); + } + row += bpp; + } else if (bit_depth == 16) { + if (row[6] != 0) { + short r1, g1, b1, a1; + short r2, g2, b2, a2; + char r3, g3, b3, a3; + // background pixel + b1 = ((*fb_buf_cur)&0x000000ff)<<8; + g1 = ((*fb_buf_cur)&0x0000ff00); + r1 = ((*fb_buf_cur)&0x00ff0000)>>8; + a1 = ((*fb_buf_cur)&0xff000000)>>16; + // new pixel + r2 = (row[0]<<8) + row[1]; + g2 = (row[2]<<8) + row[3]; + b2 = (row[4]<<8) + row[5]; + a2 = (row[6]<<8) + row[7]; + // blended pixel + r3 = (r2 * a2 + r1 * (0xffff - a2)) >> 24; + g3 = (g2 * a2 + g1 * (0xffff - a2)) >> 24; + b3 = (b2 * a2 + b1 * (0xffff - a2)) >> 24; + a3 = a1 >> 8; + (*fb_buf_cur) = (a3 << 24) | + (r3 << 16) | (g3 << 8) | (b3); + } + row += bpp*2; + } + } + fb_buf_cur++; + } + fb_buf_cur -= png_img_width; + fb_buf_cur += fbi->w;/* temp patch - lcd resoultion for qualcomm */ + } + +} + +/*----------------------------------------------------------------------------- + draw_png_mask_xy() + - draw pixel only when alpha>0 of given png image + ----------------------------------------------------------------------------*/ +void draw_png_mask_xy(FbInfo *fbi, int x1, int y1, char r, char g, char b) +{ + unsigned int *fb_buf_cur = NULL; + int bpp; + int x, y; + /* temp patch - lcd resoultion for qualcomm */ + + fb_buf_cur = (unsigned int *)fbi->buf; + + /* check out range */ + if ((x1 + png_img_width > fbi->w) || + (y1 + png_img_height > fbi->h)) { + LOG("[draw_png_img_xy] output range exceeds frame buffer range \n"); + return; + } + + if (color_type == PNG_COLOR_TYPE_RGB) { + bpp = 3; + LOG("[draw_png_img_xy] PNG_COLOR_TYPE_RGB : no mask channel \n"); + return; + } else if (color_type == PNG_COLOR_TYPE_RGBA) + bpp = 4; + else { + LOG("[draw_png_img_xy] png type does not match RGB or RGBA \n"); + return; + } + /* temp patch - lcd resoultion for qualcomm */ + fb_buf_cur += (y1 * (fbi->w)); + fb_buf_cur += x1; + for (y = 0; y < png_img_height; y++) { + png_byte *row = (png_byte *) row_pointers[y]; + for (x = 0; x < png_img_width; x++) { + if (bpp == 4) { + if (bit_depth == 8) { + if (row[3] != 0) { + (*fb_buf_cur) = ((*fb_buf_cur)&0xff000000) | + (r << 16) | (g << 8) | (b); + } + row += bpp; + } else if (bit_depth == 16) { + if (row[6] != 0) { + (*fb_buf_cur) = ((*fb_buf_cur)&0xff000000) | + (r << 16) | (g << 8) | (b); + } + row += bpp*2; + } + } + fb_buf_cur++; + } + fb_buf_cur -= png_img_width; + fb_buf_cur += fbi->w;/* temp patch - lcd resoultion for qualcomm */ + } + +} + +/*----------------------------------------------------------------------------- + release_png_res() + ----------------------------------------------------------------------------*/ +void release_png_res(void) +{ + int y; + + for (y = 0; y < png_img_height; y++) + free((void *)row_pointers[y]); + free((void *)row_pointers); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); +} + + + diff --git a/fota_gui/fota_png.h b/fota_gui/fota_png.h new file mode 100755 index 0000000..4d2a525 --- /dev/null +++ b/fota_gui/fota_png.h @@ -0,0 +1,31 @@ +/* + * 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_PNG_H__ +#define __FOTA_PNG_H__ + +#include "fota_fbinfo.h" + +extern int read_png_file(char *file_name); +extern void draw_png_img_xy(FbInfo *fbi, int x1, int y1); +extern void draw_png_img_clip_xy(FbInfo *fbi, int x1, int y1, int cx, int cy, int cw, int ch); +extern void draw_png_mask_xy(FbInfo *fbi, int x1, int y1, char r, char g, char b); +extern void release_png_res(void); + + +#endif /* __FOTA_PNG_H__ */ diff --git a/fota_gui/fota_show_img.c b/fota_gui/fota_show_img.c new file mode 100755 index 0000000..c70a407 --- /dev/null +++ b/fota_gui/fota_show_img.c @@ -0,0 +1,120 @@ +/* + * 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/fota_gui/tdm-if.c b/fota_gui/tdm-if.c new file mode 100755 index 0000000..6aa03ce --- /dev/null +++ b/fota_gui/tdm-if.c @@ -0,0 +1,324 @@ +/* + * 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 +#include +#include +#include +#include "tdm-if.h" +#include "fota_common.h" + +#define LOGD LOG + +tdm_if_disp s_st_disp; + +static void tdm_if_display_commit_handler_cb(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) +{ + LOGD("commit_handle_cb!!\n"); + + return ; +} + +int tdm_if_display_init(void) +{ + int color = 0; + int buf_cnt; + tdm_if_disp *st_disp = &s_st_disp; + tdm_error err = TDM_ERROR_NONE; + + tdm_output *output = NULL; + tdm_output_type output_type = TDM_OUTPUT_TYPE_Unknown; + tdm_output_conn_status conn_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + const tdm_output_mode *output_mode; + int output_count=0; + + tdm_info_layer layer_info; + + tbm_surface_info_s surf_info; + + int i=0; + + LOGD("start"); + + st_disp->disp = tdm_display_init(&err); + if (!st_disp->disp){ + LOGD("failed to init tdm_display. error num = %d\n", err); + goto exit; + } + + err = tdm_display_get_fd(st_disp->disp, &st_disp->tdm_fd); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get tdm fd. error num = %d\n", err); + goto exit; + } + + st_disp->drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD"); + if (st_disp->drm_fd == -1 ) + { + LOGD("failed to get tdm fd. error num = %d\n", err); + goto exit; + } + + err = tdm_display_get_output_count(st_disp->disp, &output_count); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get output count. error num = %d\n", err); + goto exit; + } + + for(i=0; idisp, i, &err); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get outout. error num = %d\n", err); + goto exit; + } + + err = tdm_output_get_output_type(output, &output_type); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get output type. error num = %d\n", err); + goto exit; + } + + err = tdm_output_get_conn_status(output, &conn_status); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get output connection status. error num = %d\n", err); + goto exit; + } + + LOGD("output_type=%d conn_status=%d\n", output_type, conn_status); + if ((output_type == TDM_OUTPUT_TYPE_LVDS) || (output_type == TDM_OUTPUT_TYPE_DSI)) + { + int cnt=0; + err = tdm_output_get_available_modes(output, &output_mode, &cnt); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get output available modes. error num = %d\n", err); + goto exit; + } + + /* GET MODE INFO */ + st_disp->output = output; + st_disp->width = output_mode->hdisplay; + st_disp->height = output_mode->vdisplay; + + unsigned int width_mm = 0; + unsigned int height_mm = 0; + err = tdm_output_get_physical_size(output, &width_mm, &height_mm); + LOGD("TDM_OUTPUT_MODE:name[%s] mode:wh[%d %d] mm[%d %d]", + output_mode->name, st_disp->width, st_disp->height, width_mm, height_mm); + + break; + } + } + + /* MEMORY ALLOCATION */ + st_disp->bufmgr = tbm_bufmgr_init(st_disp->drm_fd); + if (!st_disp->bufmgr){ + LOGD("failed to tbm_bufmgr_init\n"); + goto exit; + } + + st_disp->buffer_size = st_disp->width * st_disp->height * RGB32_PITCH; + st_disp->stride = st_disp->width * RGB32_PITCH; + + surf_info.width = st_disp->width; + surf_info.height = st_disp->height; + surf_info.format = TBM_FORMAT_ARGB8888; + surf_info.bpp = 32; + surf_info.size = st_disp->buffer_size; + surf_info.num_planes = 1; + surf_info.planes[0].size = st_disp->buffer_size; + surf_info.planes[0].offset = 0; + surf_info.planes[0].stride = st_disp->stride; + + for (buf_cnt = 0; buf_cnt < MAX_BUF; buf_cnt++) { + st_disp->bo[buf_cnt] = tbm_bo_alloc(st_disp->bufmgr, st_disp->buffer_size, TBM_BO_SCANOUT ); + if (!st_disp->bo[buf_cnt]){ + LOGD("failed to tbm_bo_alloc\n"); + goto exit; + } + + st_disp->bo_handle[buf_cnt] = tbm_bo_map(st_disp->bo[buf_cnt], TBM_DEVICE_CPU, TBM_OPTION_WRITE); + st_disp->buffer[buf_cnt] = st_disp->bo_handle[buf_cnt].ptr; + st_disp->handle[buf_cnt] = tbm_bo_get_handle(st_disp->bo[buf_cnt], TBM_DEVICE_2D).u32; + + memset(st_disp->buffer[buf_cnt], color, st_disp->stride * st_disp->height); + + tbm_bo_unmap(st_disp->bo[buf_cnt]); + + st_disp->surf[buf_cnt] = tbm_surface_internal_create_with_bos(&surf_info, &st_disp->bo[buf_cnt], 1); + if (!st_disp->surf[buf_cnt]){ + LOGD("failed to create tbm_surface!!\n"); + goto exit; + } + } + + /* SET LAYER */ + tdm_layer_capability layer_caps; + tdm_layer *tmp_layer = NULL; + for(i=0; ioutput, output_count, &err); + tdm_layer_get_capabilities(tmp_layer, &layer_caps); + if (layer_caps & TDM_LAYER_CAPABILITY_PRIMARY) + break; + } + + if (!tmp_layer) + { + LOGD("failed to get output layer. error num = %d\n", err); + goto exit; + } + + st_disp->layer = tmp_layer; + + layer_info.src_config.size.h = st_disp->width; + layer_info.src_config.size.v = st_disp->height; + layer_info.src_config.pos.x = 0; + layer_info.src_config.pos.y = 0; + layer_info.src_config.pos.w = st_disp->width; + layer_info.src_config.pos.h = st_disp->height; + layer_info.src_config.format = TBM_FORMAT_ARGB8888; + layer_info.dst_pos.x = 0; + layer_info.dst_pos.y = 0; + layer_info.dst_pos.w = st_disp->width; + layer_info.dst_pos.h = st_disp->height; + layer_info.transform = TDM_TRANSFORM_NORMAL; + + err = tdm_layer_set_info(st_disp->layer, &layer_info); + if (err != TDM_ERROR_NONE) + { + LOGD("failed to get output layer. error num = %d\n", err); + goto exit; + } + + st_disp->current_buf_id = 0; + + LOGD("done\n"); + return 0; +exit: + tdm_if_display_deinit(); + return -1; +} + +void tdm_if_display_deinit(void) +{ + int buf_cnt = 0; + tdm_if_disp *st_disp = &s_st_disp; + + if (st_disp->disp != NULL) + { + /* RELEASE RESOURCE */ + for (buf_cnt = 0; buf_cnt < MAX_BUF; buf_cnt++) { + if (st_disp->surf[buf_cnt] != NULL) + tbm_surface_destroy(st_disp->surf[buf_cnt]); + + if (st_disp->bo[buf_cnt] != NULL) + tbm_bo_unref(st_disp->bo[buf_cnt]); + } + + if (st_disp->bufmgr != NULL) + tbm_bufmgr_deinit(st_disp->bufmgr); + st_disp->bufmgr = NULL; + + tdm_display_deinit(st_disp->disp); + st_disp->disp = NULL; + } +} + +int tdm_if_display_width(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->width; +} + +int tdm_if_display_height(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->height; +} + +int tdm_if_display_bufsize(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->buffer_size; +} + +void tdm_if_buffer_update(unsigned char *buffer) +{ + tdm_if_disp *st_disp = &s_st_disp; + int buf_cnt = st_disp->current_buf_id; + memcpy(st_disp->buffer[buf_cnt], buffer, st_disp->stride * st_disp->height); +} + +void tdm_if_display_update(void) +{ + /* DISPLAY UPDATE */ + int buf_cnt = 0; + tdm_if_disp *st_disp = &s_st_disp; + + buf_cnt = st_disp->current_buf_id; + st_disp->current_buf_id = (++st_disp->current_buf_id)%MAX_BUF; + + tdm_layer_set_buffer(st_disp->layer, st_disp->surf[buf_cnt]); + + // TODO: sync or async?? + tdm_output_commit(st_disp->output, 1, tdm_if_display_commit_handler_cb, st_disp); + + return ; +} +void tdm_if_lcd_on(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + + /* SET DPMS ON */ + LOGD("DPMS ON!\n"); + tdm_output_set_dpms(st_disp->output, TDM_OUTPUT_DPMS_ON); + + return ; +} + +void tdm_if_lcd_off(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + + /* SET DPMS OFF */ + LOGD("DPMS OFF!\n"); + tdm_output_set_dpms(st_disp->output, TDM_OUTPUT_DPMS_OFF); + + return ; +} diff --git a/fota_gui/tdm-if.h b/fota_gui/tdm-if.h new file mode 100755 index 0000000..8693dba --- /dev/null +++ b/fota_gui/tdm-if.h @@ -0,0 +1,72 @@ +/* + * 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 __TDM_IF_H__ +#define __TDM_IF_H__ + +#include +#include +#include +#include +#include + +#define MAX_BUF 2 +#define RGB32_BPP 32 +#define RGB32_PITCH 4 + +typedef struct _tdm_if_disp { + tdm_display *disp; + tdm_output *output; + tdm_layer *layer; + tdm_pp *pp; + int tdm_fd; + int drm_fd; + tbm_surface_h surf[MAX_BUF]; + tbm_surface_h pp_surf[MAX_BUF]; + tbm_bufmgr bufmgr; + unsigned int handle[MAX_BUF]; + tbm_bo bo[MAX_BUF]; + tbm_bo_handle bo_handle[MAX_BUF]; + void *buffer[MAX_BUF]; + int buffer_size; + int width; + int height; + int stride; + int current_buf_id; +} tdm_if_disp; + +typedef enum { + FRONT_BUFFER = 0, + BACK_BUFFER +} BUFFER_TYPE; + +extern tdm_if_disp s_disp; + +int tdm_if_display_init(void); +void tdm_if_display_deinit(void); +void tdm_if_display_update(void); +int tdm_if_display_width(void); +int tdm_if_display_height(void); +int tdm_if_display_bufsize(void); + +void tdm_if_buffer_update(unsigned char *buffer); + +void tdm_if_lcd_on(void); +void tdm_if_lcd_off(void); + +#endif /* __TDM_IF_H__ */ diff --git a/packaging/tota-ua.spec b/packaging/tota-ua.spec new file mode 100755 index 0000000..2808a8a --- /dev/null +++ b/packaging/tota-ua.spec @@ -0,0 +1,68 @@ +Name: tota-ua +Summary: fota update agent +ExclusiveArch: %{arm} +Version: 0.1.0 +Release: 1 +Group: System +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz + +BuildRequires: cmake +BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(libtdm) +BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(libpng) +BuildRequires: pkgconfig(libssl) +BuildRequires: pkgconfig(tota) +BuildRequires: pkgconfig(openssl) + +Requires: %{name}-compat = %{version}-%{release} +Recommends: %{name}-target_rpi3 = %{version}-%{release} + +%description +Fota update agent which update firmware using delta files + +%package target_rpi3 +Summary: TOTA update agent for RPi3 target +Provides: %{name}-compat = %{version}-%{release} +%description target_rpi3 +TOTA update agent binary targeting RPi3 target. + +%prep +%setup -q + + +%build +export LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--as-needed" +LDFLAGS="$LDFLAGS" + +mkdir -p build_rpi3 +pushd build_rpi3 +%cmake .. \ + -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DFOTA_PARTITION_TYPE="PART_RPI3" + +make %{?jobs:-j%jobs} +popd + +%install +rm -rf %{buildroot} + +pushd build_rpi3 +%make_install +mv %{buildroot}%{_bindir}/delta.ua %{buildroot}%{_bindir}/delta.ua.rpi3 +popd + +%post target_rpi3 +mv %{_bindir}/delta.ua.rpi3 %{_bindir}/delta.ua + +%post + +%files +%license LICENSE +%manifest tota-ua.manifest + +%files target_rpi3 +%defattr(-,root,root,-) +%{_prefix}/share/fota +%{_prefix}/bin/* diff --git a/packaging/tota.spec b/packaging/tota.spec deleted file mode 100644 index 5721cf4..0000000 --- a/packaging/tota.spec +++ /dev/null @@ -1,31 +0,0 @@ -%define keepstatic 1 - -Name: tota -Summary: Tizen OTA update -Version: 1.0.0 -Release: 1 -Group: System/Service -License: BSD-3-Clause and BSD-2-Clause and LGPL-2.1+ and MIT and SAMSUNG -Source0: %{name}-%{version}.tar.gz - -%description -Tizen OTA(over-the-air) update package. -This package provides update agent. - -%package rpi3 -Summary: Tizen OTA update for RPi3 - -%description rpi3 -Tizen OTA(over-the-air) update package. -This package provides RPi3 target specific files. - -%prep -%setup -q - -%build - -%install - -%files - -%files rpi3 diff --git a/res/rpi3/images/dummy.png b/res/rpi3/images/dummy.png new file mode 100644 index 0000000..d0eec47 --- /dev/null +++ b/res/rpi3/images/dummy.png @@ -0,0 +1 @@ +This is not a used file. diff --git a/sign_verify/CMakeLists.txt b/sign_verify/CMakeLists.txt new file mode 100755 index 0000000..fa4e69a --- /dev/null +++ b/sign_verify/CMakeLists.txt @@ -0,0 +1,56 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +#set( CMAKE_VERBOSE_MAKEFILE on ) + +SET(VERIFY_SRCS + verify_delta.c +) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(BINDIR "${PREFIX}/bin") +SET(VERIFYUTIL "verify_delta") + + +STRING(FIND ${CMAKE_C_FLAGS} "mfloat-abi=hard" IFFOUND1) +STRING(FIND ${CMAKE_C_FLAGS} "mhard-float" IFFOUND2) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + + +INCLUDE(FindPkgConfig) +pkg_check_modules(verify_pkgs REQUIRED + openssl +) + +FOREACH(flag ${verify_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-D${FOTA_PARTITION_TYPE}") + +#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") + +ADD_EXECUTABLE(${VERIFYUTIL} ${VERIFY_SRCS}) +TARGET_LINK_LIBRARIES(${VERIFYUTIL} ${verify_pkgs_LDFLAGS}) + + +INSTALL(TARGETS ${VERIFYUTIL} DESTINATION ${BINDIR}) + + diff --git a/sign_verify/verify_delta.c b/sign_verify/verify_delta.c new file mode 100755 index 0000000..e800b77 --- /dev/null +++ b/sign_verify/verify_delta.c @@ -0,0 +1,454 @@ +/* + * 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 + +#define _DEBUG_ERROR(s, args...) printf(s "\n", ##args) +#define _DEBUG_WARNING(s, args...) printf(s "\n", ##args) +#define _DEBUG_INFO(s, args...) printf(s "\n", ##args) + +#define _INNER_FUNC_ENTER +#define _INNER_FUNC_EXIT + + +typedef struct timeval timestamp; + +int verify_FOTA_image(const char *cacert_path, const char *path); + + +int main(int argc, char **argv) +{ + int ret = 0; + + if (argc != 3) { + _DEBUG_WARNING("Usage: %s {cert file} {data file}" , argv[0]); + return -1; + } + + ret = verify_FOTA_image(argv[1], argv[2]); + if (ret == 0) { + _DEBUG_INFO("verify_FOTA_image succed!!"); + } else { + _DEBUG_WARNING("verify_FOTA_image failed [%d]" , ret); + ret = -1; + } + + return ret; +} + + +static void get_ts1(timestamp *ts) +{ + gettimeofday((struct timeval *) ts, NULL); +} + +static long e_ts2(timestamp *start, timestamp *end) +{ + return (end->tv_sec - start->tv_sec) * 1000 + (end->tv_usec + - start->tv_usec) / 1000; +} + + +static X509 *load_cert_mem(const unsigned char *cert_data, const int cert_len) +{ + _INNER_FUNC_ENTER; + X509 *cert = 0; + BIO *cert_bio = 0; + + if (!(cert_bio = BIO_new_mem_buf( + (unsigned char *)cert_data, cert_len))) { + _DEBUG_ERROR("BIO mem error"); + goto end; + } + cert = d2i_X509_bio(cert_bio, NULL); + +end: + if (cert_bio) + BIO_free(cert_bio); + + _INNER_FUNC_EXIT; + return cert; +} + +static int check(X509_STORE *ctx, X509 *cert) +{ + _INNER_FUNC_ENTER; + int ret = -140; + X509_STORE_CTX *csc = 0; + + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + _DEBUG_ERROR("X509 csc is null"); + goto end; + } + + ret = -141; + X509_STORE_set_flags(ctx, 0); + if(!X509_STORE_CTX_init(csc, ctx, cert, 0)) { + _DEBUG_ERROR("X509 store ctx init failed"); + goto end; + } + + if (X509_verify_cert(csc) != 1) { + _DEBUG_ERROR("err: %s", X509_verify_cert_error_string(csc->error)); + //fprintf(stderr,"MDFPP_E: %s\n", X509_verify_cert_error_string(csc->error)); + ret = -142; + goto end; + } + + ret = 0; +end: + if (csc) + X509_STORE_CTX_free(csc); + + _INNER_FUNC_EXIT; + return ret; +} + +static X509 *verify_certificate(const unsigned char *certdata, unsigned int certlength, + const char* CAfile, int *result) +{ + _INNER_FUNC_ENTER; + int ret = -130; + X509_STORE *cert_ctx=NULL; + X509_LOOKUP *lookup=NULL; + X509 *cert = 0; + + cert_ctx = X509_STORE_new(); + if (cert_ctx == NULL) { + _DEBUG_ERROR("cert_ctx is NULL"); + goto end; + } + + OpenSSL_add_all_algorithms(); + + ret = -131; + lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file()); + if (lookup == NULL) { + _DEBUG_ERROR("X509 lookup is NULL"); + goto end; + } + + ret = -132; + if(!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_ASN1)) { + _DEBUG_ERROR("X509 load file failed"); + goto end; + } + + ret = -133; + lookup=X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + _DEBUG_ERROR("X509 add lookup failed"); + goto end; + } + + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + ret = -134; + cert = load_cert_mem(certdata, certlength); + if (cert == NULL) { + _DEBUG_ERROR("cannot load cert from mem"); + goto end; + } + + ret = check(cert_ctx, cert); + +end: + if (cert_ctx) + X509_STORE_free(cert_ctx); + + *result = ret; + _INNER_FUNC_EXIT; + return cert; +} + +typedef struct fota_sign_info { + unsigned char SECSIG[4]; + + //uint16_t x509size; + unsigned int x509size; + + unsigned char crypt; + unsigned char hash; + unsigned char padding; + unsigned char salt; + unsigned char size; + unsigned char reserved[5]; + unsigned char *sig; + unsigned int sig_size; +} FOTA_SIGN_INFO; + +static int verify_signature(int fd, size_t length, EVP_PKEY *pkey, + unsigned char *sig, int siglen, const EVP_MD *md) +{ + _INNER_FUNC_ENTER; + unsigned char buffer[32*1024]; + EVP_MD_CTX *md_ctx; + EVP_PKEY_CTX *ctx; + size_t readreq = 32*1024; + size_t readbytes = readreq; + unsigned char md_value[64] = {0}; + int md_size = 0; + size_t totalbytes = 0; + + // Init hash + md_ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(md_ctx, md, NULL); + + // Calc hash + lseek(fd, 0, SEEK_SET); + while (totalbytes < length) { + if (totalbytes + readreq >= length) + readreq = length - totalbytes; + readbytes = read(fd, buffer, readreq); + + if(EVP_DigestUpdate(md_ctx, buffer, readbytes) != 1) { // Prevent 47917 - adding the return value check. + _INNER_FUNC_EXIT; + return -101; + } + totalbytes += readbytes; + } + EVP_DigestFinal(md_ctx, md_value, (unsigned int *)&md_size); + + EVP_MD_CTX_destroy(md_ctx); + + // Init signature algorithm + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!ctx) { + _INNER_FUNC_EXIT; + return -101; + } + if (EVP_PKEY_verify_init(ctx) <= 0) { + _INNER_FUNC_EXIT; + return -102; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { + _INNER_FUNC_EXIT; + return -103; + } + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -2) <= 0) { + _INNER_FUNC_EXIT; + return -104; + } + if (EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + _INNER_FUNC_EXIT; + return -105; + } + + // ret == 1 indicates success, 0 verify failure and < 0 for some other error. + if (EVP_PKEY_verify(ctx, sig, siglen, md_value, md_size) != 1) { +// SLOGE("Signature verification failed\n"); + _INNER_FUNC_EXIT; + return -106; + } + + // success + _INNER_FUNC_EXIT; + return 0; +} + +int verify_FOTA_image(const char *cacert_path, const char *path) +{ + _INNER_FUNC_ENTER; + int ret = -110; + X509 *cert = 0; + EVP_PKEY *pkey; + int fd = 0; + int rd = 0; + int length = 0; + off_t offset = 0; + unsigned char buffer[4096]; + int cmtsize = 0; + int old_sigsize = 0; + unsigned char *x509 = 0; + FOTA_SIGN_INFO fota_sign_info; + const EVP_MD *md; + timestamp s, e; + + if (!cacert_path || !path) { + _INNER_FUNC_EXIT; + return -111; + } + if (strlen(cacert_path) > 64) { + _INNER_FUNC_EXIT; + return -112; + } + if (strlen(path) > 64) { + _INNER_FUNC_EXIT; + return -113; + } + + /* + * Prepare OpenSSL + */ + OpenSSL_add_all_digests(); + + pkey = EVP_PKEY_new(); + + /* + * Load Certificate + */ + fd = open(path, O_RDONLY, 0644); + if (fd < 0) { + _DEBUG_WARNING("Warning: Failed to open %s : %s", + path, strerror(errno)); + _INNER_FUNC_EXIT; + return -114; + } + + /* + * Goto Footer + */ + if( (length = lseek(fd, 0, SEEK_END)) == -1){ + _DEBUG_ERROR("lseek error is %d", errno); + ret = -115; + goto end; + } + + if( lseek(fd, length - 6, SEEK_SET) == -1){ + _DEBUG_ERROR("lseek error is %d", errno); + ret = -116; + goto end; + } + + if ((rd = read(fd, buffer, 6)) != 6) { + ret = -117; + goto end; + } + // check footer constant + if (buffer[2] != 0xff || buffer[3] != 0xff) { + ret = -118; + goto end; + } + // calc comment size and start offset of sig + old_sigsize = (buffer[1] << 8) + buffer[0]; + cmtsize = (buffer[5] << 8) + buffer[4]; + + /* + * Goto Zip Comments + */ + // original string comments 'signed by SignApk" : 18 bytes + // FOTA sig header : 16 bytes + // FOTA sig : 256 bytes + // Certificate : variable (1~2k) + // original signature: variable + if( lseek(fd, length - cmtsize, SEEK_SET) == -1){ + _DEBUG_ERROR("lseek error is %d", errno); + ret = -119; + goto end; + } + + if( (cmtsize-old_sigsize) < 0 || (unsigned int)(cmtsize-old_sigsize) > sizeof(buffer)){ + ret = -119; + goto end; + } + + if ((rd = read(fd, buffer, cmtsize-old_sigsize)) != (int)(cmtsize-old_sigsize)) { + _DEBUG_ERROR("invalid comments size = %d", rd); + ret = -120; + goto end; + } + + // Goto FOTA signature + // check FOTA signature header + offset = strlen("signed by SignApk") + 1; + // copy header + memcpy((void *)&fota_sign_info, buffer+offset, 16); + + // assign buffer + fota_sign_info.sig = buffer+offset+16; + + if (fota_sign_info.SECSIG[0] != 0x53 || + fota_sign_info.SECSIG[1] != 0x45 || + fota_sign_info.SECSIG[2] != 0x43 || + fota_sign_info.SECSIG[3] != 0x53) { + _DEBUG_WARNING("invalid FOTA signature"); + ret = -121; + goto end; + } + // get signature size + switch (fota_sign_info.size) { + default: + fota_sign_info.sig_size = 256; + break; + } + // get x509 buffer + x509 = buffer + offset + 16 + fota_sign_info.sig_size; + + /* + * Verify Certificate + */ + get_ts1(&s); + cert = verify_certificate(x509, fota_sign_info.x509size, + cacert_path, &ret); + get_ts1(&e); + if (!cert || ret) { + _DEBUG_ERROR("verify_certificate failed with %d", ret); + ret = -122; + goto end; + } + + _DEBUG_INFO("Certificate verified OK (%ldms)", e_ts2(&s, &e)); + //_DEBUG_INFO("Certificate verified OK", e_ts2(&s, &e)); + + /* + * Signature verification + */ + get_ts1(&s); + switch (fota_sign_info.hash) { + default: + + md = EVP_get_digestbyname("SHA512"); + break; + } + pkey = X509_get_pubkey(cert); + if ( (length - cmtsize - 2) < 0) { // Fixed for prevent. CID:48010 + _DEBUG_ERROR("length is wrong!!"); + ret = -123; + goto end; + } + ret = verify_signature(fd, (size_t)(length - cmtsize - 2)/*size of comment length field*/, + pkey, fota_sign_info.sig, fota_sign_info.sig_size, md); + get_ts1(&e); + if(ret != 0) { + _DEBUG_ERROR("Signature verified NOK(%d) (%ldms)", ret, e_ts2(&s, &e)); + } else { + _DEBUG_INFO("Signature verified OK (%ldms)", e_ts2(&s, &e)); + } + +end: + if (pkey) + EVP_PKEY_free(pkey); + if (cert) + X509_free(cert); + if (fd) + close(fd); + + return ret; +} + diff --git a/src/common/fota_cfg.c b/src/common/fota_cfg.c new file mode 100755 index 0000000..23747e2 --- /dev/null +++ b/src/common/fota_cfg.c @@ -0,0 +1,32 @@ +/* + * 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 "fota_cfg.h" + +char fota_cfg_str[EN_CFG_MAX][CFG_MAX_LEN]; + +void fota_cfg_str_load(void) +{ + strncpy(fota_cfg_str[EN_CFG_SUPPORT_FB], "1", CFG_MAX_LEN-1); + strncpy(fota_cfg_str[EN_CFG_SUPPORT_DRM], "0", CFG_MAX_LEN-1); + strncpy(fota_cfg_str[EN_CFG_DEV_FB], "/dev/fb0", CFG_MAX_LEN-1); + strncpy(fota_cfg_str[EN_CFG_DEV_DRM_NAME], "exynos", CFG_MAX_LEN-1); +} + diff --git a/src/common/fota_cfg.h b/src/common/fota_cfg.h new file mode 100755 index 0000000..0afd301 --- /dev/null +++ b/src/common/fota_cfg.h @@ -0,0 +1,41 @@ +/* + * 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_CFG_H__ +#define __FOTA_CFG_H__ + +#define CFG_MAX_LEN 1024 + +enum { + EN_CFG_SUPPORT_FB, + EN_CFG_SUPPORT_DRM, + EN_CFG_DEV_FB, + EN_CFG_DEV_DRM_NAME, + EN_CFG_MAX +}; + +extern char fota_cfg_str[EN_CFG_MAX][CFG_MAX_LEN]; + + +extern void fota_cfg_str_load(void); + + + +#endif /* __FOTA_FB_H__ */ + + diff --git a/src/common/fota_common.h b/src/common/fota_common.h new file mode 100755 index 0000000..c766a70 --- /dev/null +++ b/src/common/fota_common.h @@ -0,0 +1,55 @@ +/* + * 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_COMMON_H__ +#define __FOTA_COMMON_H__ + + +#include +#include "fota_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; + +#ifndef HEAP_PROFILING + //#define HEAP_PROFILING; +#endif +#define UNUSED(x) (void)(x) + +struct tar_Data { + int itemSize; + int itemOffset; + int itemName[256]; + struct tar_Data *nextnode; +}; +typedef struct tar_Data tar_Data_t; + +#endif /* __FOTA_COMMON_H__ */ diff --git a/src/common/fota_log.c b/src/common/fota_log.c new file mode 100755 index 0000000..3e078f4 --- /dev/null +++ b/src/common/fota_log.c @@ -0,0 +1,95 @@ +/* + * 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 + +long curr_offset = 0; +long next_offset = 0; +long cut_offset = 0; +long max_logfile_size = (2*1024*1024); + +/*----------------------------------------------------------------------------- + log_printf + ----------------------------------------------------------------------------*/ +int log_printf(FILE* log_fp, char* format_str, ...) +{ + int ret = 0; + char log_str[4096]; + int len; + int wlen; + va_list list; + + va_start(list, format_str); + vsprintf(log_str, format_str, list); + va_end(list); + + len = strlen(log_str); + next_offset = curr_offset + len; + + if (next_offset <= max_logfile_size) { + wlen = len; + if (fwrite(log_str, 1, wlen, log_fp) != wlen) { + ret = -1; + goto exit; + } + curr_offset = next_offset; + if (curr_offset == max_logfile_size) { + rewind(log_fp); + curr_offset = 0; + } + } else { + cut_offset = max_logfile_size - curr_offset; + wlen = cut_offset; + if (fwrite(log_str, 1, wlen, log_fp) != wlen) { + ret = -1; + goto exit; + } + rewind(log_fp); + wlen = next_offset - max_logfile_size; + if (fwrite(log_str+cut_offset, 1, wlen, log_fp) != wlen) { + ret = -1; + goto exit; + } + curr_offset = next_offset - max_logfile_size; + } + +exit: + return ret; +} + +/*----------------------------------------------------------------------------- + truncate_log_file + ----------------------------------------------------------------------------*/ +void truncate_log_file(char *log_path, int size_kb) +{ + FILE *log_fp; + + if (size_kb == 0) { + log_fp = fopen(log_path, "w"); + if (log_fp == NULL) { + perror("file open error\n"); + } else { + fclose(log_fp); + } + } + + sync(); +} + + diff --git a/src/common/fota_log.h b/src/common/fota_log.h new file mode 100755 index 0000000..828228c --- /dev/null +++ b/src/common/fota_log.h @@ -0,0 +1,78 @@ +/* + * 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_LOG_H__ +#define __FOTA_LOG_H__ + +#include + +/* + * DEBUGGING FEATURE + */ + +extern unsigned int __log_level__; +extern FILE *__log_out_file__; +extern int log_printf(FILE* log_fp, char* format_str, ...); +extern void truncate_log_file(char *log_path, int size_kb); + + +#define LOG_INFO (1<<8) +#define LOG_ENGINE (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_SSENGINE LOG_ENGINE + +//#define DEBUG_STDOUT +#define DEBUG_FILE + +#ifdef DEBUG_STDOUT +#define LOGE(s, args...) printf("UA/ERROR(%s) " s, __func__, ##args) // Error log +#define LOGL(mask, s, args...) do{if((mask) & __log_level__) printf("UA/(%s): " s,__func__, ##args);}while(0) +#define LOG(s, args...) LOGL(LOG_DEBUG, s, ##args) + +#elif defined(DEBUG_FILE) +#define LOGE(s, args...) (void)log_printf(__log_out_file__, "UA/ERROR(%s) " s, __func__, ##args) +#define LOGL(mask, s, args...) do{if((mask) & __log_level__) (void)log_printf(__log_out_file__, "UA/(%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("UA/ERROR(%s) " s, __func__, ##args);\ + (void)log_printf(__log_out_file__, "UA/ERROR(%s) " s, __func__, ##args);\ + }while(0) +#define LOGL(mask, s, args...) do{ \ + if((mask) & __log_level__){\ + printf("UA/(%s): " s ,__func__, ##args);\ + (void)log_printf(__log_out_file__, "UA/(%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_LOG_H__ */ + diff --git a/src/common/fota_tar.h b/src/common/fota_tar.h new file mode 100755 index 0000000..d82df1f --- /dev/null +++ b/src/common/fota_tar.h @@ -0,0 +1,29 @@ +/* + * 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_TAR_H_ +#define _FOTA_TAR_H_ + + int tar_get_item_offset(char* tar, char* item); + + int tar_get_item_size(char* tar, char* item); + + int tar_get_cfg_data(char* tar, char* item, char *buf, int buflen); + + int tar_get_folder_size(char* tar, char* item); +#endif /* _FOTA_TAR_H_ */ diff --git a/src/common/fota_util.c b/src/common/fota_util.c new file mode 100755 index 0000000..b5a6a3d --- /dev/null +++ b/src/common/fota_util.c @@ -0,0 +1,65 @@ +/* + * 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 + +int s_fd_stdin = -1; +int s_fd_stdout = -1; +int s_fd_stderr = -1; + +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; + } +} + +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); +} + +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/src/common/fota_util.h b/src/common/fota_util.h new file mode 100755 index 0000000..932247c --- /dev/null +++ b/src/common/fota_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_UTIL_H_ +#define _FOTA_UTIL_H_ + +extern void _init_stdio(void); +extern void _exit_stdio(void); + +#endif /* _FOTA_UTIL_H_ */ + diff --git a/src/common/mmc_io.c b/src/common/mmc_io.c new file mode 100755 index 0000000..2ddbda9 --- /dev/null +++ b/src/common/mmc_io.c @@ -0,0 +1,201 @@ +/* + * 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. + */ + +#define _LARGEFILE64_SOURCE + +/*----------------------------------------------------------------------------- + include files + ----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +#include "fota_common.h" +#include "mmc_io.h" + +/*----------------------------------------------------------------------------- + definitions + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + type definitions + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + enum definitions + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + variables + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + mmc_dev_open + ----------------------------------------------------------------------------*/ +int mmc_dev_open(char *dev_name, int flag) +{ + int fd; + + fd = open(dev_name, flag); + if (fd < 0) { + LOG("[%s] open() fail ...\n", __FUNCTION__); + return -1; + } + + return fd; +} + +/*----------------------------------------------------------------------------- + mmc_dev_close + ----------------------------------------------------------------------------*/ +int mmc_dev_close(int dev_fd) +{ + int ret; + + ret = close(dev_fd); + if (ret < 0) { + LOG("[%s] close() fail ...\n", __FUNCTION__); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------- + mmc_dev_sector_read + + - offset: sector unit + ----------------------------------------------------------------------------*/ +int mmc_dev_sector_seek(int dev_fd, int sector_offset) +{ + loff_t start_offset; + loff_t ret; + + start_offset = (loff_t) sector_offset *SECTOR_SIZE; + ret = lseek64(dev_fd, start_offset, SEEK_SET); + if (ret < 0) { + LOG("[%s] lseek64() fail ...\n", __FUNCTION__); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------- + mmc_dev_sector_read + + - start : start sector number + - count : number of sectors to read + - buf size should not less than count * SECTOR_SIZE + ----------------------------------------------------------------------------*/ +int mmc_dev_sector_read(int dev_fd, int start, int count, void *buf) +{ + loff_t start_offset; + ssize_t byte_to_read; + ssize_t byte_read; + int ret; + + start_offset = (loff_t) start *SECTOR_SIZE; + ret = lseek64(dev_fd, start_offset, SEEK_SET); + if (ret < 0) { + LOG("[%s] lseek64() fail ...\n", __FUNCTION__); + return -1; + } + + byte_to_read = count * SECTOR_SIZE; + byte_read = read(dev_fd, buf, byte_to_read); + if (byte_read < byte_to_read) { + LOG("[%s] read() fail ...\n", __FUNCTION__); + return -1; + } + + return byte_read; +} + +/*----------------------------------------------------------------------------- + mmc_dev_sector_write + + - start : start sector number + - count : number of sectors to write + - buf size should not less than count * SECTOR_SIZE + ----------------------------------------------------------------------------*/ +int mmc_dev_sector_write(int dev_fd, int start, int count, void *buf) +{ + loff_t start_offset; + ssize_t byte_to_write; + ssize_t byte_written; + int ret; + + start_offset = start * SECTOR_SIZE; + ret = lseek64(dev_fd, start_offset, SEEK_SET); + if (ret < 0) { + LOG("[%s] lseek64() fail ...\n", __FUNCTION__); + return -1; + } + + byte_to_write = count * SECTOR_SIZE; + byte_written = write(dev_fd, buf, byte_to_write); + if (byte_written < byte_to_write) { + LOG("[%s] write() fail ...\n", __FUNCTION__); + return -1; + } + + return byte_written; +} + +/*----------------------------------------------------------------------------- + mmc_dev_sector_read_current + + - same as mmc_dev_sector_read() but not assign start offset. + ----------------------------------------------------------------------------*/ +int mmc_dev_sector_read_current(int dev_fd, int count, void *buf) +{ + ssize_t byte_to_read; + ssize_t byte_read; + + byte_to_read = count * SECTOR_SIZE; + byte_read = read(dev_fd, buf, byte_to_read); + if (byte_read < byte_to_read) { + LOG("[%s] read() fail ...\n", __FUNCTION__); + return -1; + } + + return byte_read; +} + +/*----------------------------------------------------------------------------- + mmc_dev_sector_write_current + + - same as mmc_dev_sector_write() but not assign start offset. + ----------------------------------------------------------------------------*/ +int mmc_dev_sector_write_current(int dev_fd, int count, void *buf) +{ + ssize_t byte_to_write; + ssize_t byte_written; + + byte_to_write = count * SECTOR_SIZE; + byte_written = write(dev_fd, buf, byte_to_write); + if (byte_written < byte_to_write) { + LOG("[%s] read() fail ...\n", __FUNCTION__); + return -1; + } + + return byte_written; +} diff --git a/src/common/mmc_io.h b/src/common/mmc_io.h new file mode 100755 index 0000000..8d37206 --- /dev/null +++ b/src/common/mmc_io.h @@ -0,0 +1,52 @@ +/* + * 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 __MMC_IO_H__ +#define __MMC_IO_H__ +/*----------------------------------------------------------------------------- + include files + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + definitions + ----------------------------------------------------------------------------*/ +#define SECTOR_SIZE 512 +#define SECTOR_SIZE_SHIFT 9 + +/*----------------------------------------------------------------------------- + type definitions + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + enum definitions + ----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + function declaration + ----------------------------------------------------------------------------*/ +extern int mmc_dev_open(char* dev_name, int flag); +extern int mmc_dev_close(int dev_fd); +extern int mmc_dev_sector_seek(int dev_fd, int sector_offset); +extern int mmc_dev_sector_read(int dev_fd, int start, int count, void* buf); +extern int mmc_dev_sector_write(int dev_fd, int start, int count, void* buf); +extern int mmc_dev_sector_read_current(int dev_fd, int count, void* buf); +extern int mmc_dev_sector_write_current(int dev_fd, int count, void* buf); + + + +#endif /* __MMC_IO_H__ */ diff --git a/src/rpi3/ua.c b/src/rpi3/ua.c new file mode 100644 index 0000000..efbc570 --- /dev/null +++ b/src/rpi3/ua.c @@ -0,0 +1,1676 @@ +/* + * 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" +#include "SS_UPI.h" + +#define MAX_CFG_LEN 4096 + +#define RAMDISK_PATH "/opt/usr/data/fota" + +#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] = { + { "KERNEL", "boot.img/", "", 0 }, + { "ROOTFS", "rootfs.img/", "", 0 }, + { "SYSDATA", "system-data.img/", "", 0 }, + { "USER", "user.img/", "", 0 }, + { "MODULE", "modules.img/", "", 0 }, +}; + +static ua_update_cfg_t def_update_cfg[UA_PARTI_MAX] = { + { DELTA_FS, UA_KERNEL, 0, 0 }, + { DELTA_FS, UA_ROOTFS, 0, 0 }, + { DELTA_FS, UA_SYSDATA, 0, 0 }, + { DELTA_FS, UA_USER, 0, 0 }, + { DELTA_FS, UA_MODULE, 0, 0 }, +}; + +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 }, + { 0, 0, 0, 0, 0, 0, NULL, NULL }, + { 0, 0, 0, 0, 0, 0, NULL, NULL }, +}; + +static int g_verify_error[] = { + [UA_KERNEL] = UPI_KERNEL_VERIFY_ERROR, + [UA_ROOTFS] = UPI_ROOTFS_VERIFY_ERROR, + [UA_SYSDATA] = UPI_SYSDATA_VERIFY_ERROR, + [UA_USER] = UPI_USER_VERIFY_ERROR, + [UA_MODULE] = UPI_MODULE_VERIFY_ERROR, +}; + +static int g_update_error[] = { + [UA_KERNEL] = UPI_KERNEL_UPDATE_ERROR, + [UA_ROOTFS] = UPI_ROOTFS_UPDATE_ERROR, + [UA_SYSDATA] = UPI_SYSDATA_UPDATE_ERROR, + [UA_USER] = UPI_USER_UPDATE_ERROR, + [UA_MODULE] = UPI_MODULE_UPDATE_ERROR, +}; + +static int s_part_num = 0; + +static int s_initrd_version = 1; +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); +/*----------------------------------------------------------------------------- + _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 + ----------------------------------------------------------------------------*/ +void fota_gui_update_progress(int percent) +{ + int ret = 0; + char cmd[1024]; + static int s_percent = -1; + + if (percent > s_percent) { + s_percent = percent; + } else { + return; + } + 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 + ----------------------------------------------------------------------------*/ +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_part_info_t *ua_part_info, ua_update_data_t *ua_update_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; + + 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; + 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){ + //commenting for now as FIXNV2 verification fails as nvitem changes after boot in device + //should use skip_verify for such cases + 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_part_info, ua_update_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; + + 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) { + 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; + + 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; +} + +/*----------------------------------------------------------------------------- + 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]; + 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; +} +//RAMDISK.delta for recovery FS. +#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; + if (ua_update_data->ua_delta_path != NULL && ua_dataSS.update_data->ua_temp_path) { + snprintf(ua_dataSS.update_data->ua_temp_path, MAX_FILE_PATH, "%s/%s", RAMDISK_PATH, 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]; + + snprintf(num_str, sizeof(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); + snprintf(ts, sizeof(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(); + + /* 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, DELTA_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]; + + snprintf(log_file, sizeof(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 */ + case E_SS_IMGBADDELTA: + case E_SS_FSBADDELTA: + 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: + case E_SS_MALLOC_ERROR: + LOG("The update fails because there isn't sufficient memory to update the device."); + break; + case E_SS_FSSRCBACKUPFAILED: + case E_SS_IMGSRCBACKUPFAILED: + case E_SS_IMGRECOVERYWRITEFAILED: + case E_SS_IMGFLASHWRITEFAIL: + case E_SS_WRITE_ERROR: + case E_SS_FSFAILEDTOBACKUPPATCHINFO: + case E_SS_FSBADATTRIBUTES: + LOG("The update failed because writing data to the device was unsuccessful."); + break; + case E_SS_FSSRCCURRUPTED: + case E_SS_IMGSRCCURRUPTED: + case E_SS_IMGSHA_MISMATCH: + case E_SS_FSSHA_MISMATCH: + case E_SS_FSFAILEDTOPARSEDELTACNT: + case E_SS_FSFAILEDTOOPENPATCHINFO: + case E_SS_FSFAILEDTOPARSEDELTAINFO: + LOG("The update failed because data was corrupted during update of 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; + } + + snprintf(return_char, sizeof(return_char), "%x", cause); + fwrite(return_char, strlen(return_char), 1, result_fp); + fclose(result_fp); + + if (s_initrd_version == 0) { + if ((result_fp = fopen("/opt/data/fota/cause", "w")) == NULL) { + LOG("cause file open fail\n"); + return; + } + + snprintf(return_char, sizeof(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; + } + + snprintf(return_char, sizeof(return_char), "%x", result); + fwrite(return_char, strlen(return_char), 1, result_fp); + fclose(result_fp); + + if (s_initrd_version == 0) { + if ((result_fp = fopen("/opt/data/fota/result", "w")) == NULL) { + LOG("result file open fail\n"); + return; + } + + snprintf(return_char, sizeof(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; + int ret; + + 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); + snprintf(s_update_data[i].ua_delta_path, MAX_FILE_PATH, "%s/%s", delta_folder, DEFAULT_DELTA_NAME); + //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); + } + + snprintf(fota_result, sizeof(fota_result), "%s/%s", result_folder, "result"); + snprintf(fota_cause, sizeof(fota_cause), "%s/%s", result_folder, "cause"); + snprintf(fota_status_path, sizeof(fota_status_path), "%s/%s", result_folder, UP_STATUS_FILE); + + if (s_initrd_version == 0) { + ret = mkdir("/opt/data/fota", S_IRUSR | S_IWUSR | S_IXUSR | + S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); + if (ret == 0 || ((ret == -1) && (errno == EEXIST))) { + LOG("mkdir(/opt/data/fota) ok\n"); + } else { + LOG("mkdir(/opt/data/fota) fail\n"); + } + } + + 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_PARTI_START; 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_SS_SUCCESS == SS_GetUPIVersion((unsigned char*)ver_str)) { + LOG("<<<<<<<<< TOTA Update Agent %s >>>>>>>>>>>>\n", ver_str); + } else { + LOG("[SS_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_BOOT_VERIFY_ERROR: + case UPI_SBOOT_VERIFY_ERROR: + 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: + case UPI_DSP_VERIFY_ERROR: + case UPI_WCNMODEM_VERIFY_ERROR: + case UPI_RAMDISK1_VERIFY_ERROR: + case UPI_SYSDATA_VERIFY_ERROR: + case UPI_USER_VERIFY_ERROR: + + case UPI_BOOT_UPDATE_ERROR: + case UPI_SBOOT_UPDATE_ERROR: + 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: + case UPI_DSP_UPDATE_ERROR: + case UPI_WCNMODEM_UPDATE_ERROR: + case UPI_RAMDISK1_UPDATE_ERROR: + case UPI_SYSDATA_UPDATE_ERROR: + case UPI_USER_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(); + unlink(delta_path); + return 0; + default: + LOG("!!! Not expected ret (= %d)\n", ret); + } + + _exit_stdio(); + return -1; +} diff --git a/src/rpi3/ua.h b/src/rpi3/ua.h new file mode 100644 index 0000000..a2870d8 --- /dev/null +++ b/src/rpi3/ua.h @@ -0,0 +1,210 @@ +/* + * 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 BOOT_PATH "/boot" +#define LOG_FILE_PATH "/last_update.log" +#define MAX_FILE_PATH 512 +#define MAX_PART_NAME 32 + +#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_BOOT_VERIFY_ERROR 0xFDC1 +#define UPI_SBOOT_VERIFY_ERROR 0xFDC2 +#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 +#define UPI_DSP_VERIFY_ERROR 0xFDCC +#define UPI_WCNMODEM_VERIFY_ERROR 0xFDCD +#define UPI_RAMDISK1_VERIFY_ERROR 0xFDCE +#define UPI_SYSDATA_VERIFY_ERROR 0xFDCF +#define UPI_USER_VERIFY_ERROR 0xFDD0 + +#define UPI_BOOT_UPDATE_ERROR 0xFDD1 +#define UPI_SBOOT_UPDATE_ERROR 0xFDD2 +#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 +#define UPI_DSP_UPDATE_ERROR 0xFDDC +#define UPI_WCNMODEM_UPDATE_ERROR 0xFDDD +#define UPI_RAMDISK1_UPDATE_ERROR 0xFDDE +#define UPI_SYSDATA_UPDATE_ERROR 0xFDDF +#define UPI_USER_UPDATE_ERROR 0xFDE0 + +#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_KERNEL = 0, + UA_ROOTFS, + UA_SYSDATA, + UA_USER, + UA_MODULE, + UA_PARTI_MAX +} UA_PART_IDX; +#define UA_PARTI_START 0 + +#define UP_STATUS_FILE "UP.STATUS" +typedef enum { + UP_START_NONE = 0, + UP_START_KERNEL, + UP_START_ROOTFS, + UP_START_SYSDATA, + UP_START_USER, + UP_START_MODULE, + 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 diff --git a/ss_engine/SS_FSUpdate.c b/ss_engine/SS_FSUpdate.c new file mode 100755 index 0000000..cb03e4c --- /dev/null +++ b/ss_engine/SS_FSUpdate.c @@ -0,0 +1,1244 @@ +/* + * 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. + */ + +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "SS_Common.h" + +#include "fota_common.h" +#include "ua.h" + +/************************************************************ + * common functions + ************************************************************/ +void SS_create_dir(char *pathname, int mode) +{ + char *p; + int r; + + /* Strip trailing '/' */ + if (pathname[strlen(pathname) - 1] == '/') + pathname[strlen(pathname) - 1] = '\0'; + + /* Try creating the directory. */ + r = mkdir(pathname, mode); + + if (r != 0) { + /* On failure, try creating parent directory. */ + p = strrchr(pathname, '/'); + if (p != NULL) { + *p = '\0'; + SS_create_dir(pathname, 0755); + *p = '/'; + r = mkdir(pathname, mode); + } + } + if (r != 0) { + if (r != EEXIST && r != -1) + LOG("Could not create directory [%s] Error[%d]\n", pathname, r); + } +} + + +void SS_unicode_to_char(const char *src, char *dest) +{ + if (src == NULL) { + return; + } + + strcpy(dest, src); +} + +void SS_char_to_unicode(const char *src, char *dest) +{ + if (src == NULL) { + return; + } + + strcpy(dest, src); +} + +long SS_recursive_folder_creater(const char *path, const mode_t mode) +{ + int ret = 0; + int offset = 0; + char temppath[MAX_PATH] = { '\0' }; + + LOGL(LOG_SSENGINE, "path: %s\n", path); + + if ((offset = strlen(path)) == 0) // For counting back until the '/' delimiter + return -1; //if from some reason we got to the end return error!!!. + + while (path[offset] != '/') // get to the next '/' place + offset--; + + strncpy(temppath, path, offset); // copy one depth below till and without the char '/' + LOGL(LOG_SSENGINE, " temppath: %s\n", temppath); + ret = mkdir(temppath, mode); + LOGL(LOG_SSENGINE, " mkdir result: %d errno: %d\n", ret, errno); + + if (ret == 0 || ((ret == -1) && (errno == EEXIST))) { + return 0; //meaning the depth creation is success. + } else if ((ret == -1) && (errno == ENOENT)) { + if ((ret = SS_recursive_folder_creater(temppath, mode)) == 0); + ret = mkdir(temppath, mode); + return ret; + } else { + return -1; + } +} + +long +SS_CopyFile(void *pbUserData, + const char *strFromPath, const char *strToPath) +{ + int fd1, fd2; + int readCount = 0, writeCount = 0; + char buf[1 << 15]; // copy 32KB wise + int ret = 0; + + char path1[MAX_PATH] = { '\0' }; + char path2[MAX_PATH] = { '\0' }; + + if (!strFromPath || !strToPath) { + LOGE("NULL file name find. Abort.\n"); + return -1; + } + + SS_unicode_to_char((const char *)strFromPath, (char *)path1); + SS_unicode_to_char((const char *)strToPath, (char *)path2); + + //LOGL(LOG_SSENGINE, "%s -> %s \n", path1, path2); + + fd1 = open(path1, O_RDONLY); + if (fd1 < 0) + return E_SS_OPENFILE_ONLYR; + ret = SS_OpenFile(pbUserData, strToPath, ONLY_W, (long *)&fd2); + if (ret != S_SS_SUCCESS || fd2 < 0) { + close(fd1); + LOGE(" SS_OpenFile fail leaved path1:%s | path2:%s\n", path1, path1); + return E_SS_WRITE_ERROR; + } + + while ((readCount = read(fd1, buf, sizeof(buf))) > 0) { + writeCount = write(fd2, buf, readCount); + if (writeCount != readCount) { + LOGE(" read %d, but write %d, abort.\n", readCount, + writeCount); + ret = E_SS_WRITE_ERROR; + break; + } + } + + close(fd1); + fsync(fd2); + close(fd2); + //LOGL(LOG_INFO, " leaved path1:%s | path2:%s\n", path1, path2); + + return ret; +} + +long SS_DeleteFile(void *pbUserData, const char *strPath) +{ + char path[MAX_PATH] = { '\0' }; + int ret = 0; + + SS_unicode_to_char((const char *)strPath, (char *)path); + //LOGL(LOG_SSENGINE, "%s\n", path); + ret = unlink(path); + if (ret == 0) + return S_SS_SUCCESS; + + LOGE("failed to delete path [%s] unlink value: %d, errno: %d\n", path, ret, errno); + if (ret < 0 && errno == ENOENT) + return S_SS_SUCCESS; + return E_SS_DELETEFILE; +} + +int SS_unlink_cbf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) +{ + int rv = remove(fpath);//returns zero on success and -1 on failure + + if (rv){ + perror(fpath); + LOGE("path : %s, remove value: %d, errno: %d\n",fpath, rv, errno); + } + return rv; +} +long SS_DeleteFolder(void *pbUserData, const char *strPath) +{ + //runs till either tree is exhausted or when unlink_cbf returns non zero value. + return ((long)nftw(strPath, SS_unlink_cbf, 64, FTW_DEPTH | FTW_PHYS) == 0) ? S_SS_SUCCESS : E_SS_FAILURE; + +} + +long SS_DeleteFolderEmpty(void *pbUserData, const char *strPath) +{ + + int ret = 0; + char path[MAX_PATH] = { '\0' }; + + SS_unicode_to_char((const char *)strPath, (char *)path); + //LOGL(LOG_REDBEND, "%s\n", path); + ret = rmdir(path); + if ((ret == 0) + || ((ret < 0) && ((errno == ENOENT) || (errno == ENOTEMPTY)))) { + LOGL(LOG_SSENGINE, "rmdir value: %d, errno: %d\n", ret, errno); + return S_SS_SUCCESS; + } + LOGE("rmdir value: %d, errno: %d\n", ret, errno); + return E_SS_FAILURE; +} + +long SS_CreateFolder(void *pbUserData, const char *strPath) +{ + mode_t mode = 0; + int ret = 0; + char path[MAX_PATH] = { '\0' }; + + SS_unicode_to_char((const char *)strPath, (char *)path); + mode = S_IRUSR /*Read by owner */ | + S_IWUSR /*Write by owner */ | + S_IXUSR /*Execute by owner */ | + S_IRGRP /*Read by group */ | + S_IWGRP /*Write by group */ | + S_IXGRP /*Execute by group */ | + S_IROTH /*Read by others */ | + S_IWOTH /*Write by others */ | + S_IXOTH /*Execute by others */ ; + + LOGL(LOG_SSENGINE, "%s, mode:0x%x\n", path, mode); + + ret = mkdir(path, mode); + + if (ret == 0 || ((ret == -1) && (errno == EEXIST))) { + return S_SS_SUCCESS; + } else if ((ret == -1) && (errno == ENOENT)) //maybe multi directory problem + { + //do//Recursive Function + //{ + ret = SS_recursive_folder_creater(path, mode); + if (ret == S_SS_SUCCESS) { + ret = mkdir(path, mode); //After creating all the depth Directories we try to create the Original one again. + if (ret == 0) + return S_SS_SUCCESS; + else + return E_SS_FAILURE; + } else { + return E_SS_FAILURE; + } + //} + //while(ret != 0); + + } else { + return E_SS_FAILURE; + } +} + +mode_t SS_get_mode(E_RW_TYPE wFlag) +{ + switch (wFlag) { + case ONLY_R: + //LOGL(LOG_SSENGINE, " RDONLY \n"); + return O_RDONLY; + case ONLY_W: + //LOGL(LOG_SSENGINE, " WRONLY \n"); + return O_WRONLY | O_CREAT; + case BOTH_RW: + //LOGL(LOG_SSENGINE, " RDWR \n"); + return O_RDWR | O_CREAT; + default: + //LOGL(LOG_SSENGINE, " Unknown \n"); + return 0; + } +} + +long +SS_OpenFile(void *pbUserData, + const char *strPath, E_RW_TYPE wFlag, long *pwHandle) +{ + mode_t mode; + char path[MAX_PATH] = { '\0' }; + + SS_unicode_to_char((const char *)strPath, (char *)path); + + mode = SS_get_mode(wFlag); + //LOGL(LOG_SSENGINE, "Path:%s wFlag:%d Mode:%d\n", path, wFlag, mode); + + if(mode & O_CREAT) { + //LOGL(LOG_SSENGINE, " open() S_IRWXU\n"); + *pwHandle = open(path, mode, S_IRWXU); + } else { + //LOGL(LOG_SSENGINE, " open() %d\n", mode); + *pwHandle = open(path, mode); + } + if (*pwHandle == -1) { + *pwHandle = 0; + LOGE(" First open() with error %d\n", errno); + if (wFlag == ONLY_R) { + LOGE(" error in ONLY_R return E_SS_OPENFILE_ONLYR\n"); + return E_SS_OPENFILE_ONLYR; + } + + //if we need to open the file for write or read/write then we need to create the folder (in case it does not exist) + if ((wFlag != ONLY_R) && (errno == ENOENT)) { + char dir[MAX_PATH] = { '\0' }; + char dirShort[MAX_PATH] = { '\0' }; + int i = 0; + //copy the full file path to directory path variable + while (path[i] != '\0') { + dir[i] = path[i]; + i++; + } + LOGL(LOG_SSENGINE, " copy dir[]=%s\n", dir); + //search for the last '/' char + while (dir[i--] != '/') ; + dir[i + 1] = '\0'; + + SS_char_to_unicode((const char *)dir, + (char *)dirShort); + + if (SS_CreateFolder(pbUserData, dirShort)) { + LOGE(" Fail create folder, Leave SS_OpenFile\n"); + return E_SS_OPENFILE_WRITE; + } + + *pwHandle = open(path, mode); + if (*pwHandle == -1) { + *pwHandle = 0; + LOGE(" After successful creating folder, fail open() with error %d\n", errno); + return E_SS_OPENFILE_WRITE; + } + } else { + LOG(" fail open() *pwHandle:%ld\n", *pwHandle); + return E_SS_OPENFILE_WRITE; + } + } + + //LOGL(LOG_SSENGINE, " Successful open() *pwHandle:%ld\n", *pwHandle); + + return S_SS_SUCCESS; +} + +long SS_ResizeFile(void *pbUserData, long wHandle, SS_UINT32 dwSize) +{ + int ret = 0; + + LOGL(LOG_SSENGINE, "handle %ld, dwSize %d\n", wHandle, errno); + + if (wHandle) + ret = ftruncate(wHandle, dwSize); + else + ret = E_SS_RESIZEFILE; + + LOGL(LOG_SSENGINE, "ret %d handle %ld %d\n", ret, wHandle, errno); + + return ret; +} + +long SS_CloseFile(void *pbUserData, long wHandle) +{ + int ret = 0; + LOGL(LOG_SSENGINE, "wHandle = %ld\n", wHandle); + + if (wHandle) { + ret = fsync(wHandle); + if (ret < 0) { + LOG(" fsync Failed with return value: %d\n", ret); + return E_SS_WRITE_ERROR; + } + LOG(" fsync after write: %d\n", ret); + ret = close(wHandle); + } + + if (ret == 0) + return S_SS_SUCCESS; + + return E_SS_CLOSEFILE_ERROR; +} + +long +SS_WriteFile(void *pbUserData, + long wHandle, + SS_UINT32 dwPosition, + unsigned char *pbBuffer, SS_UINT32 dwSize) +{ + int ret = 0; + + LOGL(LOG_SSENGINE, "Handle:%ld , Pos:%u , Size: %u\n", wHandle, + dwPosition, dwSize); + + ret = lseek(wHandle, dwPosition, SEEK_SET); + if (ret < 0) { + LOGE(" lseek failed with return value: %d\n", ret); + LOGL(LOG_SSENGINE, "lseek errno=%d\n", errno); + return E_SS_WRITE_ERROR; + } + + ret = write(wHandle, pbBuffer, dwSize); + if (ret < 0 || ret != dwSize) { + LOGE(" Failed with return value: %d\n", ret); + LOGL(LOG_SSENGINE, "ret=%d, dwSize=%u write errno=%d\n", + ret, (unsigned int)dwSize, errno); + return E_SS_WRITE_ERROR; + } + LOGL(LOG_SSENGINE, "leave Bytes Write: %d\n", ret); + + return S_SS_SUCCESS; +} + +long SS_MoveFile(void *pbUserData, const char *strFromPath, + const char *strToPath) +{ + int ret = 0; + struct stat sbuf; + char path1[MAX_PATH] = { '\0' }; + char path2[MAX_PATH] = { '\0' }; + + if (!strFromPath || !strToPath) { + return -1; //should never happen + } + + SS_unicode_to_char(strFromPath, (char *)path1); + SS_unicode_to_char(strToPath, (char *)path2); + + LOGL(LOG_INFO, "entered path1:%s | path2:%s\n", path1, path2); + ret = stat(path1, &sbuf); + if (ret < 0) { + LOGE("stat failed with return value: %d errno: %d\n", ret, errno); + return E_SS_FAILURE; + } + ret = rename(path1, path2); + if (ret < 0) { + LOGL(LOG_INFO, "rename fail with code [%d], try to create dir if errno is 2\n", errno); + if (errno == 2) { + char * file_name = strrchr(path2,'/'); + *file_name = '\0'; + SS_create_dir(path2,0755); + *file_name = '/'; + ret = rename(path1, path2); + if (ret < 0) { + LOGE("Move failed, error code [%d]",errno); + return E_SS_WRITE_ERROR; + } + } + else if (errno == 18){ //EXDEV 18 /* Cross-device link */ + //Moving file across partitions if mount point is different (Extremely rare) + ret = (int)SS_CopyFile(NULL, path1, path2); + if (ret != S_SS_SUCCESS) { + LOGE("failed to copy file [%s] result [%d]\n", path1, ret); + return E_SS_WRITE_ERROR; + } + ret = unlink(path1); + if (ret != 0) { + LOGE("failed to unlink [%s] code [%d]\n", path1, errno); + return E_SS_WRITE_ERROR; + } + } + else{ + LOGE("Move failed, error code [%d]",errno); + return E_SS_WRITE_ERROR; + } + } + LOGL(LOG_INFO, "leaved path1:%s | path2:%s\n", path1, path2); + return S_SS_SUCCESS; +} +long SS_SyncFile(void *pbUserData, long wHandle) +{ + return (-1 == fsync(wHandle)) ? E_SS_FAILURE : S_SS_SUCCESS; +} + +long +SS_ReadFile(void *pbUserData, + long wHandle, + SS_UINT32 dwPosition, + unsigned char *pbBuffer, SS_UINT32 dwSize) +{ + int ret = 0; + +#if 0 + LOG(" %s: Handle:%ld , Pos:%u , Size: %u", __func__, wHandle, + dwPosition, dwSize); +#endif + ret = lseek(wHandle, dwPosition, SEEK_SET); + if (ret < 0) { + LOGE("Handle:%ld , Pos:%u , Size: %u", wHandle, dwPosition, + dwSize); + LOGE("lseek failed with return value: %d\n", ret); + return E_SS_READ_ERROR; + } + ret = read(wHandle, pbBuffer, dwSize); + if (ret < 0) { + LOGE("Handle:%ld , Pos:%u , Size: %u", wHandle, dwPosition, + dwSize); + LOGE("read failed with return value: %d\n", ret); + return E_SS_READ_ERROR; + } + + if (ret != dwSize && ((ret + dwPosition) != (unsigned long)SS_GetFileSize(pbUserData, wHandle))) + return E_SS_READ_ERROR; + +#if 0 + LOGL(LOG_DEBUG, "Bytes Read: %d\n", ret); +#endif + return S_SS_SUCCESS; +} + +long SS_GetFileSize(void *pbUserData, long wHandle) +{ + int ret = 0; + + + ret = lseek(wHandle, 0, SEEK_END); + + if (ret == -1) { + LOGE(" lseek errno: %d\n", errno); + return E_SS_READFILE_SIZE; + } + LOGL(LOG_SSENGINE, "handle=%d Returning Size = %ld(0x%x)\n", + (int)wHandle, (long int)ret, ret); + + return ret; +} + +long SS_Unlink(void *pbUserData, char *pLinkName) +{ + int ret = 0; + char path[MAX_PATH] = { '\0' }; + //enumFileType fileType = FT_REGULAR_FILE; + + + SS_unicode_to_char((const char *)pLinkName, (char *)path); + + ret = unlink(path); + if (ret < 0 && errno != ENOENT) { + LOGE("unlink failed with return value: %d\n", ret); + return E_SS_FAILURE; + } + LOGL(LOG_SSENGINE, "unlink with return value: %d\n", ret); + + return S_SS_SUCCESS; +} + +long +SS_VerifyLinkReference(void *pbUserData, + char *pLinkName, + char *pReferenceFileName) +{ + int ret = 0; + char path[MAX_PATH] = { '\0' }; + char linkedpath[MAX_PATH] = { '\0' }; + char refpath[MAX_PATH] = { '\0' }; + + + SS_unicode_to_char((const char *)pLinkName, (char *)path); + SS_unicode_to_char((const char *)pReferenceFileName, (char *)refpath); + + ret = readlink(path, linkedpath, MAX_PATH); + if (ret < 0) { + LOGE("readlink failed with return value: %d\n", ret); + return E_SS_FAILURE; + } + + if ((memcmp(&linkedpath, &refpath, ret)) != 0) { + LOGE("not same linked path\n"); + return E_SS_FAILURE; + } + LOGL(LOG_SSENGINE, "same linked path\n"); + + return S_SS_SUCCESS; +} + +long +SS_Link(void *pbUserData, char *pLinkName, char *pReferenceFileName) +{ + int ret = 0; + char sympath[MAX_PATH] = { '\0' }; + char refpath[MAX_PATH] = { '\0' }; + //enumFileType fileType = FT_SYMBOLIC_LINK; + struct stat sbuf; + + SS_unicode_to_char((const char *)pLinkName, (char *)sympath); + SS_unicode_to_char((const char *)pReferenceFileName, (char *)refpath); + + ret = symlink(refpath, sympath); + if (ret != 0) { + LOGE(" symlink failed with return value: %d, errno: %d\n", ret,errno); + + if (errno == EEXIST) { + ret = lstat(sympath, &sbuf); + LOGL(LOG_SSENGINE, "symlink LSTAT with return value: %d\n", ret); + if (ret >= 0) { + if (S_ISREG(sbuf.st_mode)) { + LOGL(LOG_SSENGINE, " stat->st_mode = regular file, To be deleted and create a LINK \n"); + SS_DeleteFile(pbUserData,sympath); + SS_Link(pbUserData, pLinkName, pReferenceFileName); + } + } + if (SS_VerifyLinkReference(pbUserData, pLinkName + , pReferenceFileName) == S_SS_SUCCESS) { + return S_SS_SUCCESS; + } + else + return E_SS_FAILURE; + } + else if(errno == ENOENT )//to handle cases where new symlink points to a new symlink yet to be created + return errno; + else + return E_SS_FAILURE; + } + //LOGL(LOG_SSENGINE, "symlink with return value: %d\n", ret); + + return S_SS_SUCCESS; +} + +long SS_GetFileType(void *pbUserData, + char *pLinkName, enumFileType * fileType) +{ + int ret = 0; + char path[MAX_PATH] = { '\0' }; + struct stat sbuf; + + //LOGL(LOG_SSENGINE, "\n"); + SS_unicode_to_char((const char *)pLinkName, (char *)path); + + ret = lstat(path, &sbuf); + if (ret < 0) { + ret = stat(path, &sbuf); + if (ret < 0) { + LOGE("stat failed with return value: %d errno: %d\n", + ret, errno); + *fileType = FT_MISSING; + return S_SS_SUCCESS; + } + } + //LOGL(LOG_SSENGINE, " sbuf.st_mode: %d\n", sbuf.st_mode); + //LOGL(LOG_SSENGINE, " S_ISREG(sbuf.st_mode): %d\n", S_ISREG(sbuf.st_mode)); + //LOGL(LOG_SSENGINE, " S_ISLNK(sbuf.st_mode): %d\n", S_ISLNK(sbuf.st_mode)); + + if (S_ISLNK(sbuf.st_mode)) { + //LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n"); + *fileType = FT_SYMBOLIC_LINK; + return S_SS_SUCCESS; + } + + if (S_ISREG(sbuf.st_mode)) { + //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n"); + *fileType = FT_REGULAR_FILE; + return S_SS_SUCCESS; + } + + if (S_ISDIR(sbuf.st_mode)) { + //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n"); + *fileType = FT_FOLDER; + return S_SS_SUCCESS; + } + LOGE("failed to lstat, err : %d\n", ret); + return E_SS_FAILURE; +} + +char SS_a2ch(int value) +{ + char set_value = 0; + + LOGL(LOG_SSENGINE, "%d\n", value); + + switch (value) { + case '1': + set_value = 0x01; + break; + case '2': + set_value = 0x02; + break; + case '3': + set_value = 0x03; + break; + case '4': + set_value = 0x04; + break; + case '5': + set_value = 0x05; + break; + case '6': + set_value = 0x06; + break; + case '7': + set_value = 0x07; + break; + case '8': + set_value = 0x08; + break; + case '9': + set_value = 0x09; + break; + case '0': + set_value = 0x00; + break; + default: + LOGL(LOG_SSENGINE, "Wrong attribute value: %d\n", value); + + } + LOGL(LOG_SSENGINE, "SS_a2ch : %c\n", set_value); + + return set_value; +} + +void SS_chtoa(int value, char *str) +{ + char *pStr = str; + + LOGL(LOG_SSENGINE, "%d\n", value); + + switch (value) { + case 1: + *pStr = '1'; + break; + case 2: + *pStr = '2'; + break; + case 3: + *pStr = '3'; + break; + case 4: + *pStr = '4'; + break; + case 5: + *pStr = '5'; + break; + case 6: + *pStr = '6'; + break; + case 7: + *pStr = '7'; + break; + case 8: + *pStr = '8'; + break; + case 9: + *pStr = '9'; + break; + case 0: + *pStr = '0'; + break; + default: + LOGL(LOG_SSENGINE, "Wrong attribute value: %d\n", value); + } +} + +/*! + ******************************************************************************* + * Set file attributes.

+ * + * The file attributes token (\a ui8pAttribs) is defined at generation time. + * If attributes are not defined explicitly, they are given the following, + * OS-dependent values: + * \li Windows: _redbend_ro_ for R/O files, _redbend_rw_ for R/W files + * \li Linux: _redbend_oooooo:xxxx:yyyy indicating the file mode, uid, and gid + * (uid and gid use capitalized hex digits as required) + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param ui16pFilePath File path + * \param ui32AttribSize Size of \a ui8pAttribs + * \param ui8pAttribs Attributes to set + * + * \return S_SS_SUCCESS on success or < 0 on error + ******************************************************************************* + */ + +long SS_SetFileAttributes(const char *ui16pFilePath, + const SS_UINT32 ui32AttribSize, + const unsigned char *ui8pAttribs) +{ + static char tmpAttribs[512]; + static char tmpSmackAttribs[512]; + char *tp; + char *endstr; + char *smack_value, *psmack; + uid_t setUserID = 0; + gid_t setGroupID = 0; + mode_t setFileMode = 0; + const char attrDelim[2] = ":"; + + char setFilePath[MAX_PATH] = { '\0' }; + struct stat sbuf; + int ret = 0; + char *smack_attr_pos = NULL; +#if defined(FEATURE_SUPPORT_CAPABILITY) + int has_cap = 0; + char cap_raw[100]; + int cap_len; + /*ACL */ + int has_acl = 0; + char acl_raw[256]; + int acl_len; + +#endif + if (NULL == ui16pFilePath) { + LOGL(LOG_SSENGINE, "ui16pFilePath NULL [error]\n"); + return E_SS_BAD_PARAMS; + } else if (NULL == ui8pAttribs) { + LOGL(LOG_SSENGINE, "ui8pAttribs NULL [error]\n"); + return E_SS_BAD_PARAMS; + } else if (0 == ui32AttribSize) { + LOGL(LOG_SSENGINE, "ui32AttribSize 0\n"); + return S_SS_SUCCESS; + } + + SS_unicode_to_char((const char *)ui16pFilePath, (char *)setFilePath); + + ret = lstat(setFilePath, &sbuf); + if (ret < 0) { + ret = stat(setFilePath, &sbuf); + if (ret < 0) { + LOGL(LOG_SSENGINE, " stat failed with return value: %d\n", ret); + return E_SS_FAILURE; + } else { + if (S_ISLNK(sbuf.st_mode)) { + LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n"); +// return S_RB_SUCCESS; // sybolic link should be set mode. + } + if (S_ISREG(sbuf.st_mode)) { + LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n"); + } + if (S_ISDIR(sbuf.st_mode)) { + LOGL(LOG_SSENGINE, " stat->st_mode = directory\n"); + } + } + + LOGL(LOG_SSENGINE, "ui16pFilePath = %s\n", setFilePath); + LOGL(LOG_SSENGINE, "ui32AttribSize = %u\n", ui32AttribSize); + LOGL(LOG_SSENGINE, "ui8pAttribs = %s\n", ui8pAttribs); + + } + memset(tmpAttribs, 0x0, sizeof(tmpAttribs)); + memcpy(tmpAttribs, ui8pAttribs, (size_t) ui32AttribSize-1); + smack_attr_pos = tmpAttribs; + tp = strtok(tmpAttribs, attrDelim); + + // Get FileMode + if (tp != NULL) { + smack_attr_pos += strlen(tp); + smack_attr_pos++; + setFileMode = strtol(tp, &endstr, 8); + tp = strtok(NULL, attrDelim); + } + // Get UserID + if (tp != NULL) { + smack_attr_pos += strlen(tp); + smack_attr_pos++; + setUserID = (uid_t) strtol(tp, &endstr, 10); + tp = strtok(NULL, attrDelim); + } + // Get GroupID + if (tp != NULL) { + smack_attr_pos += strlen(tp); + smack_attr_pos++; + setGroupID = (gid_t) strtol(tp, &endstr, 10); + } +#if defined(FEATURE_SUPPORT_CAPABILITY) + // Get Capability + has_cap = 0; + if (*smack_attr_pos != '\0') { + char *cap_mark = "capability=0x"; + int cap_mark_len = strlen(cap_mark); + psmack = strstr(smack_attr_pos, cap_mark); + if(psmack) { + int cap_hex_len; + int i; + char ch1, ch2; + int raw1, raw2; + + tp = strstr(psmack, ":"); + smack_attr_pos = tp + 1; + memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs)); + memcpy(tmpSmackAttribs, psmack+cap_mark_len, + (int)tp - (int)psmack - cap_mark_len); + + // convert hexadecimal into raw data + cap_hex_len = strlen(tmpSmackAttribs); + cap_len = cap_hex_len/2; + memset(cap_raw, 0x00, sizeof(cap_raw)); + for (i=0; i= '0')&&(ch1 <= '9')) raw1 = ch1 - '0'; + else if ((ch1 >= 'a')&&(ch1 <= 'f')) raw1 = ch1 - 'a' + 10; + else if ((ch1 >= 'A')&&(ch1 <= 'F')) raw1 = ch1 - 'A' + 10; + else raw1 = 0; + if ((ch2 >= '0')&&(ch2 <= '9')) raw2 = ch2 - '0'; + else if ((ch2 >= 'a')&&(ch2 <= 'f')) raw2 = ch2 - 'a' + 10; + else if ((ch2 >= 'A')&&(ch2 <= 'F')) raw2 = ch2 - 'A' + 10; + else raw2 = 0; + + cap_raw[i] = raw1*16 + raw2; + } + LOGL(LOG_SSENGINE, "[Cap] %s (cap_len=%d)\n", tmpSmackAttribs, cap_len); + has_cap = 1; + } + + } + // Get ACL + has_acl = 0; + if (*smack_attr_pos != '\0') { + char *acl_mark = "acl_access=0x"; + int acl_mark_len = strlen(acl_mark); + psmack = strstr(smack_attr_pos, acl_mark); + if(psmack) { + int acl_hex_len; + int i; + char ch1, ch2; + int raw1, raw2; + + tp = strstr(psmack, ":"); + smack_attr_pos = tp + 1; + memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs)); + memcpy(tmpSmackAttribs, psmack+acl_mark_len, + (int)tp - (int)psmack - acl_mark_len); + + // convert hexadecimal into raw data + acl_hex_len = strlen(tmpSmackAttribs); + acl_len = acl_hex_len/2; + memset(acl_raw, 0x00, sizeof(acl_raw)); + for (i=0; i= '0')&&(ch1 <= '9')) raw1 = ch1 - '0'; + else if ((ch1 >= 'a')&&(ch1 <= 'f')) raw1 = ch1 - 'a' + 10; + else if ((ch1 >= 'A')&&(ch1 <= 'F')) raw1 = ch1 - 'A' + 10; + else raw1 = 0; + if ((ch2 >= '0')&&(ch2 <= '9')) raw2 = ch2 - '0'; + else if ((ch2 >= 'a')&&(ch2 <= 'f')) raw2 = ch2 - 'a' + 10; + else if ((ch2 >= 'A')&&(ch2 <= 'F')) raw2 = ch2 - 'A' + 10; + else raw2 = 0; + + acl_raw[i] = raw1*16 + raw2; + } + LOG("[ACL] %s (acl_len=%d)\n", tmpSmackAttribs, acl_len); + has_acl = 1; + } + + } + +#endif + // Get Smack value -> Set Smack value + if (*smack_attr_pos != '\0') { + smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_ACCESS); + smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_EXEC); + smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_MMAP); + smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_TRANSMUTE); + + psmack = strstr(smack_attr_pos, "access=\""); + if(psmack) { + memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs)); + memcpy(tmpSmackAttribs, psmack, strlen(psmack)); + smack_value = strtok(tmpSmackAttribs, "\""); + if (smack_value) { + smack_value = strtok(NULL, "\""); + //LOGL(LOG_SSENGINE, "[SMACK_LABEL_ACCESS] smack_value=%s\n", smack_value); + if(smack_value) { + ret = smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_ACCESS); + if (ret < 0) + LOGL(LOG_SSENGINE, "smack_lsetlabel() failed\n"); + } + } + } + psmack = strstr(smack_attr_pos, "execute=\""); + if(psmack) { + memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs)); + memcpy(tmpSmackAttribs, psmack, strlen(psmack)); + smack_value = strtok(tmpSmackAttribs, "\""); + if (smack_value) { + smack_value = strtok(NULL, "\""); + //LOGL(LOG_SSENGINE, "[SMACK_LABEL_EXEC] smack_value=%s\n", smack_value); + if(smack_value) { + ret = smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_EXEC); + if (ret < 0) + LOGL(LOG_SSENGINE, "smack_lsetlabel() failed\n"); + } + } + } + psmack = strstr(smack_attr_pos, "mmap=\""); + if(psmack) { + memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs)); + memcpy(tmpSmackAttribs, psmack, strlen(psmack)); + smack_value = strtok(tmpSmackAttribs, "\""); + if (smack_value) { + smack_value = strtok(NULL, "\""); + //LOGL(LOG_SSENGINE, "[SMACK_LABEL_MMAP] smack_value=%s\n", smack_value); + if(smack_value) { + ret = smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_MMAP); + if (ret < 0) + LOGL(LOG_SSENGINE, "smack_lsetlabel() failed\n"); + } + } + } + psmack = strstr(smack_attr_pos, "transmute=\""); + if(psmack) { + memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs)); + memcpy(tmpSmackAttribs, psmack, strlen(psmack)); + smack_value = strtok(tmpSmackAttribs, "\""); + if (smack_value) { + smack_value = strtok(NULL, "\""); + //LOGL(LOG_SSENGINE, "[SMACK_LABEL_TRANSMUTE] smack_value=%s\n", smack_value); + if(smack_value) { + if (strcasecmp(smack_value, "TRUE")==0) { + ret = smack_lsetlabel(setFilePath, "1", SMACK_LABEL_TRANSMUTE); + } else { + ret = smack_lsetlabel(setFilePath, "0", SMACK_LABEL_TRANSMUTE); + } + if (ret < 0) + LOGL(LOG_SSENGINE, "smack_lsetlabel() failed\n"); + } + } + } + } + + // Set UserID,GroupID + if (lchown(setFilePath, setUserID, setGroupID)) { + // debug start + LOGL(LOG_SSENGINE, "%s chown error\n", __func__); + LOGL(LOG_SSENGINE, "%s setUserID = %d\n", __func__, setUserID); + LOGL(LOG_SSENGINE, "%s setGroupID = %d\n", __func__, setGroupID); + LOGL(LOG_SSENGINE, "%s chown errno = %d\n", __func__, errno); + // debug end + + return E_SS_FAILURE; + } + + // mode is always 0777 at symlink file. It doesn't need to call chmod(). + if (S_ISLNK(sbuf.st_mode)) { + LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n"); + return S_SS_SUCCESS; + } + + if (chmod(setFilePath, setFileMode)) { + LOGL(LOG_SSENGINE, "%s chmod error\n", __func__); + return E_SS_FAILURE; + } +#if defined(FEATURE_SUPPORT_CAPABILITY) + if (has_cap) { + if (setxattr(setFilePath, "security.capability", (void*)cap_raw, cap_len, 0) < 0) { + LOGL(LOG_SSENGINE, "cap setxattr() failed: %s\n", strerror(errno)); + } + } + + if (has_acl) { + if (setxattr(setFilePath, "system.posix_acl_access", (void*)acl_raw, acl_len, 0) < 0) { + LOGL(LOG_SSENGINE, "Acl setxattr() failed: %s\n", strerror(errno)); + } + //LOG("Acl setxattr() :")asfd + } +#endif + + //LOGL(LOG_SSENGINE, "%s SUCCESS\n", __func__); + + return S_SS_SUCCESS; +} + + +long SS_CompareFileAttributes(void *pbUserData, + char *pFilePath, + unsigned char *pAdditionalAttribs, + unsigned long iAddiInfoSize) +{ + return S_SS_SUCCESS; +} + + + +#define MAX_INT 0xefffffff + +/* vrm functions */ +long +SS_GetAvailableFreeSpace(void *pbUserData, const char *partition_name, + SS_UINT32 *available_flash_size) +{ +// *available_flash_size = MAX_INT; +/* +#define IDENT_SBL "sbl" +#define IDENT_PLATFORM "platform" +#define IDENT_BOOT "boot" +*/ + int result = 0; + char path[MAX_PATH] = { '\0' }; + + SS_unicode_to_char(partition_name, (char *)path); + //LOGL(LOG_SSENGINE, "Enter %s path=%s\n", __func__, path); + struct statfs vfs; + + //LOGL(LOG_SSENGINE, "path=%s\n", path); + result = statfs(path, &vfs); + if (result < 0 ) + { + LOGE("failed to fstatfs, err : %d errno: %d\n", result, errno); + return -1; + } + + *available_flash_size = vfs.f_bsize * vfs.f_bavail; + if(*available_flash_size == 0) + { + *available_flash_size = 0x80000; //Same as Legecy RB + LOGE("available_flash_size=%u(vfs.f_bsize=%d vfs.f_bavail=%d\n", + (unsigned int)*available_flash_size, (int)vfs.f_bsize, (int)vfs.f_bavail); + return 0; // Same as Legecy RB + } + return 0; +} + +#ifdef HEAP_PROFILING + int max_mem; + int cur_mem; +#endif +/*******[ Multiprocess API sample implementation ]******/ +void *SS_Malloc(SS_UINT32 size) +{ + void *p = malloc(size); + + if (p) + memset(p, 0, size); +#ifdef HEAP_PROFILING + cur_mem += size; + if(cur_mem > max_mem ){ + max_mem = cur_mem; + LOGL(LOG_SSENGINE,"New chunk [%d] assigned making heap [%d]\n",size,cur_mem); + } +#endif + + return p; +} + +void SS_Free(void *pMemBlock) +{ +#ifdef HEAP_PROFILING + cur_mem -= malloc_usable_size(pMemBlock); + LOGL(LOG_SSENGINE,"Old chunk [%d] removed making heap [%d]\n",malloc_usable_size(pMemBlock),cur_mem); +#endif + if(pMemBlock) + free(pMemBlock); +} + +SS_UINT32 SS_GetMaxNumProcess(void *user) +{ + return SAMPLE_PROCS_NUM; +} + +void* SS_WaitForProcess(const void *handle, SS_UINT32* process_exit_code) +{ + pid_t pid; + *process_exit_code = 0; + + // processes + if (handle) + #ifdef _NOEXEC_ + pid = waitpid((pid_t)handle, (int *)process_exit_code, 0); + #else + pid = wait((int*)process_exit_code); + #endif + + else + pid = wait((int*)process_exit_code); + + if (pid < 0) + return NULL; + + if (!WIFEXITED(*process_exit_code)) + { + *process_exit_code = (char)WTERMSIG(*process_exit_code); + LOG("Wait Error\n"); + } + else + *process_exit_code = (char)WEXITSTATUS(*process_exit_code); + + return (void*)pid; +} +unsigned long SS_GetMaxProcRamSize(void *user) +{ + return UA_RAM_SIZE; +} + +void* SS_RunProcess(void *pbUserData, int argc, char* argv[]) +{ + pid_t child_pid; + + #ifdef _NOEXEC_ + child_pid = fork(); + #else + child_pid = vfork(); + #endif + + if (child_pid == -1) { + LOG("Fork failed.\n"); + return (void *)-1; + } + + // This is the child + if (child_pid == 0) + { + #ifdef _NOEXEC_ + #ifdef _TIZEN_REDBEND//bota + SS_HandleProcessRequest(pbUserData, argc, argv); + #endif + LOGL(LOG_SSENGINE, "SS_RunProcess was called - SS_HandleProcessRequest\n"); + exit(0); + #else + + char **params = NULL; + int i; + + params = (char **)SS_Malloc((argc+EXTRA_ARGS) *sizeof(char*)); + if (!params) + { + LOG("params allocation failed\n"); + return NULL; + } + // prepare child data, as it's forbidden to change data after vfork + params[0] = strdup(((sample_userdata*)user)->exec_path); + params[1] = strdup("handle_run_process"); + params[2] = strdup(((sample_userdata*)user)->delta_path); + + for (i=0; i < argc; i++) + params[i+EXTRA_ARGS] = strdup(argv[i]); + + // no need to free allocated memory - execv takes care of it + execv(params[0], (char**)params); + _exit(-1); // if we're here, execv has failed + #endif + } + else + { + return (void *)child_pid; + } +} + + + diff --git a/ss_engine/SS_FSUpdate.h b/ss_engine/SS_FSUpdate.h new file mode 100755 index 0000000..041cfaf --- /dev/null +++ b/ss_engine/SS_FSUpdate.h @@ -0,0 +1,407 @@ +/* + * 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. + */ + +/*! + ******************************************************************************* + * \file SS_FileSystemUpdate.h + * + * \brief UPI FS Update API + ******************************************************************************* + */ +#ifndef _SS_FILESYSTEM_UPDATE_H_ +#define _SS_FILESYSTEM_UPDATE_H_ + +#include "SS_Engine_Update.h" +#include "SS_Engine_Errors.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*! + * File access modes + */ +typedef enum tag_RW_TYPE{ + ONLY_R, //!< Read-only + ONLY_W, //!< Write-only + BOTH_RW //!< Read-write +}E_RW_TYPE; + +/*! + ******************************************************************************* + * Copy file.

+ * + * Must create the path to the new file as required. Must overwrite any contents + * in the old file, if any. Must check if the source file is a symbolic link. + * If it is, instead create a new symbolic link using \ref SS_Link. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param strFromPath Path to old file + * \param strToPath Path to new file + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_CopyFile( + void* pbUserData, + const char* strFromPath, + const char* strToPath +); + + +/*! + ******************************************************************************* + * Move (rename) file.

+ * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param strFromPath Path to old file location + * \param strToPath Path to new file location + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_MoveFile( + void* pbUserData, + const char* strFromPath, + const char* strToPath +); + +/*! + ******************************************************************************* + * Delete file.

+ * + * Must return success if the file is deleted or didn't exist. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param strPath Path to file + * + * \return S_SS_SUCCESS on success, E_SS_DELETEFILE if the file cannot be + * deleted, or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_DeleteFile( void* pbUserData, const char* strPath ); + + + +/*! + ******************************************************************************* + * Delete folder.

+ * + * Must return success if the folder is now deleted or didn't exist. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param strPath Path to folder + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_DeleteFolder( void* pbUserData, const char* strPath ); + + + +/*! + ******************************************************************************* + * Create folder.

+ * + * Must return success if the folder is created or already existsed. It is + * recommended that the new folder's attributes are a copy of its parent's + * attributes. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param strPath Path to folder + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_CreateFolder( void* pbUserData, const char* strPath ); + + + +/*! + ******************************************************************************* + * Open file.

+ * + * Must create the the file (and the path to the file) if it doesn't exist. Must + * open in binary mode. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param strPath Path to file + * \param wFlag Read/write mode, an \ref E_RW_TYPE value + * \param pwHandle (out) File handle + * + * \return S_SS_SUCCESS on success, E_SS_OPENFILE_ONLYR if attempting to open a + * non-existant file in R/O mode, E_SS_OPENFILE_WRITE if there is an + * error opening a file for writing, or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_OpenFile( + void* pbUserData, + const char* strPath, + E_RW_TYPE wFlag, + long* pwHandle +); + + + +/*! + ******************************************************************************* + * Set file size. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param wHandle File handle + * \param dwSize New file size + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_ResizeFile( + void* pbUserData, + long wHandle, + SS_UINT32 dwSize +); + + + +/*! + ******************************************************************************* + * Close file. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param wHandle File handle + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_CloseFile( + void* pbUserData, + long wHandle +); + + + +/*! + ******************************************************************************* + * Write data to a specified position within a file.

+ * + * Must return success if the block is written or at least resides in + * non-volatile memory. Use \ref SS_SyncFile to commit the file to storage. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param wHandle File handle + * \param dwPosition Position within the file to which to write + * \param pbBuffer Data to write + * \param dwSize Size of \a pbBuffer + * + * \return S_SS_SUCCESS on success, or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_WriteFile( + void* pbUserData, + long wHandle, + SS_UINT32 dwPosition, + unsigned char* pbBuffer, + SS_UINT32 dwSize +); + +/*! + ******************************************************************************* + * Commit file to storage.

+ * + * Generally called after \ref SS_WriteFile. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param wHandle File handle + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ +long SS_SyncFile( + void* pbUserData, + long wHandle +); + + +/*! + ******************************************************************************* + * Read data from a specified position within a file. + * If fewer bytes than requested are available in the specified position, this + * function should read up to the end of file and return S_SS_SUCCESS. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param wHandle File handle + * \param dwPosition Position within the file from which to read + * \param pbBuffer Buffer to contain data + * \param dwSize Size of data to read + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ + +long SS_ReadFile( + void* pbUserData, + long wHandle, + SS_UINT32 dwPosition, + unsigned char* pbBuffer, + SS_UINT32 dwSize +); + + +/*! + ******************************************************************************* + * Get file size. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param wHandle File handle + * + * \return File size, -1 if file not found, or < -1 on error + ******************************************************************************* + */ +long SS_GetFileSize( + void* pbUserData, + long wHandle +); + +/*! + ******************************************************************************* + * Get free space of a mounted file system. + * + * \param pbUserData Optional opaque data-structure to pass to + * IPL functions + * \param path Name of any directory within the mounted + * file system + * \param available_flash_size (out) Available space + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ +long SS_GetAvailableFreeSpace(void *pbUserData, const char *path, SS_UINT32 *available_flash_size); + +/*! + ******************************************************************************* + * Remove symbolic link.

+ * + * Must return an error if the file does not exist or is not a symbolic link.

+ * + * If your platform does not support symbolic links, you do not need to + * implement this. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param pLinkName Link + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ +long SS_Unlink(void *pbUserData, char *pLinkName); + +/*! + ******************************************************************************* + * Create symbolic link.

+ * + * Must create the path to the link as required. If a file already exists at the + * named location, must return success if the file is a symbolic link or an + * error if the file is a regular file. The non-existance of the target of the + * link must NOT cause an error.

+ * + * If your platform does not support symbolic links, you do not need to + * implement this. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param pLinkName Path to the link file to create + * \param pReferenceFileName Path to which to point the link + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ +long SS_Link(void *pbUserData, char *pLinkName, char *pReferenceFileName); + +/*! + ******************************************************************************* + * Set file attributes.

+ * + * The file attributes token (\a ui8pAttribs) is defined at generation time. + * If attributes are not defined explicitly, they are given the following, + * OS-dependent values: + * \li Windows: _redbend_ro_ for R/O files, _redbend_rw_ for R/W files + * \li Linux: _redbend_oooooo:xxxx:yyyy indicating the file mode, uid, and gid + * (uid and gid use capitalized hex digits as required) + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param ui16pFilePath File path + * \param ui32AttribSize Size of \a ui8pAttribs + * \param ui8pAttribs Attributes to set + * + * \return S_SS_SUCCESS on success or < 0 on error + ******************************************************************************* + */ + +long SS_SetFileAttributes(const char *ui16pFilePath, + const SS_UINT32 ui32AttribSize, + const unsigned char *ui8pAttribs); + +/*! + ******************************************************************************* + * Print status and debug information. + * + * \param pbUserData Optional opaque data-structure to pass to IPL + * functions + * \param aFormat A NULL-terminated printf-like string with support for + * the following tags: + * \li %x: Hex number + * \li %0x: Hex number with leading zeros + * \li %u: Unsigned decimal + * \li %s: NULL-terminated string + * \param ... Strings to insert in \a aFormat + * + * \return S_SS_SUCCESS on success or an \ref SS_vRM_Errors.h error code + ******************************************************************************* + */ +SS_UINT32 SS_Trace( + void* pbUserData, + const char* aFormat, + ... +); + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif diff --git a/tota-ua.manifest b/tota-ua.manifest new file mode 100755 index 0000000..1b29af6 --- /dev/null +++ b/tota-ua.manifest @@ -0,0 +1,9 @@ + + + + + + + + + -- 2.7.4