--- /dev/null
+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)
+
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+\r
+ Apache License\r
+ Version 2.0, January 2004\r
+ http://www.apache.org/licenses/\r
+\r
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+ 1. Definitions.\r
+\r
+ "License" shall mean the terms and conditions for use, reproduction,\r
+ and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+ "Licensor" shall mean the copyright owner or entity authorized by\r
+ the copyright owner that is granting the License.\r
+\r
+ "Legal Entity" shall mean the union of the acting entity and all\r
+ other entities that control, are controlled by, or are under common\r
+ control with that entity. For the purposes of this definition,\r
+ "control" means (i) the power, direct or indirect, to cause the\r
+ direction or management of such entity, whether by contract or\r
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+ outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+ "You" (or "Your") shall mean an individual or Legal Entity\r
+ exercising permissions granted by this License.\r
+\r
+ "Source" form shall mean the preferred form for making modifications,\r
+ including but not limited to software source code, documentation\r
+ source, and configuration files.\r
+\r
+ "Object" form shall mean any form resulting from mechanical\r
+ transformation or translation of a Source form, including but\r
+ not limited to compiled object code, generated documentation,\r
+ and conversions to other media types.\r
+\r
+ "Work" shall mean the work of authorship, whether in Source or\r
+ Object form, made available under the License, as indicated by a\r
+ copyright notice that is included in or attached to the work\r
+ (an example is provided in the Appendix below).\r
+\r
+ "Derivative Works" shall mean any work, whether in Source or Object\r
+ form, that is based on (or derived from) the Work and for which the\r
+ editorial revisions, annotations, elaborations, or other modifications\r
+ represent, as a whole, an original work of authorship. For the purposes\r
+ of this License, Derivative Works shall not include works that remain\r
+ separable from, or merely link (or bind by name) to the interfaces of,\r
+ the Work and Derivative Works thereof.\r
+\r
+ "Contribution" shall mean any work of authorship, including\r
+ the original version of the Work and any modifications or additions\r
+ to that Work or Derivative Works thereof, that is intentionally\r
+ submitted to Licensor for inclusion in the Work by the copyright owner\r
+ or by an individual or Legal Entity authorized to submit on behalf of\r
+ the copyright owner. For the purposes of this definition, "submitted"\r
+ means any form of electronic, verbal, or written communication sent\r
+ to the Licensor or its representatives, including but not limited to\r
+ communication on electronic mailing lists, source code control systems,\r
+ and issue tracking systems that are managed by, or on behalf of, the\r
+ Licensor for the purpose of discussing and improving the Work, but\r
+ excluding communication that is conspicuously marked or otherwise\r
+ designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+ "Contributor" shall mean Licensor and any individual or Legal Entity\r
+ on behalf of whom a Contribution has been received by Licensor and\r
+ subsequently incorporated within the Work.\r
+\r
+ 2. Grant of Copyright License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ copyright license to reproduce, prepare Derivative Works of,\r
+ publicly display, publicly perform, sublicense, and distribute the\r
+ Work and such Derivative Works in Source or Object form.\r
+\r
+ 3. Grant of Patent License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ (except as stated in this section) patent license to make, have made,\r
+ use, offer to sell, sell, import, and otherwise transfer the Work,\r
+ where such license applies only to those patent claims licensable\r
+ by such Contributor that are necessarily infringed by their\r
+ Contribution(s) alone or by combination of their Contribution(s)\r
+ with the Work to which such Contribution(s) was submitted. If You\r
+ institute patent litigation against any entity (including a\r
+ cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+ or a Contribution incorporated within the Work constitutes direct\r
+ or contributory patent infringement, then any patent licenses\r
+ granted to You under this License for that Work shall terminate\r
+ as of the date such litigation is filed.\r
+\r
+ 4. Redistribution. You may reproduce and distribute copies of the\r
+ Work or Derivative Works thereof in any medium, with or without\r
+ modifications, and in Source or Object form, provided that You\r
+ meet the following conditions:\r
+\r
+ (a) You must give any other recipients of the Work or\r
+ Derivative Works a copy of this License; and\r
+\r
+ (b) You must cause any modified files to carry prominent notices\r
+ stating that You changed the files; and\r
+\r
+ (c) You must retain, in the Source form of any Derivative Works\r
+ that You distribute, all copyright, patent, trademark, and\r
+ attribution notices from the Source form of the Work,\r
+ excluding those notices that do not pertain to any part of\r
+ the Derivative Works; and\r
+\r
+ (d) If the Work includes a "NOTICE" text file as part of its\r
+ distribution, then any Derivative Works that You distribute must\r
+ include a readable copy of the attribution notices contained\r
+ within such NOTICE file, excluding those notices that do not\r
+ pertain to any part of the Derivative Works, in at least one\r
+ of the following places: within a NOTICE text file distributed\r
+ as part of the Derivative Works; within the Source form or\r
+ documentation, if provided along with the Derivative Works; or,\r
+ within a display generated by the Derivative Works, if and\r
+ wherever such third-party notices normally appear. The contents\r
+ of the NOTICE file are for informational purposes only and\r
+ do not modify the License. You may add Your own attribution\r
+ notices within Derivative Works that You distribute, alongside\r
+ or as an addendum to the NOTICE text from the Work, provided\r
+ that such additional attribution notices cannot be construed\r
+ as modifying the License.\r
+\r
+ You may add Your own copyright statement to Your modifications and\r
+ may provide additional or different license terms and conditions\r
+ for use, reproduction, or distribution of Your modifications, or\r
+ for any such Derivative Works as a whole, provided Your use,\r
+ reproduction, and distribution of the Work otherwise complies with\r
+ the conditions stated in this License.\r
+\r
+ 5. Submission of Contributions. Unless You explicitly state otherwise,\r
+ any Contribution intentionally submitted for inclusion in the Work\r
+ by You to the Licensor shall be under the terms and conditions of\r
+ this License, without any additional terms or conditions.\r
+ Notwithstanding the above, nothing herein shall supersede or modify\r
+ the terms of any separate license agreement you may have executed\r
+ with Licensor regarding such Contributions.\r
+\r
+ 6. Trademarks. This License does not grant permission to use the trade\r
+ names, trademarks, service marks, or product names of the Licensor,\r
+ except as required for reasonable and customary use in describing the\r
+ origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+ 7. Disclaimer of Warranty. Unless required by applicable law or\r
+ agreed to in writing, Licensor provides the Work (and each\r
+ Contributor provides its Contributions) on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+ implied, including, without limitation, any warranties or conditions\r
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+ PARTICULAR PURPOSE. You are solely responsible for determining the\r
+ appropriateness of using or redistributing the Work and assume any\r
+ risks associated with Your exercise of permissions under this License.\r
+\r
+ 8. Limitation of Liability. In no event and under no legal theory,\r
+ whether in tort (including negligence), contract, or otherwise,\r
+ unless required by applicable law (such as deliberate and grossly\r
+ negligent acts) or agreed to in writing, shall any Contributor be\r
+ liable to You for damages, including any direct, indirect, special,\r
+ incidental, or consequential damages of any character arising as a\r
+ result of this License or out of the use or inability to use the\r
+ Work (including but not limited to damages for loss of goodwill,\r
+ work stoppage, computer failure or malfunction, or any and all\r
+ other commercial damages or losses), even if such Contributor\r
+ has been advised of the possibility of such damages.\r
+\r
+ 9. Accepting Warranty or Additional Liability. While redistributing\r
+ the Work or Derivative Works thereof, You may choose to offer,\r
+ and charge a fee for, acceptance of support, warranty, indemnity,\r
+ or other liability obligations and/or rights consistent with this\r
+ License. However, in accepting such obligations, You may act only\r
+ on Your own behalf and on Your sole responsibility, not on behalf\r
+ of any other Contributor, and only if You agree to indemnify,\r
+ defend, and hold each Contributor harmless for any liability\r
+ incurred by, or claims asserted against, such Contributor by reason\r
+ of your accepting any such warranty or additional liability.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\r
+ APPENDIX: How to apply the Apache License to your work.\r
+\r
+ To apply the Apache License to your work, attach the following\r
+ boilerplate notice, with the fields enclosed by brackets "[]"\r
+ replaced with your own identifying information. (Don't include\r
+ the brackets!) The text should be enclosed in the appropriate\r
+ comment syntax for the file format. We also recommend that a\r
+ file or class name and description of purpose be included on the\r
+ same "printed page" as the copyright notice for easier\r
+ identification within third-party archives.\r
+\r
+ Copyright [yyyy] [name of copyright owner]\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
--- /dev/null
+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})
+
+
--- /dev/null
+/*
+ * 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 <stdio.h>
+#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__ */
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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
+}
+
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#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<len; i++) {
+ ch = *(str + i);
+ if ((ch >= '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();
+}
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <error.h>
+
+#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;
+}
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#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;
+}
+
+
--- /dev/null
+/*
+ * 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 <stdio.h>
+
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <png.h>
+#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);
+}
+
+
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <error.h>
+
+#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;
+}
--- /dev/null
+/*
+ * 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 <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#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; i<output_count; i++)
+ {
+ output = tdm_display_get_output(st_disp->disp, 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; i<output_count; i++)
+ {
+ tmp_layer = tdm_output_get_layer(st_disp->output, 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 ;
+}
--- /dev/null
+/*
+ * 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 <tdm.h>
+#include <tbm_bufmgr.h>
+#include <tdm_helper.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+
+#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__ */
--- /dev/null
+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/*
+++ /dev/null
-%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
--- /dev/null
+This is not a used file.
--- /dev/null
+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})
+
+
--- /dev/null
+/*
+ * 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 <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/err.h>
+
+#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;
+}
+
--- /dev/null
+/*
+ * 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 <string.h>
+
+#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);
+}
+
--- /dev/null
+/*
+ * 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__ */
+
+
--- /dev/null
+/*
+ * 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 <stdio.h>
+#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__ */
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdarg.h>
+
+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();
+}
+
+
--- /dev/null
+/*
+ * 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 <stdio.h>
+
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+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);
+}
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/reboot.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#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>
+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
+
+<Firmware Update Package-Device Mismatch>
+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
+
+<Failed Firmware Update Package Validation>
+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 Not Acceptable>
+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)
+
+<Firmware update fails due to device out of memory>
+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<num_part; i++) {
+ if (fscanf(fp, "%d %32s", &id, part_name) < 0) {
+ LOG("fail to fscanf()\n");
+ break;
+ }
+ LOG("%s [%d]\n", part_name, id);
+ for(j = 0; j < s_part_num; j++) {
+ if (strcmp(s_part_info[j].ua_parti_name, part_name) == 0) {
+ memset((void*)blk_name, 0x00, sizeof(blk_name));
+ snprintf(blk_name, sizeof(blk_name)-1, "/dev/mmcblk0p%d", id);
+ s_part_info[j].ua_blk_name = strdup(blk_name);
+ }
+ }
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ fota_configure_update
+ ----------------------------------------------------------------------------*/
+int fota_configure_update(void)
+{
+ char cfg_data[MAX_CFG_LEN];
+ int data_size = -1;
+ char* line = NULL;
+ char* field = NULL;
+ char* ctx1 = NULL;
+ char* ctx2 = NULL;
+ int line_num = 0;
+ int field_num = 0;
+ char* part_name = NULL;
+ char* subj_name = NULL;
+ int update_type = EXTRA;
+ int part_idx = UA_PARTI_MAX;
+ char *blk_name = NULL;
+ int blk_offset = 0;
+ int src_img_size=0;
+ int trg_img_size=0;
+ char *src_img_sha1=NULL;
+ char *trg_img_sha1=NULL;
+ memset((void*)cfg_data, 0x00, sizeof(cfg_data));
+
+ data_size = tar_get_cfg_data(delta_path, UPDATTE_CFG_FILE, cfg_data, MAX_CFG_LEN);
+ if (data_size <= 0) {
+ LOG("tar_get_cfg_data() fail\n");
+ return -1;
+ }
+
+ line_num = 0;
+ line = strtok_r(cfg_data, "\n", &ctx1);
+ while (line) {
+ part_name = NULL;
+ subj_name = NULL;
+ update_type = EXTRA;
+ part_idx = UA_PARTI_MAX;
+ blk_name = NULL;
+ blk_offset = 0;
+ src_img_size=0;
+ trg_img_size=0;
+ src_img_sha1=NULL;
+ trg_img_sha1=NULL;
+
+ field_num = 0;
+ field = strtok_r(line, "\t", &ctx2);
+ while (field) {
+ switch (field_num) {
+ case 0:
+ part_name = strdup(field);
+ part_idx = get_part_idx(field);
+ break;
+ case 1:
+ subj_name = strdup(field);
+ break;
+ case 2:
+ update_type = get_update_type(field);
+ break;
+ case 3:
+ blk_name = strdup(field);
+ break;
+ case 4:
+ blk_offset = atoi(field);
+ break;
+ case 5:
+ src_img_size=atoi(field);
+ break;
+ case 6:
+ trg_img_size=atoi(field);
+ break;
+ case 7:
+ src_img_sha1=strdup(field);
+ break;
+ case 8:
+ trg_img_sha1=strdup(field);
+ break;
+ }
+ field_num++;
+ LOG("%s,", field);
+ field = strtok_r(NULL, "\t", &ctx2);
+ }
+ LOG("\n");
+if(!part_name)
+ return -1;
+ if (update_type != EXTRA
+#ifdef SS_RECOVERYRAMDISK
+ || (0==strcmp(part_name, "RAMDISK2"))
+#endif
+) {
+ s_part_info[line_num].ua_parti_name = part_name;
+ s_part_info[line_num].ua_subject_name = subj_name;
+ s_part_info[line_num].ua_blk_name = blk_name;
+ s_part_info[line_num].ua_blk_offset = blk_offset;
+
+ s_update_cfg[line_num].update_type = update_type;
+ s_update_cfg[line_num].part_idx = part_idx;
+ s_update_cfg[line_num].soure_img_size= src_img_size;
+ s_update_cfg[line_num].target_img_size= trg_img_size;
+ s_update_cfg[line_num].soure_sha1=src_img_sha1;
+ s_update_cfg[line_num].target_sha1=trg_img_sha1;
+
+ line_num++;
+ } else {
+ if (part_name) free(part_name);
+ if (subj_name) free(subj_name);
+ if (blk_name) free(blk_name);
+ }
+ line = strtok_r(NULL, "\n", &ctx1);
+ }
+
+ LOG("Effective cfg line num = %d\n", line_num);
+
+ return line_num;
+}
+
+/*-----------------------------------------------------------------------------
+ main
+
+ argv[1] : directory path for delta file
+ argv[2] : directory path for log file, result file, temp file
+ argv[3] : operation mode ("0" or none : Foreground Mode, "1" : Background Mode)
+ ----------------------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+ char ver_str[MAX_PATH];
+ int ret = FAIL;
+
+ _init_stdio();
+
+ /* check whether FG mode or BG mode */
+ if (check_ua_op_mode(argc, argv) < 0) {
+ ret = UPI_INVALID_PARAM_ERROR;
+ goto Results;
+ }
+
+ if (strcmp(argv[1], "/system") == 0) {
+ s_initrd_version = 0;
+ }
+
+ if (s_initrd_version == 0) {
+ memset(delta_folder, 0x00, sizeof(delta_folder));
+ snprintf(delta_folder, sizeof(delta_folder)-1, "%s", argv[2]);
+ snprintf(delta_path, sizeof(delta_path), "%s/%s", delta_folder, DEFAULT_DELTA_NAME);
+
+ memset(temp_folder, 0x00, sizeof(temp_folder));
+ snprintf(temp_folder, sizeof(temp_folder)-1, "%s", delta_folder);
+ } else {
+ memset(delta_folder, 0x00, sizeof(delta_folder));
+ snprintf(delta_folder, sizeof(delta_folder)-1, "%s", argv[1]);
+ snprintf(delta_path, sizeof(delta_path), "%s/%s", delta_folder, DEFAULT_DELTA_NAME);
+
+ memset(temp_folder, 0x00, sizeof(temp_folder));
+ snprintf(temp_folder, sizeof(temp_folder)-1, "%s", argv[2]);
+ }
+
+ memset(log_folder, 0x00, sizeof(log_folder));
+ snprintf(log_folder, sizeof(log_folder)-1, "%s", temp_folder);
+
+ memset(result_folder, 0x00, sizeof(result_folder));
+ snprintf(result_folder, sizeof(result_folder)-1, "%s", temp_folder);
+
+ _launch_fota_gui_process();
+
+ log_init();
+ fota_cfg_str_load();
+
+ /* Check fota folder path */
+ if(check_existence(delta_folder) == 0) {
+ ret = UPI_DELTA_PATH_ERROR;
+ goto Results;
+ }
+
+ /* load update configuration */
+ ret = fota_configure_update();
+ if (ret > 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;
+}
--- /dev/null
+/*
+ * 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 <stdio.h>
+
+/*
+ * 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
--- /dev/null
+/*
+ * 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/smack.h>
+#include <sys/wait.h>
+
+#include <ftw.h>
+#include <sys/xattr.h>
+#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.<p>
+ *
+ * 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<cap_len; i++) {
+ ch1 = tmpSmackAttribs[i*2];
+ ch2 = tmpSmackAttribs[i*2+1];
+ if ((ch1 >= '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<acl_len; i++) {
+ ch1 = tmpSmackAttribs[i*2];
+ ch2 = tmpSmackAttribs[i*2+1];
+ if ((ch1 >= '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;
+ }
+}
+
+
+
--- /dev/null
+/*
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * \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.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * Must return an error if the file does not exist or is not a symbolic link.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * 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.<p>
+ *
+ * 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
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+ <assign>
+ <filesystem path="/usr/bin/*" exec_label="none" />
+ </assign>
+</manifest>
+