[Feature][task-view-762][FOTA] move the real fota functions to lynq-fota-tool process

Only Configure: No
Affected branch: ZK-first-oem-release
Affected module: FOTA
Is it affected on both ZXIC and MTK: only MTK
Self-test: Yes
Doc Update: No

Change-Id: Ie0661abd3f7b56e56deae2a0099b9070f07aeb08
diff --git a/LYNQ_PUBLIC/IC_meta/mtk/2735/liblynq-fota-run/liblynq-fota-run.bb b/LYNQ_PUBLIC/IC_meta/mtk/2735/liblynq-fota-run/liblynq-fota-run.bb
new file mode 100755
index 0000000..faa12a6
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_meta/mtk/2735/liblynq-fota-run/liblynq-fota-run.bb
@@ -0,0 +1,66 @@
+inherit externalsrc package
+
+DESCRIPTION = "lynq-fota-run.so demo"
+SECTION = "base"
+#LICENSE = "MediaTekProprietary"
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+DEPENDS += "bootctrl nandapi liblynq-protcl liblynq-log liblynq-uci"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -Wl,--hash-style=gnu"
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'RAT_CONFIG_C2K_SUPPORT = ${RAT_CONFIG_C2K_SUPPORT}'\
+                'MTK_MULTI_SIM_SUPPORT = ${MTK_MULTI_SIM_SUPPORT}'\
+                'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+
+FILES_${PN} = "${base_libdir}/*.so \
+               ${base_bindir}\
+               ${base_sbindir}"
+
+
+FILES_${PN}-dev = "/test \
+                   ${includedir}"
+
+FILES_${PN}-doc = "/doc"
+
+FILES_${PN}-dbg ="${base_bindir}/.debug \
+                  ${base_libdir}/.debug \
+                  ${base_sbindir}/.debug"
+
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+	if [ "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" ]; then
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+	elif [ "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4" ]; then
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+	elif [ "${PACKAGE_ARCH}" = "cortexa53hf-neon-fp-armv8" ]; then
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE -mhard-float -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53 -mtune=cortex-a53"
+	else
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -Wl,--hash-style=gnu -DTELEPHONYWARE"
+	fi
+}
+
+do_install () {
+    oe_runmake install ROOT=${D}
+
+    if [ -d "${WORKONSRC}" ] ; then
+        install -d ${D}${includedir}/
+        cp -af ${S}/include/ ${D}${includedir}/
+      fi
+}
+
+addtask bachclean
+do_bachclean () {
+    oe_runmake clean
+}
diff --git a/LYNQ_PUBLIC/IC_meta/mtk/2735/lynq-fota-tool/lynq-fota-tool.bb b/LYNQ_PUBLIC/IC_meta/mtk/2735/lynq-fota-tool/lynq-fota-tool.bb
new file mode 100755
index 0000000..a788e78
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_meta/mtk/2735/lynq-fota-tool/lynq-fota-tool.bb
@@ -0,0 +1,36 @@
+inherit externalsrc package
+
+DESCRIPTION = "lynq-fota-tool demo"
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS += "platform-libs liblynq-fota-run"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'RAT_CONFIG_C2K_SUPPORT = ${RAT_CONFIG_C2K_SUPPORT}'\
+                'MTK_MULTI_SIM_SUPPORT = ${MTK_MULTI_SIM_SUPPORT}'\
+                'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+EXTRA_OEMAKE += "'LYNQ_CONFIG_VERSION = ${LYNQ_CONFIG_VERSION}' \
+                 'LYNQ_CONFIG_SW_VERSION = ${LYNQ_CONFIG_SW_VERSION}'"
+
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+	if [ "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" ]; then
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+	elif [ "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4" ]; then
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+	elif [ "${PACKAGE_ARCH}" = "cortexa53hf-neon-fp-armv8" ]; then
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE -mhard-float -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53 -mtune=cortex-a53"
+	else
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -Wl,--hash-style=gnu -DTELEPHONYWARE"
+	fi
+}
+
+do_install() {
+	install -d ${D}${bindir}/
+	install -m 0755 ${S}/lynq-fota-tool ${D}${bindir}/
+}
diff --git a/LYNQ_PUBLIC/IC_meta/mtk/2735/packagegroups/packagegroup-lynq-mt2735.bb b/LYNQ_PUBLIC/IC_meta/mtk/2735/packagegroups/packagegroup-lynq-mt2735.bb
index 5d637e5..a58e907 100755
--- a/LYNQ_PUBLIC/IC_meta/mtk/2735/packagegroups/packagegroup-lynq-mt2735.bb
+++ b/LYNQ_PUBLIC/IC_meta/mtk/2735/packagegroups/packagegroup-lynq-mt2735.bb
@@ -11,6 +11,7 @@
     liblynq-uci \
     liblynq-protcl \
     liblynq-fota \
+    liblynq-fota-run \
     lynq-threadhandle \
     lynq-broadcast-receive \
     lynq-broadcast-send \
@@ -35,6 +36,7 @@
     lynq-at-test \
     liblynq-logdata-handle \
     lynq-default \
+    lynq-fota-tool \
     lynq-logrotate-service \
     liblynq-system-own \
     lynq-wg870 \
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/MD5/md5.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/MD5/md5.c
new file mode 100755
index 0000000..5dd9ff3
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/MD5/md5.c
@@ -0,0 +1,161 @@
+#include "string.h"
+#include "md5.h"
+
+unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+void MD5Init(MD5_CTX *context)
+{
+	context->count[0] = 0;
+	context->count[1] = 0;
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xEFCDAB89;
+	context->state[2] = 0x98BADCFE;
+	context->state[3] = 0x10325476;
+}
+void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
+{
+	unsigned int i = 0,index = 0,partlen = 0;
+	index = (context->count[0] >> 3) & 0x3F;
+	partlen = 64 - index;
+	context->count[0] += inputlen << 3;
+	if(context->count[0] < (inputlen << 3))
+		context->count[1]++;
+	context->count[1] += inputlen >> 29;
+
+	if(inputlen >= partlen)
+	{
+		memcpy(&context->buffer[index],input,partlen);
+		MD5Transform(context->state,context->buffer);
+		for(i = partlen;i+64 <= inputlen;i+=64)
+			MD5Transform(context->state,&input[i]);
+		index = 0;        
+	}  
+	else
+	{
+		i = 0;
+	}
+	memcpy(&context->buffer[index],&input[i],inputlen-i);
+}
+void MD5Final(MD5_CTX *context,unsigned char digest[16])
+{
+	unsigned int index = 0,padlen = 0;
+	unsigned char bits[8];
+	index = (context->count[0] >> 3) & 0x3F;
+	padlen = (index < 56)?(56-index):(120-index);
+	MD5Encode(bits,context->count,8);
+	MD5Update(context,PADDING,padlen);
+	MD5Update(context,bits,8);
+	MD5Encode(digest,context->state,16);
+}
+void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
+{
+	unsigned int i = 0,j = 0;
+	while(j < len)
+	{
+		output[j] = input[i] & 0xFF;  
+		output[j+1] = (input[i] >> 8) & 0xFF;
+		output[j+2] = (input[i] >> 16) & 0xFF;
+		output[j+3] = (input[i] >> 24) & 0xFF;
+		i++;
+		j+=4;
+	}
+}
+void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
+{
+	unsigned int i = 0,j = 0;
+	while(j < len)
+	{
+		output[i] = (input[j]) |
+			(input[j+1] << 8) |
+			(input[j+2] << 16) |
+			(input[j+3] << 24);
+		i++;
+		j+=4; 
+	}
+}
+void MD5Transform(unsigned int state[4],unsigned char block[64])
+{
+	unsigned int a = state[0];
+	unsigned int b = state[1];
+	unsigned int c = state[2];
+	unsigned int d = state[3];
+	unsigned int x[64];
+	MD5Decode(x,block,64);
+	FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
+	FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
+	FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
+	FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
+	FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
+	FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
+	FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
+	FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
+	FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
+	FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
+	FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
+	FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
+	FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
+	FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
+	FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
+	FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
+
+	/* Round 2 */
+	GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
+	GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
+	GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
+	GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
+	GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
+	GG(d, a, b, c, x[10], 9,  0x2441453); /* 22 */
+	GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
+	GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
+	GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
+	GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
+	GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
+	GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
+	GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
+	GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
+	GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
+	GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
+
+	/* Round 3 */
+	HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
+	HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
+	HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
+	HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
+	HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
+	HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
+	HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
+	HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
+	HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
+	HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
+	HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
+	HH(b, c, d, a, x[ 6], 23,  0x4881d05); /* 44 */
+	HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
+	HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
+	HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
+	HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
+
+	/* Round 4 */
+	II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
+	II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
+	II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
+	II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
+	II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
+	II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
+	II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
+	II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
+	II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
+	II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
+	II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
+	II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
+	II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
+	II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
+	II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
+	II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+}
\ No newline at end of file
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/MD5/md5_encode.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/MD5/md5_encode.c
new file mode 100755
index 0000000..918d634
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/MD5/md5_encode.c
@@ -0,0 +1,264 @@
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <log/log.h>
+//xf.li@20230822 add for ab recover start
+#include <errno.h>
+//xf.li@20230822 add for ab recover end
+#include "md5.h"
+#include "mtk_device_wrap.h"
+#include "liblog/lynq_deflog.h"
+#define LOG_TAG "LYNQ_FOTA"
+
+int ota_file_open(char* path, char* flag)
+{
+#if 1
+	if(strcmp(flag, "r") == 0 || strcmp(flag, "rb") == 0)
+		return mtk_device_wrap_open(path, O_RDONLY);
+	else if(strcmp(flag, "r+") == 0 || strcmp(flag, "rb+") == 0)
+		return mtk_device_wrap_open(path, O_RDWR | O_CREAT);
+	else if(strcmp(flag, "w+") == 0 ||strcmp(flag, "wb+") == 0 || strcmp(flag, "w") == 0  || strcmp(flag, "wb") == 0 )	
+		return mtk_device_wrap_open(path, O_RDWR | O_CREAT | O_TRUNC);
+	else if(strcmp(flag, "a+") == 0 ||strcmp(flag, "ab+") == 0 || strcmp(flag, "a") == 0  || strcmp(flag, "ab") == 0 )	
+		return mtk_device_wrap_open(path, O_RDWR | O_CREAT | O_APPEND);	
+#endif
+}
+
+
+int ota_file_seek(int handle, int offset,  int flag)
+{
+	return mtk_device_wrap_seek(handle,offset,flag);
+}
+
+
+
+int ota_file_read(char* buffer, size_t count, int file)
+{
+	return mtk_device_wrap_read(file,buffer,count);
+}
+
+
+
+void ota_file_close(int handle)
+{
+	mtk_device_wrap_close(handle);
+}
+
+#define MD5_READ_BUFFER_LEN 4*1024
+int lynq_md5_file_verfy(char* filePath, char* file_md5)
+{
+	int ret = -1;
+	int handle;
+
+	LYVERBLOG("[+MD5]:calc file md5: %s\n", filePath);
+	handle = open(filePath, O_RDONLY);	
+	LYVERBLOG("[+MD5]:handle:%d\n",handle);
+	if(handle >= 0){
+		{
+			int read_len = 0; 
+			unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+			unsigned char decrypt[16];
+			int i;
+			MD5_CTX md5;  
+			MD5Init(&md5);
+			//strcpy(buffer,"12345");
+			while ((read_len = read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+			{   
+				//printf("readlen:%d\n",read_len);
+				MD5Update(&md5, (unsigned char*)buffer, read_len); 				
+				memset(buffer,0,sizeof(buffer));
+			}
+			MD5Final(&md5, (unsigned char*)decrypt);
+			memset(buffer, 0, MD5_READ_BUFFER_LEN);
+			for(i = 0; i < 16; i++)  
+			{  
+				sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);  
+			}
+			LYVERBLOG("[+MD5]:md5:%s\n", buffer);
+			LYVERBLOG("[+MD5]:md5:%s\n", file_md5);
+			
+			ret = strncmp((const char*)buffer, (const char*)file_md5,32);
+			LYVERBLOG("[+MD5]:ret:%d\n", ret);
+		}
+		close(handle);
+	}
+	return ret;
+}
+//xf.li@20230822 add for ab recover start
+#define MD5_VERFY_ERROR 5
+int lynq_md5_file_verfy_ab(char* filePath, char* file_md5)
+{
+	int ret = -1;
+	int handle;
+
+	RLOGD("[+MD5]:calc file md5: %s\n", filePath);
+	handle = open(filePath, O_RDONLY);	
+	RLOGD("[+MD5]:handle:%d\n",handle);
+	if(handle == -1)
+	{
+		RLOGD("[+MD5]: can't open the file, errno is %d\n",errno);
+	}
+	if(handle >= 0)
+	{
+		int read_len = 0; 
+		unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+		unsigned char decrypt[16];
+		int i;
+		MD5_CTX md5;  
+		MD5Init(&md5);
+		while ((read_len = read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+		{   
+			MD5Update(&md5, (unsigned char*)buffer, read_len); 				
+			memset(buffer,0,sizeof(buffer));
+			usleep(1000);
+		}
+		MD5Final(&md5, (unsigned char*)decrypt);
+		memset(buffer, 0, MD5_READ_BUFFER_LEN);
+		for(i = 0; i < 16; i++)  
+		{  
+			sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);  
+		}
+		RLOGD("[+MD5]:buffer md5:%s\n", buffer);
+		RLOGD("[+MD5]:file_md5 md5:%s\n", file_md5);
+		
+		ret = strncmp((const char*)buffer, (const char*)file_md5,32);
+		RLOGD("[+MD5]:ret:%d\n", ret);
+		close(handle);
+	}
+	if(ret != 0)
+	{
+		return MD5_VERFY_ERROR;
+	}
+	return ret;
+}
+int calculate_file_md5_value(char* filePath, unsigned char buffer_out[])
+{
+	//int ret = -1;
+	int handle;
+
+	RLOGD("[+MD5]:calc file md5: %s\n", filePath);
+	handle = open(filePath, O_RDONLY);
+	RLOGD("[+MD5]:handle:%d\n",handle);
+	if(handle == -1)
+	{
+		RLOGD("[+MD5]: can't open the file, errno is %d\n",errno);
+	}
+	if(handle >= 0)
+	{
+		int read_len = 0; 
+		unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+		unsigned char decrypt[16];
+		int i;
+		MD5_CTX md5;  
+		MD5Init(&md5);
+		while ((read_len = read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+		{   
+			MD5Update(&md5, (unsigned char*)buffer, read_len); 				
+			memset(buffer,0,sizeof(buffer));
+			usleep(1000);
+		}
+		MD5Final(&md5, (unsigned char*)decrypt);
+		memset(buffer, 0, MD5_READ_BUFFER_LEN);
+		for(i = 0; i < 16; i++)  
+		{  
+			sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);  
+		}
+		RLOGD("[+MD5]: md5 of %s : %s\n", filePath, buffer);
+		memcpy(buffer_out, buffer, MD5_READ_BUFFER_LEN);
+		close(handle);
+	}
+	else
+	{
+		return -1;
+	}
+	return 0;
+}
+
+int lynq_md5_two_file_verfy(char* filePath_1, char* filePath_2)
+{
+	int ret = -1;
+	int handle_1, handle_2;
+	unsigned char buffer_1[MD5_READ_BUFFER_LEN] = {0};
+	unsigned char buffer_2[MD5_READ_BUFFER_LEN] = {0};
+	
+	ret = calculate_file_md5_value(filePath_1, buffer_1);
+	if(ret < 0)
+	{
+		RLOGD("[+MD5]:calculate file1 md5 value ERROE!!!\n");
+		return ret;
+	}
+	ret = calculate_file_md5_value(filePath_2, buffer_2);
+	if(ret < 0)
+	{
+		RLOGD("[+MD5]:calculate file2 md5 value ERROE!!!\n");
+		return ret;
+	}
+	RLOGD("buffer_1 is %s, buffer_2 is %s\n", buffer_1, buffer_2);
+	ret = strncmp((const char*)buffer_1, (const char*)buffer_2, 32);
+	RLOGD("[+MD5]:strncmp ret:%d\n", ret);
+
+	if(ret != 0)
+	{
+		return MD5_VERFY_ERROR;
+	}
+	return 0;
+}
+//xf.li@20230822 add for ab recover end
+#if 0
+int md5_file_verfy_new(char* filePath, char* file_md5,int packe_len)
+{
+	int ret = -1;
+	int handle;
+	int tatal_packe_len = 0;
+
+	LYVERBLOG("[+MD5]:calc file md5: %s\n", filePath);
+	handle = mtk_device_wrap_open(filePath, O_RDONLY);	
+	LYVERBLOG("[+MD5]:handle:%d\n",handle);
+	if(handle >= 0){
+		{
+			int read_len = 0; 
+			unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+			unsigned char decrypt[16];
+			int i;
+			MD5_CTX md5;  
+			MD5Init(&md5);
+			//strcpy(buffer,"12345");
+			tatal_packe_len = packe_len;
+			LYVERBLOG("[+MD5]:tatal_packe_len:%d\n", tatal_packe_len);
+			while ((read_len = mtk_device_wrap_read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+			{   
+				//printf("readlen:%d\n",read_len);
+				if(tatal_packe_len >= read_len)
+				{
+					MD5Update(&md5, (unsigned char*)buffer, read_len); 
+					tatal_packe_len -= read_len;
+				}
+				else if(tatal_packe_len > 0)
+				{
+					LYVERBLOG("[+MD5]:tatal_packe_len:%d\n", tatal_packe_len);
+					MD5Update(&md5, (unsigned char*)buffer, tatal_packe_len); 
+					tatal_packe_len -= read_len;
+				}
+				LYVERBLOG("[+MD5]:tatal_packe_len:%d\n", tatal_packe_len);			
+				memset(buffer,0,sizeof(buffer));
+			}
+			MD5Final(&md5, (unsigned char*)decrypt);
+			memset(buffer, 0, MD5_READ_BUFFER_LEN);
+			for(i = 0; i < 16; i++)  
+			{  
+				sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);  
+			}
+			LYVERBLOG("[+MD5]:md5:%s\n", buffer);
+			LYVERBLOG("[+MD5]:md5:%s\n", file_md5);
+			
+			ret = strncmp((const char*)buffer, (const char*)file_md5,32);
+			LYVERBLOG("[+MD5]:ret:%d\n", ret);
+		}
+		mtk_device_wrap_close(handle);
+	}
+	return ret;
+}
+#endif
\ No newline at end of file
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/iot_rock.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/iot_rock.h
new file mode 100755
index 0000000..ea557b9
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/iot_rock.h
@@ -0,0 +1,166 @@
+#ifndef _IOT_ROCK_H_

+#define _IOT_ROCK_H_

+

+#include <sys/types.h>

+#include <sys/stat.h>

+#include <fcntl.h>

+#include <unistd.h>

+

+/* public */

+

+#define E_ROCK_SUCCESS (0)

+#define E_ROCK_INVALID_DELTA (-1)

+#define E_ROCK_DELTA_MISMATCH (-2)

+#define E_ROCK_DELTA_CHUNK_MISMATCH (-3)

+#define E_ROCK_READ_DELTA_ERROR (-4)

+#define E_ROCK_READ_BLOCK_ERROR (-11)

+#define E_ROCK_WRITE_BLOCK_ERROR (-12)

+#define E_ROCK_RAM_NOT_ENOUGH (-20)

+#define E_ROCK_INVALID_CTX	(-30)

+#define E_ROCK_FOTA_ADDR (-50)

+

+

+#define PATCH_SYSTEM   (1)

+#define PATCH_BOOT     (2)

+#define PATCH_TEE      (3)

+#define PATCH_MD1IMG   (4)

+#define PATCH_MD1DSP   (5)

+#define PATCH_VBMETA   (6)

+#define PATCH_OEMAPP   (7)

+#define PATCH_OEMAPP2  (8)

+#define PATCH_MEDMCU   (9)

+#define PATCH_SPM      (10)

+#define PATCH_PROTECT  (11)

+#define PATCH_MCF1     (12)

+#define PATCH_MCF2     (13)

+#define PATCH_MCUPM    (14)

+#define PATCH_SSPM     (15)

+#define PATCH_DPM      (16)

+#define PATCH_PIIMG    (17)

+#define PATCH_HSMOS    (18)

+#define PATCH_BL2      (19)

+#define PATCH_BL33     (20)

+

+#define FULL_SYSTEM    (65)

+#define FULL_BOOT      (66)

+#define FULL_TEE       (67)

+#define FULL_MD1IMG    (68)

+#define FULL_MD1DSP    (69) 

+#define FULL_VBMETA    (70)

+#define FULL_OEMAPP    (71)

+#define FULL_OEMAPP2   (72)

+#define FULL_MEDMCU    (73)

+#define FULL_SPM       (74)

+#define FULL_PROTECT   (75)

+#define FULL_MCF1      (76)

+#define FULL_MCF2      (77)

+#define FULL_MCUPM     (78) 

+#define FULL_SSPM      (79)

+#define FULL_DPM       (80)

+#define FULL_PIIMG     (81)

+#define FULL_HSMOS     (82)

+#define FULL_BL2       (83)

+#define FULL_BL33      (84)

+

+

+

+

+

+

+

+

+#define MAX_OTA_ROLE   (128) 

+#define REAL_OTA_ROLE  (20)

+

+

+

+#define MODE_NORMAL           0

+#define MODE_A2B              1

+#define MODE_B2A              2

+

+#define WAIT            0xff

+#define PASS             0

+#define ERROR           -1

+

+typedef struct {

+	void* user_context;

+	unsigned int rom_base;	// old rom start

+	unsigned char* ram_base;	// ram working buffer start

+	unsigned int ram_len; 		// ram working buffer len

+

+	unsigned int backup_base;	// ram backup storage start

+	unsigned int backup_len; 		// ram backup storage len

+

+	unsigned int update_nvram;	// nvram update flag

+

+	int read_rom_directly;

+	int first_run;

+} IOT_UPDATA_CONTEXT;

+

+

+

+

+typedef struct {

+

+    char fota_flag[32];	    //fota 标志保留 

+    int  update_result;     //升级结果

+	int  ota_run;            //  

+	char cid[32];

+	char did[32];

+} UPDATE_INFO;

+

+

+typedef struct {

+	int  need_update;

+    int  check_delta;

+    int  check_rom;

+	int  update_result;

+	

+} UPDATE_STATUS;

+

+

+typedef struct {

+	int  ota_run;

+    UPDATE_STATUS  update_status[MAX_OTA_ROLE];

+	int  update_result;

+	int  switch_slot;

+	

+} OTA_STATUS;

+

+

+

+

+

+//#define DELTA_HEARD_SIZE	(4*5)

+

+//#define DELTA_HEARD_SIZE	    (4*11 + 4*11)

+#define DELTA_HEARD_SIZE	    512

+#define DELTA_FULL_HEARD_SIZE   8

+

+

+

+int iot_patch(IOT_UPDATA_CONTEXT* update_ctx);

+int lynq_read_process(void);

+unsigned int iot_hash(unsigned char *buf,unsigned int len, unsigned int* value);

+int lynq_md5_file_verfy(char* filePath, char* file_md5);

+//xf.li@20230822 add for ab recover start

+int lynq_md5_file_verfy_ab(char* filePath, char* file_md5);

+int calculate_file_md5_value(char* filePath, unsigned char buffer_out[]);

+int lynq_md5_two_file_verfy(char* filePath_1, char* filePath_2);

+//xf.li@20230822 add for ab recover end

+//int md5_file_verfy_new(char* filePath, char* file_md5,int packe_len);

+int lynq_rock_main(int first_run);

+int lynq_fota_func(void);

+int lynq_nand_open(const char *pathname, int flags);

+ssize_t lynq_nand_read(int fd, void *buf, size_t count);

+ssize_t lynq_nand_write(int fd, void *buf, size_t count);

+int lynq_nand_close(int fd);

+int lynq_get_upgrade_status(void);

+void lynq_reboot_device(void);

+int lynq_fota_nrestart(void);

+int lynq_fota_set_addr_value(char *value,int size);

+int lynq_fota_get_addr_value(char *tmp);

+#endif

+

+

+

diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/iot_rock_ipl.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/iot_rock_ipl.h
new file mode 100755
index 0000000..77c7c2a
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/iot_rock_ipl.h
@@ -0,0 +1,22 @@
+#ifndef _IOT_ROCK_IPL_H_

+#define _IOT_ROCK_IPL_H_

+

+void rock_trace(void* ctx, const char* fmt, ...);

+void rock_progress(void* ctx, int percent);

+int rock_read_block(void* ctx, unsigned char* dest, unsigned int start, unsigned int size);

+int rock_read_delta(void* ctx, unsigned char* dest, unsigned int offset, unsigned int size);

+int rock_write_block(void* ctx, unsigned char* src, unsigned int start, unsigned int size);

+int rock_process_block(void* ctx, unsigned char* data, unsigned int start, unsigned int size);

+int rock_get_blocksize(void* ctx);

+

+int rock_read_file(void* ctx,  void* name, unsigned char* dest, unsigned int offset, unsigned int size);

+int rock_write_file(void* ctx,  void* name, unsigned char* src, unsigned int offset, unsigned int size);

+

+int rock_delete_file(void* ctx, void* name);

+

+int rock_fatal(void* ctx, int error_code);

+

+int rock_mismatch(void* ctx, unsigned char* buf, unsigned int start, unsigned int size, 

+							unsigned int source_hash,unsigned int target_hash);

+#endif

+

diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/md5.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/md5.h
new file mode 100755
index 0000000..f0e3a1b
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/md5.h
@@ -0,0 +1,48 @@
+#ifndef MD5_H
+#define MD5_H
+
+typedef struct
+{
+	unsigned int count[2];
+	unsigned int state[4];
+	unsigned char buffer[64];   
+}MD5_CTX;
+
+
+#define F(x,y,z) ((x & y) | (~x & z))
+#define G(x,y,z) ((x & z) | (y & ~z))
+#define H(x,y,z) (x^y^z)
+#define I(x,y,z) (y ^ (x | ~z))
+#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
+#define FF(a,b,c,d,x,s,ac) \
+{ \
+	a += F(b,c,d) + x + ac; \
+	a = ROTATE_LEFT(a,s); \
+	a += b; \
+}
+#define GG(a,b,c,d,x,s,ac) \
+{ \
+	a += G(b,c,d) + x + ac; \
+	a = ROTATE_LEFT(a,s); \
+	a += b; \
+}
+#define HH(a,b,c,d,x,s,ac) \
+{ \
+	a += H(b,c,d) + x + ac; \
+	a = ROTATE_LEFT(a,s); \
+	a += b; \
+}
+#define II(a,b,c,d,x,s,ac) \
+{ \
+	a += I(b,c,d) + x + ac; \
+	a = ROTATE_LEFT(a,s); \
+	a += b; \
+}                                            
+void MD5Init(MD5_CTX *context);
+void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
+void MD5Final(MD5_CTX *context,unsigned char digest[16]);
+void MD5Transform(unsigned int state[4],unsigned char block[64]);
+void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
+void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
+
+#endif
\ No newline at end of file
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/md5_encode.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/md5_encode.h
new file mode 100755
index 0000000..c3e5d38
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/md5_encode.h
@@ -0,0 +1,33 @@
+#ifndef MD5_ENCODE_H_
+#define MD5_ENCODE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//打开文件
+int ota_file_open(char* path, char* flag);
+//文件偏移位置
+int ota_file_seek(int handle, int offset,  int flag);
+//读文件内容
+int ota_file_read(char* buffer, size_t count, int file);
+//关闭文件
+void ota_file_close(int handle);
+
+
+/*** 
+ * @description:                校验文件的MD5
+ * @param filePath              文件路径
+ * @param file_md5              待校验MD5值
+ * @return  		0:校验成功;  其他:校验失败 
+ */
+int md5_file_verfy(char* filePath, char* file_md5);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/sha.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/sha.h
new file mode 100755
index 0000000..05f9941
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/include/sha.h
@@ -0,0 +1,75 @@
+/* sha.h
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _EMBEDDED_SHA_H_
+#define _EMBEDDED_SHA_H_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SHA_CTX {
+    uint64_t count;
+    uint32_t state[5];
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+    union {
+        uint8_t b[64];
+        uint32_t w[16];
+    } buf;
+#else
+    uint8_t buf[64];
+#endif
+} SHA_CTX;
+
+void SHA_init(SHA_CTX* ctx);
+void SHA_update(SHA_CTX* ctx, const void* data, int len);
+const uint8_t* SHA_final(SHA_CTX* ctx);
+
+/* Convenience method. Returns digest parameter value. */
+const uint8_t* SHA(const void* data, int len, uint8_t* digest);
+
+#define SHA_DIGEST_SIZE 20
+
+typedef enum check_status_t{
+	ERROR_SHA = -3,			// sha1输入参数错误
+	PATCH_ERR = -2,			// 检测hash既不等于source_hash也不等于target_hash, 一般错误情况
+	NOT_EXIST_FILE = -1,	// 检测文件不存在
+	SOURCE_SUCC = 0,		// 检测hash等于目标source_hash, 一般正常情况
+	PATCH_SUCC = 1,			// 检测hash等于目标target_hash, up to data
+}Check_status;
+
+int ParseSha1(const char* str, uint8_t* digest);
+
+const uint8_t* ROCK_SHA(const char *file_name, uint8_t *digest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/lib/libiotpatch.a b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/lib/libiotpatch.a
new file mode 100755
index 0000000..023c16e
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/lib/libiotpatch.a
Binary files differ
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/lib/libmd5.a b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/lib/libmd5.a
new file mode 100755
index 0000000..1cebf1f
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/lib/libmd5.a
Binary files differ
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/makefile b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/makefile
new file mode 100755
index 0000000..1bee260
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/makefile
@@ -0,0 +1,79 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -g -Os \
+                -flto \
+                -fpermissive \
+                -DRIL_SHLIB \
+                -DATCI_PARSE \
+                -DKEEP_ALIVE \
+                -D__LINUX_OS__ \
+                -DECALL_SUPPORT
+
+CFLAGS += -fPIC -O2 $(INCLUDE) -D_LARGEFILE64_SOURCE
+
+$(warning ################# rock ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I./include \
+  -I$(LOCAL_PATH)/../include \
+  -I$(ROOT)$(includedir)/logger \
+  -I$(ROOT)$(includedir)/liblog \
+  -I$(ROOT)$(includedir)/ftp \
+  -I$(ROOT)$(includedir)/glib-2.0 \
+  -I$(ROOT)$(libdir)/glib-2.0/include \
+
+
+
+LOCAL_LIBS := \
+    -L. \
+    -L./lib \
+    -ldl \
+    -lpthread \
+    -llog \
+    -lstdc++ \
+    -liotpatch \
+	-lmd5	\
+    -lnandapi  \
+    -lbootctrl  \
+    -llynq-log \
+    -llynq-protcl \
+    -llynq-uci \
+
+SOURCES = $(wildcard *.c wildcard *.h rock_ua/*.c  MD5/*c)
+
+EXECUTABLE = liblynq-fota-run.so
+
+OBJECTS=$(SOURCES:.c=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.c
+	$(CC) $(LOCAL_C_INCLUDES) $(CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $< 
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/rock_ua/rock_ua.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/rock_ua/rock_ua.c
new file mode 100755
index 0000000..48e9950
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/rock_ua/rock_ua.c
@@ -0,0 +1,2327 @@
+// 2017-07-31 carota Rock FOTA ua porting file
+
+
+#define ROCK_FOTA_SUPPORT
+
+#ifdef ROCK_FOTA_SUPPORT
+
+
+#include "iot_rock.h"
+#include "iot_rock_ipl.h"
+#include "sha.h"
+#include <log/log.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <stdint.h>
+
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+#include <sys/reboot.h>
+
+
+
+#include "liblog/lynq_deflog.h"
+#include "mtk_device_wrap.h"
+#include <include/lynq_uci.h>
+
+#define ROCK_DEFAULT_BLOCK_SIZE 0x40000
+#define ROCK_RAM_LEN  (1024*1024)
+
+#define LOG_TAG "LYNQ_FOTA"
+#define ROCK_BACKUP_LEN ROCK_DEFAULT_BLOCK_SIZE
+
+
+#define FILENAME_SIZE   50
+
+
+char partition_filename_a[][FILENAME_SIZE] = {
+    {"/dev/disk/by-partlabel/system_a"},
+    {"/dev/disk/by-partlabel/boot_a"},
+    {"/dev/disk/by-partlabel/tee_a"},
+    {"/dev/disk/by-partlabel/md1img_a"},
+    {"/dev/disk/by-partlabel/md1dsp_a"},
+    {"/dev/disk/by-partlabel/vbmeta_a"},
+    {"/dev/disk/by-partlabel/oemapp_a"},
+    {"/dev/disk/by-partlabel/oemapp2_a"},
+    {"/dev/disk/by-partlabel/medmcu_a"},
+    {"/dev/disk/by-partlabel/spm_a"},
+    {"/dev/disk/by-partlabel/protect_a"},
+    {"/dev/disk/by-partlabel/mcf1_a"},
+    {"/dev/disk/by-partlabel/mcf2_a"},
+    {"/dev/disk/by-partlabel/mcupm_a"},
+    {"/dev/disk/by-partlabel/sspm_a"},
+    {"/dev/disk/by-partlabel/dpm_a"},
+    {"/dev/disk/by-partlabel/pi_img_a"},
+    {"/dev/disk/by-partlabel/hsm_os_a"},
+    {"/dev/disk/by-partlabel/bl2_a"},
+    {"/dev/disk/by-partlabel/bl33_a"}
+};
+
+
+char partition_filename_b[][FILENAME_SIZE] = {
+    {"/dev/disk/by-partlabel/system_b"},
+    {"/dev/disk/by-partlabel/boot_b"},
+    {"/dev/disk/by-partlabel/tee_b"},
+    {"/dev/disk/by-partlabel/md1img_b"},
+    {"/dev/disk/by-partlabel/md1dsp_b"},
+    {"/dev/disk/by-partlabel/vbmeta_b"},
+    {"/dev/disk/by-partlabel/oemapp_b"},
+    {"/dev/disk/by-partlabel/oemapp2_b"},
+    {"/dev/disk/by-partlabel/medmcu_b"},
+    {"/dev/disk/by-partlabel/spm_b"},
+    {"/dev/disk/by-partlabel/protect_b"},
+    {"/dev/disk/by-partlabel/mcf1_b"},
+    {"/dev/disk/by-partlabel/mcf2_b"},
+    {"/dev/disk/by-partlabel/mcupm_b"},
+    {"/dev/disk/by-partlabel/sspm_b"},
+    {"/dev/disk/by-partlabel/dpm_b"},
+    {"/dev/disk/by-partlabel/pi_img_b"},
+    {"/dev/disk/by-partlabel/hsm_os_b"},
+    {"/dev/disk/by-partlabel/bl2_b"},
+    {"/dev/disk/by-partlabel/bl33_b"}
+};
+
+
+
+
+char partition_filename[][FILENAME_SIZE] = {
+    {"system"},
+    {"boot"},
+    {"tee"},
+    {"md1img"},
+    {"md1dsp"},
+    {"vbmeta"},
+    {"oemapp"},
+    {"oemapp2"},
+    {"medmcu"},
+    {"spm"},
+    {"protect"},
+    {"mcf1"},
+    {"mcf2"},
+    {"mcupm"},
+    {"sspm"},
+    {"dpm"},
+    {"pi_img"},
+    {"hsm_os"},
+    {"bl2"},
+    {"bl33"}
+};
+//+10 
+
+unsigned int  delta_head[128]={0};  //512/4   128/2=64
+
+#define FOTA_DELTA_MTD "/dev/mtd47"
+#define FOTA_UCI_MODULE "lynq_fota"
+#define FOTA_UCI_FILE "lynq_uci"
+#define FOTA_UCI_ADDR "lynq_fota_addr"
+#define FOTA_UCI_STATE "lynq_fota_state"
+
+#define FILE_UPDATE_STATE  "/data/.update_status"
+#define FILE_UPDATE_FLAG   "/tmp/update_flag"
+#define FILE_FOTA_STATE    "/data/.fota_status"
+
+#define NAND_PAGE_SIZE  4096
+
+
+#define BOOTDEV_TYPE_NAND 1
+
+#define BACKUP_ADDR_FLAG    0xffffffff
+#define FILE_BACKUP      "/data/.backup"
+
+#define SLOT_A    0
+#define SLOT_B    1
+
+#define FULL_HEAD "full-ota"
+
+//xf.li@20230822 add for ab rollback start
+#define DEV_SYSTEM_A    "/dev/disk/by-partlabel/system_a"
+#define DEV_SYSTEM_B    "/dev/disk/by-partlabel/system_b"
+
+#define DEV_BOOT_A      "/dev/disk/by-partlabel/boot_a"
+#define DEV_BOOT_B      "/dev/disk/by-partlabel/boot_b"
+
+#define DEV_SPM_A      "/dev/disk/by-partlabel/spm_a"
+#define DEV_SPM_B      "/dev/disk/by-partlabel/spm_b"
+
+#define DEV_MD1IMG_A    "/dev/disk/by-partlabel/md1img_a"
+#define DEV_MD1IMG_B    "/dev/disk/by-partlabel/md1img_b"
+
+#define DEV_TEE_A       "/dev/disk/by-partlabel/tee_a"
+#define DEV_TEE_B       "/dev/disk/by-partlabel/tee_b" 
+
+#define DEV_VBMETA_A       "/dev/disk/by-partlabel/vbmeta_a"
+#define DEV_VBMETA_B       "/dev/disk/by-partlabel/vbmeta_b"
+
+#define DEV_BL2_A         "/dev/disk/by-partlabel/bl2_a"
+#define DEV_BL2_B         "/dev/disk/by-partlabel/bl2_b"
+
+#define DEV_BL33_A        "/dev/disk/by-partlabel/bl33_a"
+#define DEV_BL33_B        "/dev/disk/by-partlabel/bl33_b"
+
+#define DEV_MEDMCU_A        "/dev/disk/by-partlabel/medmcu_a"
+#define DEV_MEDMCU_B        "/dev/disk/by-partlabel/medmcu_b"
+
+#define DEV_OEMAPP_A        "/dev/disk/by-partlabel/oemapp_a"
+#define DEV_OEMAPP_B        "/dev/disk/by-partlabel/oemapp_b"
+
+#define DEV_OEMAPP2_A        "/dev/disk/by-partlabel/oemapp2_a"
+#define DEV_OEMAPP2_B        "/dev/disk/by-partlabel/oemapp2_b"
+
+
+#define DEV_MISC        "/dev/disk/by-partlabel/misc"
+
+#define BACKUP_UBI_NUM  31 //max ubi number
+#define MTD_SYSTEM_A 14
+#define MTD_SYSTEM_B 15
+#define MD5_RETRY_TIME 3
+#define MD5_VERFY_ERROR 5
+#define MD5_READ_BUFFER_LEN 4*1024
+#define FOTA_FIRST 0
+#define RECOVER_FIRST 1
+int fota_interrupt = 1;
+//xf.li@20230822 add for ab rollback end
+
+
+//int fd_system_a,fd_system_b,fd_boot_a,fd_boot_b,fd_tee_a,fd_tee_b,fd_bl2,fd_bl33,fd_delta,fd_curr,fd_log,fd_update_status,fd_md1img_a,fd_md1img_b,fd_fota_status,fd_md1dsp_a,fd_md1dsp_b,fd_vbmeta_a,fd_vbmeta_b,fd_oemapp_a,fd_oemapp_b,fd_oemapp2_a,fd_oemapp2_b,fd_medmcu_a,fd_medmcu_b,fd_bl33_a,fd_bl33_b;
+int fd_delta,fd_curr,fd_log,fd_update_status,fd_fota_status;
+int fd_write,fd_read;
+
+static unsigned int  delta_offset = 0;
+static unsigned int  now_patch = 0;
+unsigned int  current_slot = 0;
+unsigned char rock_debug_buffer[512];
+char g_delta_mtd[16];
+int g_addr_flag = 0;
+
+
+OTA_STATUS  fota_status;
+UPDATE_INFO up_info;
+
+
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+boot_control_module_t* module;
+
+static void lynq_init_wake_lock_func(void);
+static void lynq_fota_grab_artial_wake_lock(void);
+static void lynq_fota_release_wake_lock(void);
+int check(int sys_size);
+int check_cpu();
+
+static const char hex_chars[] = "0123456789abcdef";
+
+/**
+ * @brief The following is the wake up
+ * start
+ */
+
+#define ANDROID_WAKE_LOCK_NAME "fota-interface"
+
+void *dlHandle_wakelock;
+
+enum {
+    PARTIAL_WAKE_LOCK = 1,  // the cpu stays on, but the screen is off
+    FULL_WAKE_LOCK = 2      // the screen is also on
+};
+
+// while you have a lock held, the device will stay on at least at the
+// level you request.
+
+int (*acquire_wake_lock)(int lock, const char* id);
+int (*release_wake_lock)(const char* id);
+
+void convert_hex(unsigned char *sha, unsigned char *shastr)
+{
+    int i;
+    int j = 0;
+    unsigned int c;
+
+    for (i = 0; i < 20; i++) {
+        c = (sha[i] >> 4) & 0x0f;
+        shastr[j++] = hex_chars[c];
+        shastr[j++] = hex_chars[sha[i] & 0x0f];
+    }
+    shastr[40] = '\0';
+}  
+
+
+
+
+int rock_mismatch(void* ctx, unsigned char* buf, unsigned int start, unsigned int size, 
+                            unsigned int source_hash,unsigned int target_hash) {
+
+      return 0;
+}
+                            
+int rock_fatal(void* ctx, int error_code) {
+    return 0;
+}
+
+void rock_trace(void* ctx, const char* fmt, ...) {
+
+    va_list     ap;
+    memset(rock_debug_buffer,0x0,sizeof(rock_debug_buffer));
+    va_start (ap, fmt);
+
+    
+    vsnprintf(rock_debug_buffer,sizeof(rock_debug_buffer),fmt,ap);
+    LYDBGLOG("+[UA]: %s",rock_debug_buffer);
+    
+
+    va_end (ap);
+
+}
+
+static int save_fota_status()
+{
+    int err;
+    fd_fota_status = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777);
+
+    if (fd_fota_status < 0) {
+        err = errno;
+        RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+
+    write(fd_fota_status, &fota_status,sizeof(fota_status));
+    sync();
+    close(fd_fota_status);
+}
+
+int lynq_read_process(void)
+{
+    int err;
+    fd_fota_status = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777);
+
+    if (fd_fota_status < 0) {
+        err = errno;
+        RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+    memset(&fota_status, 0 , sizeof(fota_status));
+    read(fd_fota_status, &fota_status,sizeof(fota_status));
+    sync();
+    close(fd_fota_status);
+    return fota_status.ota_run;
+}
+
+static int save_fota_info()
+{
+    int err;
+    fd_update_status = open(FILE_UPDATE_STATE,O_RDWR);
+
+    if (fd_update_status < 0) {
+        err = errno;
+        RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+
+    write(fd_update_status, &up_info, sizeof(fota_status));
+    sync();
+    close(fd_update_status);
+}
+
+
+
+void rock_progress(void* ctx, int percent) {
+    int i = 0;
+    static int tmp_percent = -1;
+    rock_trace(ctx, "rock update progress %d\n", percent);
+
+    if (tmp_percent != percent) {
+        tmp_percent = percent;
+        if (percent > 20) {
+            i = fota_status.ota_run;
+            if (fota_status.update_status[i-1].check_delta != PASS) {
+                fota_status.update_status[i-1].check_delta = PASS;
+                fota_status.update_status[i-1].check_rom= PASS;
+                save_fota_status();
+            }
+        }
+    }
+}
+
+int rock_process_block(void* ctx, unsigned char* data, unsigned int start, unsigned int size){
+
+    int writen = 0;
+    int ret,err;
+
+    if (start == BACKUP_ADDR_FLAG) {
+        int fd_backup = open(FILE_BACKUP,O_RDWR | O_CREAT,0777);
+        while (writen < size) {
+            write(fd_backup,data,ROCK_DEFAULT_BLOCK_SIZE);
+            sync();
+            writen += ROCK_DEFAULT_BLOCK_SIZE;
+        }
+        close(fd_backup);
+        return size;
+    }
+
+    writen = 0;
+   
+    if (mtk_device_wrap_seek(fd_write, start, SEEK_SET) < 0) {
+        err = errno;
+        rock_trace(ctx, "mtk_device_wrap_seek write\n");
+        return err;
+    }
+
+    while (writen < size) {
+        ret = mtk_device_wrap_write(fd_write,data+writen, ROCK_DEFAULT_BLOCK_SIZE);
+        writen += ROCK_DEFAULT_BLOCK_SIZE;
+    }       
+    
+    
+    return size;
+}
+
+int rock_write_block(void* ctx, unsigned char* src, unsigned int start, unsigned int size){
+
+#if 0
+
+    int writen = 0;
+    int ret,err;
+    
+    
+    if (start == BACKUP_ADDR_FLAG) {
+        int fd_backup = open(FILE_BACKUP,O_RDWR | O_CREAT,0777);
+        while (writen < size) {
+            write(fd_backup,src,ROCK_DEFAULT_BLOCK_SIZE);
+            sync();
+            writen += ROCK_DEFAULT_BLOCK_SIZE;
+        }
+        close(fd_backup);
+        return size;
+    }
+    
+    writen = 0;
+   
+    if (mtk_device_wrap_seek(fd_curr, start, SEEK_SET) < 0) {
+        err = errno;
+        rock_trace(ctx, "mtk_device_wrap_seek write\n");
+        return err;
+    } 
+
+    while (writen < size) {
+        ret = mtk_device_wrap_write(fd_curr,src+writen, ROCK_DEFAULT_BLOCK_SIZE);
+        writen += ROCK_DEFAULT_BLOCK_SIZE;
+    }    
+    
+
+#endif
+
+    return size;
+
+}
+
+int rock_read_block(void* ctx, unsigned char* dest, unsigned int start, unsigned int size){
+
+
+    int ret,err;
+    
+
+    if (start == BACKUP_ADDR_FLAG) {
+        int fd_backup = open(FILE_BACKUP,O_RDONLY);
+        read(fd_backup,dest,size);
+        sync();
+        close(fd_backup);
+        return size;
+    }
+    
+
+
+    if (mtk_device_wrap_seek(fd_read, start, SEEK_SET) < 0) {
+        err = errno;
+        rock_trace(ctx, "mtk_device_wrap_seek read block err\n");
+    }
+
+    do {
+
+        ret = mtk_device_wrap_read(fd_read, dest, size);
+
+        if (ret == 0) {
+            break;
+        } else if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            err = -errno;
+            rock_trace(ctx,"%s Error reading metadata file\n");
+
+            mtk_device_wrap_close(fd_read);
+
+            return err;
+        }
+        size -= ret;
+        dest += ret;
+    } while(size > 0);
+
+
+    return ret;
+   
+    
+}
+
+
+int rock_read_delta(void* ctx, unsigned char* dest, unsigned int offset, unsigned int size){
+
+    int ret = 0,err = 0;
+
+    if(g_addr_flag == 1)
+    {
+        if (mtk_device_wrap_seek(fd_delta, offset + delta_offset, SEEK_SET) < 0) {
+            err = -errno;
+            rock_trace(ctx, "mtk_device_wrap_seek df_delta err\n");
+            return err;
+        }
+
+        do {
+
+            ret = mtk_device_wrap_read(fd_delta, dest, size);
+
+            if (ret == 0)
+            {
+                break;
+            }
+            else if (ret < 0)
+            {
+                if (errno == EINTR)
+                {
+                    continue;
+                }
+                err = -errno;
+                rock_trace(ctx," Error reading metadata file\n");
+                mtk_device_wrap_close(fd_delta);
+                return err;
+            }
+            size -= ret;
+            dest += ret;
+        } while(size > 0);
+    }
+    else
+    {
+        if (lseek(fd_delta, offset + delta_offset, SEEK_SET) < 0)
+        {
+            err = -errno;
+            rock_trace(ctx, "mtk_device_wrap_seek df_delta err\n");
+            return err;
+        }
+        do {
+            ret = read(fd_delta, dest, size);
+            if (ret == 0)
+            {
+                break;
+            }
+            else if (ret < 0)
+            {
+                if (errno == EINTR)
+                {
+                    continue;
+                }
+                err = -errno;
+                rock_trace(ctx," Error reading metadata file\n");
+                close(fd_delta);
+                return err;
+            }
+            size -= ret;
+            dest += ret;
+        } while(size > 0);
+    }
+
+    return ret;
+
+}
+
+int rock_get_blocksize(void* ctx) {
+    return ROCK_DEFAULT_BLOCK_SIZE;
+}
+
+int rock_read_file(void* ctx,  void* name, unsigned char* dest, unsigned int offset, unsigned int size){return 0;}
+int rock_write_file(void* ctx,  void* name, unsigned char* src, unsigned int offset, unsigned int size){return 0;}
+int rock_delete_file(void* ctx, void* name){return 0;}
+/* ROCK IPL end */
+
+void delete_enter(char data[])
+{
+    char *find = strchr(data, ':');
+    if(find)
+        *find = '\0';
+    return ;
+}
+/*
+int get_delta_mtd(char *delta_mtd)
+{
+    FILE *fp;
+    char mtd_buffer[16] = {0};
+    fp = popen("cat /proc/mtd|grep delta|awk '{print $1}'","r");
+    if(fp == NULL)
+    {
+        RLOGD("get_delta_mtd popen fail\n");
+        return -1;
+    }
+    fgets(mtd_buffer, sizeof(mtd_buffer), fp);
+    if(strlen(mtd_buffer) == 0)
+    {
+        RLOGD("get delta mtd fail\n");
+        pclose(fp);
+        return -1;
+    }
+    delete_enter(mtd_buffer);
+    sprintf(delta_mtd,"/dev/%s", mtd_buffer);
+    RLOGD("delta_mtd:%s\n", delta_mtd);
+    pclose(fp);
+    return 0;
+}
+*/
+
+int get_file_size(void)
+{
+    FILE *stream;
+    stream = fopen("/tmp/fota.delta", "r");
+    long file_size = -1;
+    long cur_offset = ftell(stream);
+    if (cur_offset == -1)
+    {
+        printf("ftell failed :%s\n", strerror(errno));
+        return -1;
+    }
+    if (fseek(stream, 0, SEEK_END) != 0)
+    {
+        printf("fseek failed: %s\n", strerror(errno));
+        return -1;
+    }
+    file_size = ftell(stream);
+    if (file_size == -1)
+    {
+        printf("ftell failed :%s\n", strerror(errno));
+    }
+    if (fseek(stream, cur_offset, SEEK_SET) != 0)
+    {
+        printf("fseek failed: %s\n", strerror(errno));
+        return -1;
+    }
+    fclose(stream);
+    if(file_size >52428800)
+    {
+        return -1;
+    }
+    return 0;
+}
+
+static int init_dev_fd()
+{
+
+    int err;
+    int ret;
+    int result;
+    char lynq_fota_addr[64] = {0};
+    char fota_name[]= "fota.delta";
+    int n;
+    if(0 != lynq_fota_get_addr_value(lynq_fota_addr))
+    {
+        return E_ROCK_FOTA_ADDR;
+    }
+    RLOGD("+[UA]: get fota pack addr: %s\n",lynq_fota_addr);
+
+
+    if(!(strcmp(lynq_fota_addr, "/tmp/fota.delta")))
+    {
+        ret = get_file_size();
+        if(ret != 0)
+        {
+            RLOGE("the delta size over 50M\n");
+            return -1;
+        }
+
+        strcpy(g_delta_mtd, FOTA_DELTA_MTD);
+        result = test_write_delta(lynq_fota_addr, g_delta_mtd);
+        if(result != 0)
+        {
+            RLOGE("fota.delta write into mtd fail !\n");
+        }
+        strcpy(lynq_fota_addr, g_delta_mtd);
+        if(lynq_fota_set_addr_value(lynq_fota_addr,strlen(lynq_fota_addr)))
+        {
+            RLOGE("set addr fail\n");
+            return 1;
+        }
+        RLOGD("+[UA]: get fota pack addr: %s\n", lynq_fota_addr);
+        fd_delta = mtk_device_wrap_open(lynq_fota_addr,O_RDWR);
+
+        if (fd_delta < 0) {
+            err = errno;
+            RLOGE("+[UA]: Error opening fota file: %s\n",strerror(errno));
+            mtk_device_wrap_close(fd_delta);
+            return -err;
+        }
+        g_addr_flag = 1;
+
+    }
+    else if(!(strcmp(lynq_fota_addr, g_delta_mtd)))
+    {
+        fd_delta = mtk_device_wrap_open(lynq_fota_addr,O_RDWR);
+
+        if (fd_delta < 0) {
+            err = errno;
+            RLOGE("+[UA]: Error opening fota file: %s\n",strerror(errno));
+            mtk_device_wrap_close(fd_delta);
+            return -err;
+        }
+        g_addr_flag = 1;
+    }
+    else
+    {
+        fd_delta = open(lynq_fota_addr,O_RDWR);
+
+        if (fd_delta < 0) {
+            err = errno;
+            RLOGE("+[UA]: Error opening fota file: %s\n",strerror(errno));
+            close(fd_delta);
+            return -err;
+        }
+        g_addr_flag = 0;
+
+    }
+
+    fd_update_status = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777);
+    if (fd_update_status < 0) {
+        err = errno;
+        RLOGE("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+        close(fd_update_status);
+        return -err;
+    }
+    memset(&up_info, 0, sizeof(up_info));
+    lseek(fd_update_status,0,SEEK_SET);
+    read(fd_update_status,(unsigned char *)&up_info,sizeof(up_info));
+    close(fd_update_status);
+    return 0;
+}
+
+
+
+
+
+static int close_dev_fd(int fd)
+{
+    close(fd);
+}
+
+
+
+static int reboot_device() {
+    
+  reboot(RB_AUTOBOOT);
+  
+  while (1) pause();
+}
+
+
+
+int test_write_delta(char *source, char *target)
+{
+    int fd_source,fd_target,size;
+    char buf[32];
+    char delta_data[ROCK_DEFAULT_BLOCK_SIZE];
+    char lynq_fota_addr[64];
+    fd_source = open(source,O_RDONLY);
+
+    if (fd_source < 0) {
+        RLOGE("+[UA]: open source  error\n");
+        return 1;
+    }
+
+    fd_target = mtk_device_wrap_open(target,O_RDWR);
+
+    if (fd_target < 0) {
+        mtk_device_wrap_close(fd_target);
+        close(fd_source);
+        RLOGE("+[UA]: open target  error\n");
+        return 1;
+    } 
+
+    if(!(strcmp(lynq_fota_addr, g_delta_mtd)))
+    {
+        sprintf(buf,"flash_eraseall %s", g_delta_mtd);
+        system(buf);
+    }
+    while(( size = read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0) {
+           mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE);
+    }
+    
+    mtk_device_wrap_close(fd_target);
+    close(fd_source);
+    return 0;
+}
+
+
+int nand_copyto_nand(char *source, char *target)
+{
+    int fd_source,fd_target,size;
+
+    char delta_data[ROCK_DEFAULT_BLOCK_SIZE];
+     
+    fd_source = mtk_device_wrap_open(source,O_RDONLY);
+     
+    if (fd_source < 0) {
+        RLOGE("+[UA]: open source  error\n");
+        return 1;
+    }
+
+    fd_target = mtk_device_wrap_open(target,O_RDWR);
+ 
+    if (fd_target < 0) {
+        mtk_device_wrap_close(fd_target);
+        mtk_device_wrap_close(fd_source);
+        RLOGE("+[UA]: open target  error\n");
+        return 1;
+    } 
+    
+    while(( size = mtk_device_wrap_read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0) {
+           mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE);
+    }
+    
+    mtk_device_wrap_close(fd_target);
+    mtk_device_wrap_close(fd_source);
+    return 0;
+}
+
+int delta_copyto_nand(unsigned int start,int size)
+{
+ 
+    char delta_data[NAND_PAGE_SIZE];
+    unsigned int ret = 0;
+    int err;
+
+
+    if(g_addr_flag == 1)
+    {
+        if (mtk_device_wrap_seek(fd_delta, start, SEEK_SET) < 0)
+        {
+            LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+            return -1;
+        }
+
+        if (mtk_device_wrap_seek(fd_curr, 0, SEEK_SET) < 0)
+        {
+            LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+            return -1;
+        }
+
+        do {
+            memset(delta_data,0,NAND_PAGE_SIZE);
+            ret = mtk_device_wrap_read(fd_delta, delta_data, NAND_PAGE_SIZE);
+
+            if (ret == 0)
+            {
+                break;
+            }
+            else if (ret < 0)
+            {
+                if (errno == EINTR)
+                {
+                    continue;
+                }
+                err = -errno;
+                return err;
+            }
+            size -= NAND_PAGE_SIZE;
+            mtk_device_wrap_write(fd_curr,delta_data,NAND_PAGE_SIZE);
+            //mtk_device_wrap_write(fd_curr,delta_data,ret);
+        } while(size > 0);
+
+    }
+    else
+    {
+        if (lseek(fd_delta, start, SEEK_SET) < 0) {
+            LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+            return -1;
+        }
+
+        if (mtk_device_wrap_seek(fd_curr, 0, SEEK_SET) < 0) {
+            LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+            return -1;
+        }
+
+        do {
+            memset(delta_data,0,NAND_PAGE_SIZE);
+            ret = read(fd_delta, delta_data, NAND_PAGE_SIZE);
+
+            if (ret == 0)
+            {
+                break;
+            }
+            else if (ret < 0)
+            {
+                if (errno == EINTR)
+                {
+                    continue;
+                }
+                err = -errno;
+                return err;
+            }
+            size -= NAND_PAGE_SIZE;
+            mtk_device_wrap_write(fd_curr,delta_data,NAND_PAGE_SIZE);
+            //mtk_device_wrap_write(fd_curr,delta_data,ret);
+
+        } while(size > 0);
+    }
+
+    return 0;
+}
+
+
+unsigned char ram_buffer[ROCK_RAM_LEN];
+
+int check(int sys_size)
+{
+    int fd;
+    int i=0;
+    int j=0;
+    int num=i;
+    int n = 0;
+    const uint8_t data[] = { 0x74, 0x77, 0x6f, 0x63, 0x6f, 0x72, 0x65};
+    const char * core_flag="twocore\n";
+    
+    uint8_t buffer[16]; 
+
+    if(sys_size == 0)//for only upgrade oemapp and oemapp2
+    {
+        return 0;
+    }
+    n = strlen(core_flag);
+    lseek(fd_delta,520,SEEK_SET);
+    lseek(fd_delta,sys_size,SEEK_CUR);
+    lseek(fd_delta, -1*n, SEEK_CUR);
+    read(fd_delta, buffer, n);
+    lseek(fd_delta,0,SEEK_SET);//file reset
+    if (memcmp(buffer, core_flag, n) == 0)
+    {
+        return 0;
+    }
+    return -1;
+
+}
+
+int check_cpu(void)
+{
+    int i=0;
+    int ret;
+    char buffer[3][64];
+    FILE *fp;
+    char num;
+    fp = popen("od -x /proc/device-tree/chosen/atag,devinfo","r");
+
+    for(i=0;i<3;i++)
+    {
+        fgets(buffer[i], 64, fp);
+    }
+
+    for(i=0;i<3;i++)
+    {
+        RLOGD("buffer[i] = %s\n",buffer[i]);
+    }
+    RLOGD("%c\n", buffer[2][14]);
+
+    num = buffer[2][14];
+
+
+    RLOGE("num=%c\n", num);
+    if(num == '0' || num == '1')
+    {
+        printf("this is four core\n");
+        return 4;
+    }
+    else if(num == '2' || num == '3')
+    {
+        printf("this is two core\n");
+        return 2;
+    }
+    else
+    {
+        RLOGE("this char is error\n");
+        return -1;
+    }
+    pclose(fp);
+
+    return -1;
+}
+
+
+
+static int rock_update_main(unsigned int rom_base,  unsigned int backup_base, unsigned int backup_len, int read_rom_directly, int first_run, int switch_slot_flag, int 
+reboot_flag, int backup_mode) {
+    int status,err,start,fd;
+    int ret = 0;
+    int i = 0;
+    int retry_cnt = 0;
+    int cpu_flag;
+    IOT_UPDATA_CONTEXT ctx;
+
+    //OTA_STATUS  fota_status;
+
+
+    const hw_module_t* hw_module;
+    unsigned int  slot;
+
+    unsigned int  update_mode = MODE_NORMAL;
+    unsigned int  delta_size;
+    unsigned char full_header[9];
+    
+    char digest_s[SHA_DIGEST_SIZE];
+    char digest_t[SHA_DIGEST_SIZE];
+    char str_sha[40];
+    char cmd_sys[100];
+    int core_num;
+    int sha_size = 0;
+    int is_need_fullupdate = 0;
+    int fd_partition_a,fd_partition_b;
+//xf.li@20230830 add for ab_recover start
+    fd = open(FILE_UPDATE_FLAG,O_RDWR | O_CREAT,0777);
+    if (fd < 0)
+    {
+        RLOGE("+[UA]: can't open file /tmp/update_flag.\n");
+        return -1;
+    }
+    close(fd);
+//xf.li@20230830 add for ab_recover end
+    memset(&fota_status,0,sizeof(fota_status));
+    fota_status.ota_run = 1;
+    save_fota_status();
+
+    hw_module = &HAL_MODULE_INFO_SYM;
+
+    if (!hw_module ||
+        strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+        ret = -EINVAL;
+    }
+    if (ret != 0) {
+        RLOGE("+[UA]: Error loading boot_control HAL implementation.\n");
+        return -1;
+    }
+
+    module = (boot_control_module_t*)hw_module;
+    module->init(module);
+
+
+    if (module == NULL) {
+        RLOGE("+[UA]: Error getting bootctrl module.\n");
+        return  -1;
+    }
+
+    lynq_init_wake_lock_func();
+    lynq_fota_grab_artial_wake_lock();
+     /*************    Bootctrl Init  End  *************/
+
+    current_slot = module->getCurrentSlot(module);
+    
+    int is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+  
+    RLOGE("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
+    if((current_slot != 0)&&(current_slot != 1))
+    {
+        RLOGE("+[UA]: Error getting bootctrl current_slot.\n");
+        return -1;
+    }
+
+    memset(&ctx, 0, sizeof(ctx));
+    ctx.rom_base = 0;
+    ctx.ram_base =(unsigned char *)&ram_buffer[0];
+    ctx.ram_len = ROCK_RAM_LEN;
+    ctx.backup_base = BACKUP_ADDR_FLAG;
+    //ctx.backup_len = ROCK_DEFAULT_BLOCK_SIZE;
+    ctx.backup_len = 0;
+    ctx.update_nvram = 0;
+    ctx.read_rom_directly = read_rom_directly;
+    //ctx.first_run = first_run;
+    ctx.first_run = 1;
+
+    if(0 != init_dev_fd())
+    {
+        RLOGE("+[UA]: get fota addr error\n");
+        system("echo fota-interface >/sys/power/wake_unlock");
+        return E_ROCK_FOTA_ADDR;
+    }
+
+    RLOGE("+[UA]: up_info.ota_run = %d\n",up_info.ota_run);
+
+#if 0
+    if ((up_info.ota_run>PATCH_BL33)||(up_info.ota_run<PATCH_SYSTEM))
+    {
+        up_info.ota_run = 0;
+    }    
+#endif 
+    up_info.ota_run = 0;
+    if(backup_mode == 1)
+    {
+        if(current_slot == 0)
+        {
+            update_mode = MODE_A2B;
+        }else
+        {
+            update_mode = MODE_B2A;
+        }
+    }
+    else
+    {
+        update_mode = MODE_NORMAL;
+    }
+    
+    RLOGE("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag);
+    RLOGE("+[UA]: update_mode = %d\n",update_mode);
+
+    memset(&delta_head, 0, sizeof(delta_head));
+    if(g_addr_flag == 1)
+    {
+        RLOGD("fd_delta=%d\n", fd_delta);
+        ret = mtk_device_wrap_read(fd_delta, (char *)&delta_head[0], sizeof(delta_head));
+        if(ret <0)
+        {
+             return -1;
+        }
+    }
+    else
+    {
+        read(fd_delta, (char *)&delta_head[0], sizeof(delta_head));
+    }
+
+
+    delta_size = 0;
+    sha_size = 0;
+    for (i = 0;i<REAL_OTA_ROLE; i++)    {
+        if (delta_head[i] > 0) {
+            fota_status.update_status[i].need_update = 1;
+            delta_size+=delta_head[i];
+        }
+        RLOGE("+[UA]: %s,delta size = %d, i=%d\n",partition_filename[i],delta_head[i], i);
+    }
+
+    for(i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE); i++) {
+        if (delta_head[i] > 0) {
+            fota_status.update_status[i].need_update = 1;
+            sha_size+=delta_head[i];
+        }
+        RLOGE("+[UA]: %s,full size = %d, i=%d\n",partition_filename[i-MAX_OTA_ROLE/2],delta_head[i], i);
+    }
+
+    core_num= check_cpu();
+    if(core_num == 2)
+    {
+        cpu_flag = check(delta_head[64]);
+        if(cpu_flag < 0)
+        {
+            RLOGE("cpu core is error\n");
+            system("echo fota-interface >/sys/power/wake_unlock");
+            return -1;
+        }
+        else
+        {
+            RLOGE("cpu core match\n");
+        }
+    }
+    else if(core_num == 4)
+    {
+        RLOGE("the cpu core is four!!!\n");
+    }
+    else
+    {
+        RLOGE("read the cpu core fail");
+        system("echo fota-interface >/sys/power/wake_unlock");
+        return -1;
+    }
+
+    fota_status.switch_slot = WAIT;
+    save_fota_status();
+
+    is_need_fullupdate = 0;
+    if(sha_size>0) {
+        is_need_fullupdate = 1;
+        sha_size+=8;
+    }
+
+    sha_size+=delta_size;
+    
+    memset(digest_s,0,SHA_DIGEST_SIZE);
+    memset(digest_t,0,SHA_DIGEST_SIZE);
+    memset(str_sha,0,40);
+    if(g_addr_flag == 1)
+    {
+        ret = mtk_device_wrap_seek(fd_delta, sha_size + sizeof(delta_head), SEEK_SET);
+        if(ret < 0)
+        {
+            RLOGE("mtk_device_wrap_seek fail\n");
+            return -1;
+        }
+        ret = mtk_device_wrap_read(fd_delta, digest_s, SHA_DIGEST_SIZE);
+        if(ret < 0)
+        {
+            RLOGE("mtk_device_wrap_read fail\n");
+            return -1;
+        }
+    }
+    else
+    {
+        lseek(fd_delta, sha_size + sizeof(delta_head), SEEK_SET);
+        read(fd_delta, digest_s, SHA_DIGEST_SIZE);
+    }
+
+    convert_hex(digest_s,str_sha);
+    RLOGE("+[UA]: delta save sha = %s\n",str_sha);
+    if(g_addr_flag == 1)
+    {
+        ROCK_SHA_FILE(fd_delta,sizeof(delta_head),sha_size,digest_t);
+    }
+    else
+    {
+        ROCK_SHA_FILE_COMMON(fd_delta,sizeof(delta_head),sha_size,digest_t);
+    }
+    memset(str_sha,0,40);
+    convert_hex(digest_t,str_sha);
+    RLOGE("+[UA]: delta calc sha = %s\n",str_sha);
+    
+    if(memcmp(digest_s,digest_t,SHA_DIGEST_SIZE)==0) {
+
+        RLOGE("sha verify pass\n");
+    
+    }else{
+        RLOGE("delta sha verify fial!\n");
+        
+        system("echo fota-interface >/sys/power/wake_unlock");
+        return -1;
+    }
+
+    memset(digest_s,0,SHA_DIGEST_SIZE);
+    memset(digest_t,0,SHA_DIGEST_SIZE);
+    
+    
+    //delta_offset = DELTA_HEARD_SIZE;
+    delta_offset = sizeof(delta_head);
+    
+    for(i = 0;i<REAL_OTA_ROLE; i++){    //diff
+        //now_patch = i+1;
+        if (i>0) {
+            delta_offset+=delta_head[i-1];
+        }
+        if((delta_head[i]>0) && (up_info.ota_run<=(i+1))){ 
+                        now_patch = i + 1;
+#if 0
+            if (up_info.ota_run == now_patch) //升级ps断电?
+            {
+                ctx.first_run = 0;
+
+            }else{
+                ctx.first_run = 1;
+            }
+#endif             
+            ctx.first_run = 1;  //always
+            RLOGD("+[UA]: PATCH %s,ctx.first_run = %d\n", partition_filename[i] ,ctx.first_run);
+            up_info.ota_run = now_patch;
+        
+            if(current_slot==SLOT_B) {
+                sprintf(cmd_sys,"flash_eraseall %s",partition_filename_a[i]);
+            }else{
+                sprintf(cmd_sys,"flash_eraseall %s",partition_filename_b[i]);
+            }
+            system(cmd_sys);
+
+
+            fd_partition_a = mtk_device_wrap_open(partition_filename_a[i],O_RDWR);
+            if (fd_partition_a < 0) {
+                err = errno;
+                RLOGE("+[UA]: Error opening id_a[%d] file: %s\n",i,strerror(errno));
+                system("echo fota-interface >/sys/power/wake_unlock");
+                return -err;
+            }
+
+            fd_partition_b = mtk_device_wrap_open(partition_filename_b[i],O_RDWR);
+            if (fd_partition_b < 0) {
+                err = errno;
+                RLOGE("+[UA]: Error opening id_b[%d] file: %s\n",i,strerror(errno));
+                system("echo fota-interface >/sys/power/wake_unlock");
+                return -err;
+            }            
+            if(current_slot==SLOT_B){
+                fd_read  = fd_partition_b;
+                fd_write = fd_partition_a;
+            } else {
+                fd_read  = fd_partition_a;
+                fd_write = fd_partition_b;
+            }
+
+            fota_status.ota_run = i+1;
+            fota_status.update_status[i].check_delta = WAIT;
+            fota_status.update_status[i].check_rom = WAIT;
+            fota_status.update_status[i].update_result= WAIT;
+
+            save_fota_status();
+
+            up_info.ota_run = i+1;
+            save_fota_info();
+
+            RLOGE("+[UA]: Start upgrading %s.\n",partition_filename[i]);
+            status = iot_patch(&ctx);
+            RLOGE("+[UA]: %s upgrade result:%d\n",partition_filename[i],status);
+        
+            //up_info.ota_run = 0;
+        
+            //fota_status.ota_run = 0;
+            fota_status.update_status[i].update_result= status; 
+            fota_status.update_result= status;
+
+            if((status == 0)||(status ==1))
+            {
+
+                fota_status.update_status[i].check_delta = PASS;
+                fota_status.update_status[i].check_rom = PASS;
+                RLOGE("+[UA]: %s upgrade success!!!\n",partition_filename[i]);
+               
+            }else if(status == E_ROCK_INVALID_DELTA) {
+                fota_status.update_status[i].check_delta = ERROR;
+                fota_status.update_status[i].check_rom = WAIT;
+            }else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+                fota_status.update_status[i].check_delta = PASS;
+                fota_status.update_status[i].check_rom = ERROR;
+
+            }else{
+        
+            //fota_status.update_status[PATCH_SYSTEM -1].check_delta = PASS;
+            //fota_status.update_status[PATCH_SYSTEM -1].check_rom = WAIT;
+            }
+
+            save_fota_status();
+
+        
+            if ((status != 0) &&(status != 1))
+            {
+
+                up_info.fota_flag[0] = 'e';
+                up_info.fota_flag[1] = 'n';
+                up_info.fota_flag[2] = 'd';
+                up_info.update_result = status;
+                up_info.ota_run = 0;
+                save_fota_info();
+            
+                mtk_device_wrap_close(fd_read);
+                mtk_device_wrap_close(fd_write);
+    
+                system("echo fota-interface >/sys/power/wake_unlock");
+                return status;
+            }
+                mtk_device_wrap_close(fd_read);
+                mtk_device_wrap_close(fd_write);
+        
+        }
+    
+    }
+    
+    
+    
+    if (is_need_fullupdate == 1)
+    {
+
+        now_patch = 0;
+        up_info.ota_run = 0;
+
+        fota_status.switch_slot = WAIT;
+        save_fota_status();
+        
+        if (g_addr_flag == 1)
+        {
+            if (mtk_device_wrap_seek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0)
+            {
+                err = errno;
+                RLOGE("+[UA]: mtk_device_wrap_seek df_delta err\n");
+                system("echo fota-interface >/sys/power/wake_unlock");
+                return -1;
+            }
+            mtk_device_wrap_read(fd_delta, full_header, DELTA_FULL_HEARD_SIZE);
+        }
+        else
+        {
+		
+            if (lseek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0)
+            {
+                err = errno;
+                RLOGE("+[UA]: mtk_device_wrap_seek df_delta err\n");
+                system("echo fota-interface >/sys/power/wake_unlock");
+                return -1;
+            }
+            read(fd_delta, full_header, DELTA_FULL_HEARD_SIZE);
+        
+	}
+
+        if (memcmp(full_header, "full-ota", DELTA_FULL_HEARD_SIZE) != 0) {
+            RLOGE("+[UA]: invalid full delta header\r\n");
+            up_info.fota_flag[0] = 'e';
+            up_info.fota_flag[1] = 'n';
+            up_info.fota_flag[2] = 'd';
+            up_info.update_result = -1;
+            up_info.ota_run = 0;
+            save_fota_info();
+
+            //for (i = FULL_SYSTEM;i<=FULL_BL33;i++){
+            
+            for (i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE);i++){
+                  if (fota_status.update_status[i].need_update ==1) {
+                    fota_status.ota_run = i;
+                    fota_status.update_status[i].check_delta = ERROR;
+                    fota_status.update_status[i].check_rom= WAIT;
+                    fota_status.update_status[i].update_result= ERROR;
+                }
+            }
+            fota_status.update_result = ERROR;
+            save_fota_status();
+            system("echo fota-interface >/sys/power/wake_unlock");
+            return -1;
+        }
+    }
+    
+    
+    
+    delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE;
+    
+    for(i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE);i++) {
+    
+        if (i>MAX_OTA_ROLE/2) {
+            delta_offset+=delta_head[i-1];
+        }    
+        if(delta_head[i]>0) {
+
+            if(current_slot==SLOT_B) {
+                sprintf(cmd_sys,"flash_eraseall %s",partition_filename_a[i-MAX_OTA_ROLE/2]);
+            } else {
+                sprintf(cmd_sys,"flash_eraseall %s",partition_filename_b[i-MAX_OTA_ROLE/2]);
+            }
+            system(cmd_sys);
+        
+            if(current_slot==SLOT_B) {
+                fd_partition_a = mtk_device_wrap_open(partition_filename_a[i-MAX_OTA_ROLE/2],O_RDWR);
+                if (fd_partition_a < 0) {
+                    err = errno;
+                    RLOGE("+[UA]: Error opening full id_a[%d] file: %s\n",i,strerror(errno));
+                    system("echo fota-interface >/sys/power/wake_unlock");
+                    return -err;
+                }
+                fd_curr = fd_partition_a;
+            }else{
+                fd_partition_b = mtk_device_wrap_open(partition_filename_b[i-MAX_OTA_ROLE/2],O_RDWR);
+                if (fd_partition_b < 0) {
+                    err = errno;
+                    RLOGE("+[UA]: Error opening full_id_b[%d] file: %s\n",i,strerror(errno));
+                    system("echo fota-interface >/sys/power/wake_unlock");
+                    return -err;
+                }
+                fd_curr = fd_partition_b;            
+            }
+            fota_status.ota_run = i+1;
+            save_fota_status();
+            up_info.ota_run = i+1;
+            save_fota_info();
+            retry_cnt = 0;
+            RLOGE("+[UA]: Start upgrading %s full.\n",partition_filename[i-MAX_OTA_ROLE/2]);
+            do{
+                status = delta_copyto_nand(delta_offset,delta_head[i]);
+                if(g_addr_flag == 1)
+                {
+                    ROCK_SHA_FILE(fd_delta,delta_offset,delta_head[i],digest_s);
+                }
+                else
+                {
+                    ROCK_SHA_FILE_COMMON(fd_delta,delta_offset,delta_head[i],digest_s);
+                }
+                ROCK_SHA_FILE(fd_curr,0,delta_head[i],digest_t);
+                retry_cnt++;
+            }while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+        
+            mtk_device_wrap_close(fd_curr);
+        
+            RLOGE("+[UA]: %s full retry_cnt = %d\n",partition_filename[i-MAX_OTA_ROLE/2],retry_cnt);
+        
+            if (retry_cnt>3) {
+                if (status == 0) {
+                    status = retry_cnt;
+                }
+                if(current_slot==SLOT_B) {
+                    nand_copyto_nand(partition_filename_b[i-MAX_OTA_ROLE/2],partition_filename_a[i-MAX_OTA_ROLE/2]);
+                }
+                else{
+                    nand_copyto_nand(partition_filename_a[i-MAX_OTA_ROLE/2],partition_filename_b[i-MAX_OTA_ROLE/2]);
+                }
+            }
+        
+            RLOGE("+[UA]: %s full upgrade result:%d\n",partition_filename[i-MAX_OTA_ROLE/2],status);
+
+            fota_status.update_result = status;
+            fota_status.update_status[i].update_result = status;
+            save_fota_status();
+
+            if (status != 0)
+            {
+
+                up_info.fota_flag[0] = 'e';
+                up_info.fota_flag[1] = 'n';
+                up_info.fota_flag[2] = 'd';
+                up_info.update_result = status;
+                up_info.ota_run = 0;
+                save_fota_info();
+                system("echo fota-interface >/sys/power/wake_unlock");
+                return status;
+            }
+    
+        }            
+    
+    }
+    
+    
+
+
+    if(update_mode != MODE_NORMAL){ //need backup
+        if(current_slot == SLOT_A) {
+            up_info.fota_flag[0] = 'B';
+            up_info.fota_flag[1] = '-';
+            up_info.fota_flag[2] = 'A';
+
+        }else{
+            up_info.fota_flag[0] = 'A';
+            up_info.fota_flag[1] = '-';
+            up_info.fota_flag[2] = 'B';
+
+        }
+
+    }else{
+        up_info.fota_flag[0] = 'e';
+        up_info.fota_flag[1] = 'n';
+        up_info.fota_flag[2] = 'd';
+
+    }
+
+
+    up_info.update_result = status;
+    up_info.ota_run = 0;
+    save_fota_info();
+
+    //close_dev_fd(fd_curr);
+    
+
+    
+    close(fd_update_status);
+    sync();
+    
+
+    slot = (current_slot == 0) ? 1 : 0;
+    
+    RLOGE("+[UA]: slot SLOT = %d\n",slot);
+    
+        if(switch_slot_flag==1)
+        {
+            module->setActiveBootSlot(module,slot);
+            RLOGE("+[UA]: upgrade is success!!!!\n");
+        }
+
+    fota_status.ota_run = 0;
+    fota_status.switch_slot = PASS;
+    fota_status.update_result = status;
+    save_fota_status();
+    
+    sleep(5);
+    sync();
+    sleep(5);
+
+    system("echo fota-interface >/sys/power/wake_unlock");
+
+    if(reboot_flag==1){
+    reboot_device();
+    }
+
+    return status;
+}
+
+
+
+static void rock_fail_handler()
+{
+    int ret = 0;
+    RLOGD("rock_fail_handler start\n");
+    //ret = rock_update_main(0, 0, 0, 0, 1, 1);
+    if(ret)
+    {
+        RLOGD("fota update fail again!\n");
+    }
+}
+
+/* main entrpoint */
+int lynq_rock_main(int first_run)
+{
+
+    int ret = 0;
+    
+    
+        ret = rock_update_main(0, 0, 0, 0, first_run, 1, 1, 1);
+        RLOGD("rock_update_main ret = %d\n", ret);
+        if(ret)
+        {
+            RLOGD("fota update fail!\n");
+        }
+        return ret;
+}
+
+#endif
+
+//xf.li@20230403 add for verfy start
+int lynq_file_md5_verfy(char *source, unsigned char *source_md5, char *target)
+{
+    int fd, size, ret, is_system = 0;
+    int need_copy = 1;
+    int system_mtd_num = 0;
+    int system_ubi_num = BACKUP_UBI_NUM;//max ubi number
+    char cmd_ubi_attach[128] = {0};
+    char cmd_ubi_detach[128] = {0};
+    char md5_target_file_patch[128] = {0};
+
+    RLOGD("in lynq_file_md5_verfy, source:%s, target:%s\n", source, target);
+    if(strcmp(source, DEV_SYSTEM_A) == 0 || strcmp(source, DEV_SYSTEM_B) == 0)
+    {
+        RLOGD("verfy system.img\n");
+        is_system = 1;
+        if(strcmp(source, DEV_SYSTEM_A) == 0)
+        {
+            system_mtd_num = MTD_SYSTEM_B;
+        }
+        else if(strcmp(source, DEV_SYSTEM_B) == 0)
+        {
+            system_mtd_num = MTD_SYSTEM_A;
+        }
+        else
+        {
+            RLOGD("source:%s, target:%s\n", source, target);
+        }
+        for( ; system_ubi_num >= 10; system_ubi_num--)//try from ubi31 to ubi10
+        {
+            sprintf(md5_target_file_patch, "/dev/ubi%d", system_ubi_num);
+            RLOGD("ubi_num = %d\n", system_ubi_num);
+            if((access(md5_target_file_patch, F_OK)) == -1)   
+            {
+                RLOGD("no the ubi file, can use this ubi.\n");
+                break;
+            }
+        }
+        if(system_ubi_num < 10)
+        {
+            RLOGE("no the ubi file, can use this ubi.\n");
+            return -1;
+        }
+    }
+    //=========================caculate md5sum start=====================
+    if(is_system == 1)
+    {
+        RLOGD("in system caculate\n");
+        RLOGD("system_mtd_num = %d, ubi_num = %d\n", system_mtd_num, system_ubi_num);
+        sprintf(cmd_ubi_attach, "ubiattach /dev/ubi_ctrl -m %d -d %d", system_mtd_num, system_ubi_num);
+        RLOGD("cmd_ubi_attach:%s", cmd_ubi_attach);
+        ret = system(cmd_ubi_attach);
+        if(ret != 0)
+        {
+            RLOGE("ubi attach error!!!\n");
+            return need_copy;
+        }
+        RLOGD("attach over\n");
+        //attach success
+        sprintf(md5_target_file_patch, "/dev/ubi%d_0", system_ubi_num);
+        RLOGD("md5_target_file_patch:%s", md5_target_file_patch);
+        //make sure the ubi volume is exist
+        if((access(md5_target_file_patch, F_OK)) == -1)   
+        {   
+            RLOGD("no the ubi file.\n");
+            sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num);
+            ret = system(cmd_ubi_detach);
+            if(ret != 0)
+            {
+                RLOGD("ubi dettach error!!!\n");
+            }
+
+            return need_copy;
+        }
+        //calculate md5sum
+        //ret = lynq_md5_two_file_verfy("/dev/ubi0_0", md5_target_file_patch);
+        ret = lynq_md5_file_verfy_ab(md5_target_file_patch, source_md5);
+        if(ret == MD5_VERFY_ERROR)
+        {
+            //ubidetach
+            sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num);
+            ret = system(cmd_ubi_detach);
+            if(ret != 0)
+            {
+                RLOGD("ubi dettach error!!!\n");
+            }
+            return need_copy;
+        }
+        if(ret != 0)
+        {
+            //ubidetach
+            sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num);
+            ret = system(cmd_ubi_detach);
+            if(ret != 0)
+            {
+                RLOGD("ubi dettach error!!!\n");
+            }
+            RLOGD("calculate system error!!!\n");
+            return -1;
+        }
+
+        RLOGD("verfy system.img over\n");
+    }
+    else
+    {
+        RLOGD("verfy else img\n");
+        //calculate md5sum
+        //ret = lynq_md5_two_file_verfy(source, target);
+        ret = lynq_md5_file_verfy_ab(target, source_md5);
+        if(ret == MD5_VERFY_ERROR)
+        {
+            return need_copy;
+        }
+        if(ret != 0)
+        {
+            RLOGD("calculate %s and %s error!!!\n", source, target);
+            return -1;
+        }
+    }
+    //====================caculate md5sum end======================
+    return 0;
+}
+//xf.li@20230403 add for verfy end
+
+
+//xf.li@20230401 add for ab rollback start
+
+int backup_nand_copyto_nand(char *source, char *target)
+{
+    int fd_source, fd_target, size;
+    int ret = -1;
+    int sleep_count = 0;
+    char cmd_erase_target[128] = {0};
+    int retry = MD5_RETRY_TIME;
+    unsigned char source_md5[MD5_READ_BUFFER_LEN] = {0};
+    char delta_data[ROCK_DEFAULT_BLOCK_SIZE];
+    //caclculate source md5 start
+    if(strcmp(source, DEV_SYSTEM_A) == 0 || strcmp(source, DEV_SYSTEM_B) == 0)
+    {
+        RLOGD("backup_nand_copyto_nand: verfy system.img\n");
+        
+        ret = calculate_file_md5_value("/dev/ubi0_0", source_md5);
+        if(ret < 0)
+        {
+            RLOGD("[+MD5]:calculate source md5 value ERROE!!!\n");
+            return ret;
+        }
+        RLOGD("source_md5 is %s\n", source_md5);   
+    }
+    else
+    {
+        ret = calculate_file_md5_value(source, source_md5);
+        if(ret < 0)
+        {
+            RLOGD("[+MD5]:calculate source md5 value ERROE!!!\n");
+            return ret;
+        }
+        RLOGD("source_md5 is %s\n", source_md5);
+    }
+    //caclculate source md5 end
+    //ret = lynq_file_md5_verfy(source, target);//verfy md5 value
+    ret = lynq_file_md5_verfy(source, source_md5, target);//verfy md5 value
+    RLOGD("+[UA]: md5_file_verfy :ret=%d\n", ret);
+    if(ret == 0)
+    {
+        RLOGD("+[UA]: nand_copyto_nand don't neet copy\n");
+    }
+    for(; ret > 0 && retry > 0; retry--)
+    {   
+        //erase nand-target start
+        if(fota_interrupt == FOTA_FIRST && (access(FILE_UPDATE_FLAG, F_OK)) == 0)
+        {
+            RLOGD("+[UA]: fota runing\n");
+            return -1;
+        }
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");//lock
+        RLOGD("+[UA]: ready to flash_erase\n");
+        sprintf(cmd_erase_target, "flash_erase %s 0 0", target);
+        ret = system(cmd_erase_target);
+        release_wake_lock("ab_recover");//unlock
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: erase %s fail\n", target);
+            return -1;
+        }
+        sleep(1);//sleep 1s
+
+        //erase nand-target end
+        RLOGD("+[UA]: ready to copy\n");
+        fd_source = mtk_device_wrap_open(source, O_RDONLY);
+        if (fd_source < 0) {
+            RLOGD("+[UA]: open source error\n");
+            return -1;
+        }
+
+        fd_target = mtk_device_wrap_open(target, O_RDWR);
+        if (fd_target < 0) {
+            RLOGD("+[UA]: open target  error\n");
+            return -1;
+        } 
+        ret = 0;//init ret
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");//lock
+        while(( size = mtk_device_wrap_read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0)
+        {
+            if(fota_interrupt == FOTA_FIRST && (access(FILE_UPDATE_FLAG, F_OK)) == 0)
+            {
+                RLOGD("+[UA]: fota runing\n");
+                ret = -1;
+                break;
+            }
+            usleep(40000);//sleep 40ms
+            mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE);
+            usleep(60000);//sleep 60ms
+            sleep_count++;
+            if(sleep_count >= 20)
+            {
+                //unlock
+                release_wake_lock("ab_recover");
+                sleep(1);//sleep 1s
+                //lock
+                acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");
+                sleep_count = 0;
+                RLOGD("+[UA]: try sleep one time");
+            }
+        }
+        release_wake_lock("ab_recover");//unlock
+        RLOGD("+[UA]: copy end\n");
+        mtk_device_wrap_close(fd_target);
+        mtk_device_wrap_close(fd_source);
+        if(ret < 0)
+        {
+            RLOGD("+[UA]: ret < 0\n");
+            return -1;
+        }
+        RLOGD("+[UA]: ready to md5_verfy\n");
+        //ret = lynq_file_md5_verfy(source, target);//verfy md5 value
+        ret = lynq_file_md5_verfy(source, source_md5, target);//verfy md5 value
+        RLOGD("+[UA]: md5_file_verfy :ret=%d\n", ret);
+        if(ret == 0)
+        {
+            RLOGD("+[UA]: nand_copyto_nand copy success\n");
+            break;
+        }
+    }
+    if(ret != 0)
+    {
+        RLOGD("+[UA]: md5_file_verfy FAIL!!!\n");
+    }
+    return ret;
+}
+//xf.li@20230401 add for ab rollback end
+
+//xf.li@20230822 add for ab rollback start
+
+int lynq_backup_main()
+{
+    const hw_module_t* hw_module;
+    hw_module = &HAL_MODULE_INFO_SYM;
+    int is_successful;
+    int ret = 0;
+    if (!hw_module || strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) 
+    {
+        ret = -1;
+    }
+    RLOGD("ret = %d\n", ret);
+    if (ret != 0)
+    {
+        RLOGD("+[UA]: Error loading boot_control HAL implementation.\n");
+        return -1;
+    }
+    module = (boot_control_module_t*)hw_module;
+    module->init(module);
+    if (module == NULL) 
+    {
+        RLOGD("+[UA]: Error getting bootctrl module.\n");
+        return  -1;
+    }
+    lynq_init_wake_lock_func();
+    current_slot = module->getCurrentSlot(module);
+    is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+    RLOGD("+[UA]: Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
+    fota_interrupt = RECOVER_FIRST;
+    if(current_slot==SLOT_B)
+    {
+        ret = backup_nand_copyto_nand(DEV_SPM_B,DEV_SPM_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup spm_a fail\n");
+            return 1;
+        }
+        fota_interrupt = FOTA_FIRST;
+        ret = backup_nand_copyto_nand(DEV_SYSTEM_B,DEV_SYSTEM_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup system_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_BOOT_B,DEV_BOOT_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup boot_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_TEE_B,DEV_TEE_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup tee_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_MD1IMG_B,DEV_MD1IMG_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup md1img_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_VBMETA_B,DEV_VBMETA_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup vbmeta_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_MEDMCU_B,DEV_MEDMCU_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup medmcu_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_BL2_B,DEV_BL2_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup bl2_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_BL33_B,DEV_BL33_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup bl33_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_OEMAPP_B,DEV_OEMAPP_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup oemapp_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_OEMAPP2_B,DEV_OEMAPP2_A);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup oemapp2_a fail\n");
+            return 1;
+        }
+    }
+    else
+    {
+        ret = backup_nand_copyto_nand(DEV_SPM_A,DEV_SPM_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup spm_a fail\n");
+            return 1;
+        }
+        fota_interrupt = FOTA_FIRST;
+        ret = backup_nand_copyto_nand(DEV_SYSTEM_A,DEV_SYSTEM_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup system_b fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_BOOT_A,DEV_BOOT_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup boot_b fail\n");
+            return 1;
+        }
+        
+        ret = backup_nand_copyto_nand(DEV_TEE_A,DEV_TEE_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup tee_b fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_MD1IMG_A,DEV_MD1IMG_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup md1img_b fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_VBMETA_A,DEV_VBMETA_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup vbmeta_b fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_MEDMCU_A,DEV_MEDMCU_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup medmcu_b fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_BL2_A,DEV_BL2_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup bl2_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_BL33_A,DEV_BL33_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup bl33_a fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_OEMAPP_A,DEV_OEMAPP_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup oemapp_b fail\n");
+            return 1;
+        }
+        ret = backup_nand_copyto_nand(DEV_OEMAPP2_A,DEV_OEMAPP2_B);
+        if(ret != 0)
+        {
+            RLOGD("+[UA]: backup oemapp2_b fail\n");
+            return 1;
+        }
+    }
+    RLOGD("+[UA]: lynq_backup_main success \n");
+    return 0;
+}
+//xf.li@20230822 add for ab rollback end
+
+
+int lynq_check_oemapp(char* name)
+{
+    FILE *fp;
+    char check_result[64];
+    int ret;
+    if(strcmp(name, "oemapp") == 0)
+    {
+        RLOGD("lynq_check_oemapp oemapp");
+        ret = system("cat /proc/mtd|grep oemapp");
+        if(ret != 0)
+        {
+            return 0;
+        }
+        if(system("df -lh|grep oemapp |grep -v oemapp2") != 0)
+        {
+            return -1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+    else if(strcmp(name, "oemapp2") == 0)
+    {
+        RLOGD("lynq_check_oemapp oemapp2");
+        ret = system("cat /proc/mtd|grep oemapp2");
+        if(ret != 0)
+        {
+            return 0;
+        }
+        if(system("df -lh|grep oemapp2") != 0)
+        {
+            return -1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+}
+
+//lt add @2021.9.23 for  deal with power down \ backup or upgrade.
+int lynq_fota_func(void) 
+{
+    int fd;
+    int first_run = 1;
+    int ret = 0;
+    UPDATE_INFO lynq_up_info;
+    //xf.li@20230822 add for ab backup start
+    unsigned int current_slot, other_slot;
+    int is_other_slot_bootable;
+    const hw_module_t* hw_module;
+    //xf.li@20230822 add for ab backup end
+    RLOGE("[+UP]: ******lynq_fota_func start******\n");
+    //xf.li@20230822 add for ab backup start
+    //----------get current slot and whether other slot  is bootable
+    hw_module = &HAL_MODULE_INFO_SYM;
+    if (!hw_module ||
+        strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+        ret = -EINVAL;
+    }
+    if (ret != 0) {
+        RLOGE("+[UA]: Error loading boot_control HAL implementation.\n");
+        return -1;
+    }
+    module = (boot_control_module_t*)hw_module;
+    module->init(module);
+    if (module == NULL) {
+        RLOGE("+[UA]: Error getting bootctrl module.\n");
+        return  -1;
+    }
+    current_slot = module->getCurrentSlot(module);
+    other_slot = (current_slot == 0) ? 1 : 0;
+    is_other_slot_bootable = module->isSlotBootable(module, other_slot);
+    //-----------end
+    RLOGE("current slot:%u, is_other_slot_bootable : %d\n",current_slot, is_other_slot_bootable);
+    //xf.li@20230822 add for ab backup end
+
+    memset(&lynq_up_info, 0, sizeof(lynq_up_info));
+    fd = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777);
+    if (fd < 0)
+    {
+        return -1;
+    }
+    read(fd,(unsigned char *)&lynq_up_info,sizeof(lynq_up_info));
+    close(fd);
+
+    RLOGD("[+UP]: lynq_up_info.ota_run=%d\n",lynq_up_info.ota_run);
+    if((lynq_check_oemapp("oemapp") != 0) || (lynq_check_oemapp("oemapp2") != 0))
+    {
+        RLOGD("ENTER LYNQ_CHECK_OEMAPP\n");
+        system("echo mode 001 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio");
+        system("echo dir 001 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio");
+        system("echo out 001 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio");
+        RLOGD("need setUnbootable.\n");
+        module->setSlotAsUnbootable(module,current_slot);
+        RLOGD("+[UA]: setSlotAsUnbootable!!!!\n");
+        sync();
+        if(((lynq_up_info.fota_flag[0]=='A')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='B'))||
+        ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A')))
+        {
+            RLOGD("mark oemapp mount fail\n");
+            lynq_set_value(FOTA_UCI_MODULE,FOTA_UCI_STATE, "1");
+        }
+        sleep(5);
+        reboot_device();
+    }
+
+    if(lynq_up_info.ota_run != 0)
+    { 
+        //Power off, call UA
+        RLOGE("[+UP]: ***Power off, call UA***\n");
+        ret = rock_update_main(0, 0, 0, 0, first_run, 1, 0, 1);
+        RLOGE("rock_update_main ret = %d\n", ret);
+        if(ret) 
+        {
+            RLOGE("fota update fail!\n");
+        }
+    }
+
+    if(((lynq_up_info.fota_flag[0]=='A')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='B'))||
+        ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A')))
+    {
+        //Upgrade the other side and call UA
+        RLOGE("[+UP]: ***Upgrade the other side and call UA***\n");
+        ret = rock_update_main(0, 0, 0, 0, first_run, 0, 0, 0);
+        RLOGE("rock_update_main ret = %d\n", ret);
+        if(ret)
+        {
+            RLOGE("fota update fail!\n");
+        }
+    }
+    //xf.li@20230822 add for ab backup start
+    else if(is_other_slot_bootable == 0) 
+    {
+        RLOGE("need backup\n");
+        ret = lynq_backup_main();
+        if(ret != 0)
+        {
+            RLOGE("ERROE: backup fail!!!\n");
+        }
+        else
+        {
+            RLOGE("backup success!!!\n");
+            module->setCompleteBackup(module, current_slot);
+        }
+    }
+    else
+    {
+        RLOGE("Don't need backup\n");
+    }
+    //xf.li@20230822 add for ab backup end
+
+    return 0;
+}    
+
+int lynq_nand_open(const char *pathname, int flags)
+{
+//    printf("pathname:%s---flags:%d",pathname,flags);
+    return open(pathname,flags);
+}
+
+ssize_t lynq_nand_read(int fd, void *buf, size_t count)
+{
+//    printf("rfd:%d---buf:%s---count:%d",fd,buf,count);
+    return read(fd,buf,count);
+}
+
+ssize_t lynq_nand_write(int fd, void *buf, size_t count)
+{
+ //   printf("wfd:%d---buf:%s---count:%d",fd,buf,count);
+    return write(fd,buf,count);
+}
+
+int lynq_nand_close(int fd)
+{
+    return close(fd);
+}
+
+/**
+ * @brief Obtain the upgrade result
+ * 
+ * @param void
+ * @return 0xff:open file fail,0:upgrade success,1,upgrade wait 
+ */
+ int lynq_get_upgrade_status(void)
+{
+    int lynq_state_fd;
+    int lynq_upgrade_wait = 1;
+    OTA_STATUS lynq_ota_status;
+
+    memset(&lynq_ota_status, 0, sizeof(lynq_ota_status));
+
+    lynq_state_fd = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777);
+
+    if (lynq_state_fd < 0) 
+    {
+        return 0xff;
+    }
+    read(lynq_state_fd,(unsigned char *)&lynq_ota_status,sizeof(lynq_ota_status));
+    close(lynq_state_fd);
+    if((lynq_ota_status.ota_run != 0) && (lynq_ota_status.update_result == 0))
+    {
+        return lynq_upgrade_wait;
+    }
+    return lynq_ota_status.update_result;
+}
+
+/**
+ * @brief reboot device
+ * 
+ * @param void
+ * @return void
+ */
+ void lynq_reboot_device(void)
+{
+    reboot_device();
+    return ;
+}
+
+/**
+ * @brief fota no resatrt
+ * 
+ * @param void
+ * @return 0:fota success -Other values:fota fail
+ */
+
+int lynq_fota_nrestart(void)
+{
+
+    int ret = 0;
+#if 0
+    printf("-********copy delta ***-\n");
+    test_write_delta("/data/delta",DEV_DELTA);
+#endif
+
+    ret = rock_update_main(0, 0, 0, 0, 1, 1, 0, 1);
+    RLOGD("rock_update_nrestart ret = %d\n", ret);
+    if(ret)
+    {
+        RLOGD("fota update fail!\n");
+    }
+    return ret;
+}
+
+/**
+ * @brief Set the upgrade package address
+ * 
+ * @param1 value:fota addr
+ * @param1 szie:fota addr length
+ * @return 0:set success other:set fail
+ */
+int lynq_fota_set_addr_value(char *value,int size)
+{
+    if(size < 64)
+    {
+        return lynq_set_value(FOTA_UCI_MODULE,FOTA_UCI_ADDR, value);
+    }
+    return -1;
+}
+/**
+ * @brief get the upgrade package address
+ * 
+ * @param1 value:fota addr
+ * @return 0:get success other:set fail
+ */
+int lynq_fota_get_addr_value(char *tmp)
+{
+    return lynq_get_value(FOTA_UCI_FILE, FOTA_UCI_MODULE,FOTA_UCI_ADDR, tmp);
+}
+
+/**
+ * @brief Porting wakes up the demo content
+ */
+static void lynq_init_wake_lock_func(void)
+{
+    const char *lynqLibPath_WakeLock = "/usr/lib64/libpower.so";
+
+    dlHandle_wakelock = dlopen(lynqLibPath_WakeLock, RTLD_NOW);
+    if (dlHandle_wakelock == NULL) 
+    {
+        printf("dlopen lynqLibPath_WakeLock failed: %s", dlerror());
+        exit(EXIT_FAILURE);
+    }
+    
+    acquire_wake_lock = (int(*)(int,const char*))dlsym(dlHandle_wakelock, "acquire_wake_lock");
+    if (acquire_wake_lock == NULL) {
+        printf("acquire_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+        exit(EXIT_FAILURE);
+    }
+    release_wake_lock = (int(*)( const char*))dlsym(dlHandle_wakelock, "release_wake_lock");
+    if (release_wake_lock == NULL) {
+        printf("release_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+        exit(EXIT_FAILURE);
+    }
+    dlerror(); // Clear any previous dlerror
+
+  return;
+}
+
+/**
+ * @brief fota wake lock
+ * 
+ * @param1 value:void
+ * @return ;
+ */
+static void lynq_fota_grab_artial_wake_lock(void) 
+{
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, ANDROID_WAKE_LOCK_NAME);
+}
+
+/**
+ * @brief get the upgrade package address
+ * 
+ * @param1 value:void
+ * @return ;
+ */
+static void lynq_fota_release_wake_lock(void) 
+{
+    release_wake_lock(ANDROID_WAKE_LOCK_NAME);
+}
+/**
+ * @brief This is the wake up call
+ * end
+ */
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/rock_ua/sha.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/rock_ua/sha.c
new file mode 100755
index 0000000..5ac6b53
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota-run/rock_ua/sha.c
@@ -0,0 +1,428 @@
+/* sha.c
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "sha.h"
+
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mtk_device_wrap.h"
+
+// Some machines lack byteswap.h and endian.h.  These have to use the
+// slower code, even if they're little-endian.
+
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+
+#include <byteswap.h>
+#include <memory.h>
+
+
+
+// This version is about 28% faster than the generic version below,
+// but assumes little-endianness.
+
+static inline uint32_t ror27(uint32_t val) {
+    return (val >> 27) | (val << 5);
+}
+static inline uint32_t ror2(uint32_t val) {
+    return (val >> 2) | (val << 30);
+}
+static inline uint32_t ror31(uint32_t val) {
+    return (val >> 31) | (val << 1);
+}
+
+static void SHA1_Transform(SHA_CTX* ctx) {
+    uint32_t W[80];
+    register uint32_t A, B, C, D, E;
+    int t;
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+
+#define SHA_F1(A,B,C,D,E,t)                     \
+    E += ror27(A) +                             \
+        (W[t] = bswap_32(ctx->buf.w[t])) +      \
+        (D^(B&(C^D))) + 0x5A827999;             \
+    B = ror2(B);
+
+    for (t = 0; t < 15; t += 5) {
+        SHA_F1(A,B,C,D,E,t + 0);
+        SHA_F1(E,A,B,C,D,t + 1);
+        SHA_F1(D,E,A,B,C,t + 2);
+        SHA_F1(C,D,E,A,B,t + 3);
+        SHA_F1(B,C,D,E,A,t + 4);
+    }
+    SHA_F1(A,B,C,D,E,t + 0);  // 16th one, t == 15
+
+#undef SHA_F1
+
+#define SHA_F1(A,B,C,D,E,t)                                     \
+    E += ror27(A) +                                             \
+        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+        (D^(B&(C^D))) + 0x5A827999;                             \
+    B = ror2(B);
+
+    SHA_F1(E,A,B,C,D,t + 1);
+    SHA_F1(D,E,A,B,C,t + 2);
+    SHA_F1(C,D,E,A,B,t + 3);
+    SHA_F1(B,C,D,E,A,t + 4);
+
+#undef SHA_F1
+
+#define SHA_F2(A,B,C,D,E,t)                                     \
+    E += ror27(A) +                                             \
+        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+        (B^C^D) + 0x6ED9EBA1;                                   \
+    B = ror2(B);
+
+    for (t = 20; t < 40; t += 5) {
+        SHA_F2(A,B,C,D,E,t + 0);
+        SHA_F2(E,A,B,C,D,t + 1);
+        SHA_F2(D,E,A,B,C,t + 2);
+        SHA_F2(C,D,E,A,B,t + 3);
+        SHA_F2(B,C,D,E,A,t + 4);
+    }
+
+#undef SHA_F2
+
+#define SHA_F3(A,B,C,D,E,t)                                     \
+    E += ror27(A) +                                             \
+        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+        ((B&C)|(D&(B|C))) + 0x8F1BBCDC;                         \
+    B = ror2(B);
+
+    for (; t < 60; t += 5) {
+        SHA_F3(A,B,C,D,E,t + 0);
+        SHA_F3(E,A,B,C,D,t + 1);
+        SHA_F3(D,E,A,B,C,t + 2);
+        SHA_F3(C,D,E,A,B,t + 3);
+        SHA_F3(B,C,D,E,A,t + 4);
+    }
+
+#undef SHA_F3
+
+#define SHA_F4(A,B,C,D,E,t)                                     \
+    E += ror27(A) +                                             \
+        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+        (B^C^D) + 0xCA62C1D6;                                   \
+    B = ror2(B);
+
+    for (; t < 80; t += 5) {
+        SHA_F4(A,B,C,D,E,t + 0);
+        SHA_F4(E,A,B,C,D,t + 1);
+        SHA_F4(D,E,A,B,C,t + 2);
+        SHA_F4(C,D,E,A,B,t + 3);
+        SHA_F4(B,C,D,E,A,t + 4);
+    }
+
+#undef SHA_F4
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+}
+
+void SHA_update(SHA_CTX* ctx, const void* data, int len) {
+    int i = ctx->count % sizeof(ctx->buf);
+    const uint8_t* p = (const uint8_t*)data;
+
+    ctx->count += len;
+
+    while (len > sizeof(ctx->buf) - i) {
+        memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
+        len -= sizeof(ctx->buf) - i;
+        p += sizeof(ctx->buf) - i;
+        SHA1_Transform(ctx);
+        i = 0;
+    }
+
+    while (len--) {
+        ctx->buf.b[i++] = *p++;
+        if (i == sizeof(ctx->buf)) {
+            SHA1_Transform(ctx);
+            i = 0;
+        }
+    }
+}
+
+
+const uint8_t* SHA_final(SHA_CTX* ctx) {
+    uint64_t cnt = ctx->count * 8;
+    int i;
+
+    SHA_update(ctx, (uint8_t*)"\x80", 1);
+    while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+        SHA_update(ctx, (uint8_t*)"\0", 1);
+    }
+    for (i = 0; i < 8; ++i) {
+        uint8_t tmp = cnt >> ((7 - i) * 8);
+        SHA_update(ctx, &tmp, 1);
+    }
+
+    for (i = 0; i < 5; i++) {
+        ctx->buf.w[i] = bswap_32(ctx->state[i]);
+    }
+
+    return ctx->buf.b;
+}
+
+#else   // #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static void SHA1_transform(SHA_CTX *ctx) {
+    uint32_t W[80];
+    uint32_t A, B, C, D, E;
+    uint8_t *p = ctx->buf;
+    int t;
+
+    for(t = 0; t < 16; ++t) {
+        uint32_t tmp =  *p++ << 24;
+        tmp |= *p++ << 16;
+        tmp |= *p++ << 8;
+        tmp |= *p++;
+        W[t] = tmp;
+    }
+
+    for(; t < 80; t++) {
+        W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+
+    for(t = 0; t < 80; t++) {
+        uint32_t tmp = rol(5,A) + E + W[t];
+
+        if (t < 20)
+            tmp += (D^(B&(C^D))) + 0x5A827999;
+        else if ( t < 40)
+            tmp += (B^C^D) + 0x6ED9EBA1;
+        else if ( t < 60)
+            tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
+        else
+            tmp += (B^C^D) + 0xCA62C1D6;
+
+        E = D;
+        D = C;
+        C = rol(30,B);
+        B = A;
+        A = tmp;
+    }
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+}
+
+void SHA_update(SHA_CTX *ctx, const void *data, int len) {
+    int i = ctx->count % sizeof(ctx->buf);
+    const uint8_t* p = (const uint8_t*)data;
+
+    ctx->count += len;
+
+    while (len--) {
+        ctx->buf[i++] = *p++;
+        if (i == sizeof(ctx->buf)) {
+            SHA1_transform(ctx);
+            i = 0;
+        }
+    }
+}
+const uint8_t *SHA_final(SHA_CTX *ctx) {
+    uint8_t *p = ctx->buf;
+    uint64_t cnt = ctx->count * 8;
+    int i;
+
+    SHA_update(ctx, (uint8_t*)"\x80", 1);
+    while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+        SHA_update(ctx, (uint8_t*)"\0", 1);
+    }
+    for (i = 0; i < 8; ++i) {
+        uint8_t tmp = cnt >> ((7 - i) * 8);
+        SHA_update(ctx, &tmp, 1);
+    }
+
+    for (i = 0; i < 5; i++) {
+        uint32_t tmp = ctx->state[i];
+        *p++ = tmp >> 24;
+        *p++ = tmp >> 16;
+        *p++ = tmp >> 8;
+        *p++ = tmp >> 0;
+    }
+
+    return ctx->buf;
+}
+
+#endif // endianness
+
+void SHA_init(SHA_CTX* ctx) {
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+    ctx->count = 0;
+}
+
+/* Convenience function */
+const uint8_t* SHA(const void *data, int len, uint8_t *digest) {
+    const uint8_t *p;
+    int i;
+	
+    SHA_CTX ctx;
+    SHA_init(&ctx);
+    SHA_update(&ctx, data, len);
+    p = SHA_final(&ctx);
+    for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
+        digest[i] = *p++;
+    }
+    return digest;
+}
+
+#define NAND_PAGE_SIZE_SHA  4096
+
+const uint8_t* ROCK_SHA_FILE_COMMON(int fd_sha, int offset,int totle_size, uint8_t *digest) {
+    const uint8_t *p;
+    int i = 0;
+    //int fd_sha;
+    int size = 0;
+    int totale_size_common = totle_size;
+    char data[NAND_PAGE_SIZE_SHA];
+	
+
+    lseek(fd_sha, offset, SEEK_SET);
+    SHA_CTX ctx;
+    SHA_init(&ctx);
+
+    do{
+        if(totale_size_common >= NAND_PAGE_SIZE_SHA)
+        {
+            size = read(fd_sha,data,NAND_PAGE_SIZE_SHA);
+        }
+        else
+        {
+            size = read(fd_sha,data,totale_size_common);
+        }
+        if (size == 0){
+		    break;
+		}			
+        SHA_update(&ctx, data, size);
+        totale_size_common -= size;
+
+    }while(totale_size_common>0);
+    p = SHA_final(&ctx);
+    for (i = 0; i < SHA_DIGEST_SIZE; ++i) 
+    {
+        digest[i] = *p++;
+    }
+    return digest;
+}
+
+const uint8_t* ROCK_SHA_FILE(int fd_sha, int offset,int totle_size, uint8_t *digest) {
+    const uint8_t *p;
+    int i = 0;
+    //int fd_sha;
+    int size = 0;
+    int totale_size_file = totle_size;
+    char data[NAND_PAGE_SIZE_SHA];
+	
+
+    mtk_device_wrap_seek(fd_sha, offset, SEEK_SET);
+    SHA_CTX ctx;
+    SHA_init(&ctx);
+
+    do{
+        if(totale_size_file >= NAND_PAGE_SIZE_SHA)
+        {
+            size = mtk_device_wrap_read(fd_sha,data,NAND_PAGE_SIZE_SHA);   
+        }
+        else
+        {
+            size = mtk_device_wrap_read(fd_sha,data,totale_size_file);
+        }
+	    if (size == 0){
+		    break;
+		}	
+        SHA_update(&ctx, data, size);
+        totale_size_file -= size;
+
+    }while(totale_size_file>0);
+    p = SHA_final(&ctx);
+    for (i = 0; i < SHA_DIGEST_SIZE; ++i) 
+    {
+        digest[i] = *p++;
+    }
+    return digest;
+}
+
+
+
+// Take a string 'str' of 40 hex digits and parse it into the 20
+// byte array 'digest'.  'str' may contain only the digest or be of
+// the form "<digest>:<anything>".  Return 0 on success, -1 on any
+// error.
+int ParseSha1(const char* str, uint8_t* digest) {
+    int i;
+    const char* ps = str;
+    uint8_t* pd = digest;
+    for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
+        int digit;
+        if (*ps >= '0' && *ps <= '9') {
+            digit = *ps - '0';
+        } else if (*ps >= 'a' && *ps <= 'f') {
+            digit = *ps - 'a' + 10;
+        } else if (*ps >= 'A' && *ps <= 'F') {
+            digit = *ps - 'A' + 10;
+        } else {
+            return -1;
+        }
+        if (i % 2 == 0) {
+            *pd = digit << 4;
+        } else {
+            *pd |= digit;
+            ++pd;
+        }
+    }
+    if (*ps != '\0') return -1;
+    return 0;
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c
index 49ebfcc..160ccec 100755
--- a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c
@@ -19,7 +19,7 @@
 #include <string.h>
 #include <dlfcn.h>
 #include <stdint.h>
-
+#include <pthread.h>
 
 #include <hardware/boot_control.h>
 #include <hardware/hardware.h>
@@ -117,7 +117,6 @@
 
 unsigned int  delta_head[128]={0};  //512/4   128/2=64
 
-
 #define FOTA_DELTA_MTD "/dev/mtd47"
 #define FOTA_UCI_MODULE "lynq_fota"
 #define FOTA_UCI_FILE "lynq_uci"
@@ -194,6 +193,7 @@
 int fd_delta,fd_curr,fd_log,fd_update_status,fd_fota_status;
 int fd_write,fd_read;
 
+static pthread_mutex_t s_update_main_mutex;
 static unsigned int  delta_offset = 0;
 static unsigned int  now_patch = 0;
 unsigned int  current_slot = 0;
@@ -635,7 +635,7 @@
         ret = get_file_size();
         if(ret != 0)
         {
-            RLOGD("the delta size over 50M\n");
+            RLOGE("the delta size over 50M\n");
             return -1;
         }
 
@@ -643,12 +643,12 @@
         result = test_write_delta(lynq_fota_addr, g_delta_mtd);
         if(result != 0)
         {
-            RLOGD("fota.delta write into mtd fail !\n");
+            RLOGE("fota.delta write into mtd fail !\n");
         }
         strcpy(lynq_fota_addr, g_delta_mtd);
         if(lynq_fota_set_addr_value(lynq_fota_addr,strlen(lynq_fota_addr)))
         {
-            RLOGD("set addr fail\n");
+            RLOGE("set addr fail\n");
             return 1;
         }
         RLOGD("+[UA]: get fota pack addr: %s\n", lynq_fota_addr);
@@ -656,7 +656,7 @@
 
         if (fd_delta < 0) {
             err = errno;
-            RLOGD("+[UA]: Error opening fota file: %s\n",strerror(errno));
+            RLOGE("+[UA]: Error opening fota file: %s\n",strerror(errno));
             mtk_device_wrap_close(fd_delta);
             return -err;
         }
@@ -669,7 +669,7 @@
 
         if (fd_delta < 0) {
             err = errno;
-            RLOGD("+[UA]: Error opening fota file: %s\n",strerror(errno));
+            RLOGE("+[UA]: Error opening fota file: %s\n",strerror(errno));
             mtk_device_wrap_close(fd_delta);
             return -err;
         }
@@ -681,7 +681,7 @@
 
         if (fd_delta < 0) {
             err = errno;
-            RLOGD("+[UA]: Error opening fota file: %s\n",strerror(errno));
+            RLOGE("+[UA]: Error opening fota file: %s\n",strerror(errno));
             close(fd_delta);
             return -err;
         }
@@ -692,7 +692,7 @@
     fd_update_status = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777);
     if (fd_update_status < 0) {
         err = errno;
-        RLOGD("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+        RLOGE("+[UA]: Error opening metadata file: %s\n",strerror(errno));
         close(fd_update_status);
         return -err;
     }
@@ -732,7 +732,7 @@
     fd_source = open(source,O_RDONLY);
 
     if (fd_source < 0) {
-        RLOGD("+[UA]: open source  error\n");
+        RLOGE("+[UA]: open source  error\n");
         return 1;
     }
 
@@ -741,7 +741,7 @@
     if (fd_target < 0) {
         mtk_device_wrap_close(fd_target);
         close(fd_source);
-        RLOGD("+[UA]: open target  error\n");
+        RLOGE("+[UA]: open target  error\n");
         return 1;
     } 
 
@@ -769,7 +769,7 @@
     fd_source = mtk_device_wrap_open(source,O_RDONLY);
      
     if (fd_source < 0) {
-        RLOGD("+[UA]: open source  error\n");
+        RLOGE("+[UA]: open source  error\n");
         return 1;
     }
 
@@ -778,7 +778,7 @@
     if (fd_target < 0) {
         mtk_device_wrap_close(fd_target);
         mtk_device_wrap_close(fd_source);
-        RLOGD("+[UA]: open target  error\n");
+        RLOGE("+[UA]: open target  error\n");
         return 1;
     } 
     
@@ -931,7 +931,7 @@
     num = buffer[2][14];
 
 
-    RLOGD("num=%c\n", num);
+    RLOGE("num=%c\n", num);
     if(num == '0' || num == '1')
     {
         printf("this is four core\n");
@@ -944,7 +944,7 @@
     }
     else
     {
-        RLOGD("this char is error\n");
+        RLOGE("this char is error\n");
         return -1;
     }
     pclose(fp);
@@ -985,7 +985,7 @@
     fd = open(FILE_UPDATE_FLAG,O_RDWR | O_CREAT,0777);
     if (fd < 0)
     {
-        RLOGD("+[UA]: can't open file /tmp/update_flag.\n");
+        RLOGE("+[UA]: can't open file /tmp/update_flag.\n");
         return -1;
     }
     close(fd);
@@ -1001,7 +1001,7 @@
         ret = -EINVAL;
     }
     if (ret != 0) {
-        RLOGD("+[UA]: Error loading boot_control HAL implementation.\n");
+        RLOGE("+[UA]: Error loading boot_control HAL implementation.\n");
         return -1;
     }
 
@@ -1010,7 +1010,7 @@
 
 
     if (module == NULL) {
-        RLOGD("+[UA]: Error getting bootctrl module.\n");
+        RLOGE("+[UA]: Error getting bootctrl module.\n");
         return  -1;
     }
 
@@ -1022,8 +1022,12 @@
     
     int is_successful = module->isSlotMarkedSuccessful(module, current_slot);
   
-    RLOGD("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
-
+    RLOGE("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
+    if((current_slot != 0) && (current_slot != 1))
+    {
+        RLOGE("+[UA]: Error getting bootctrl current_slot.\n");
+        return -1;
+    }
 
     memset(&ctx, 0, sizeof(ctx));
     ctx.rom_base = 0;
@@ -1039,12 +1043,12 @@
 
     if(0 != init_dev_fd())
     {
-        RLOGD("+[UA]: get fota addr error\n");
+        RLOGE("+[UA]: get fota addr error\n");
         system("echo fota-interface >/sys/power/wake_unlock");
         return E_ROCK_FOTA_ADDR;
     }
 
-    RLOGD("+[UA]: up_info.ota_run = %d\n",up_info.ota_run);
+    RLOGE("+[UA]: up_info.ota_run = %d\n",up_info.ota_run);
 
 #if 0
     if ((up_info.ota_run>PATCH_BL33)||(up_info.ota_run<PATCH_SYSTEM))
@@ -1068,13 +1072,18 @@
         update_mode = MODE_NORMAL;
     }
     
-    RLOGD("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag);
-    RLOGD("+[UA]: update_mode = %d\n",update_mode);
+    RLOGE("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag);
+    RLOGE("+[UA]: update_mode = %d\n",update_mode);
 
     memset(&delta_head, 0, sizeof(delta_head));
     if(g_addr_flag == 1)
     {
-        mtk_device_wrap_read(fd_delta, (char *)&delta_head[0], sizeof(delta_head));
+        RLOGD("fd_delta=%d\n", fd_delta);
+        ret = mtk_device_wrap_read(fd_delta, (char *)&delta_head[0], sizeof(delta_head));
+        if(ret <0)
+        {
+             return -1;
+        }
     }
     else
     {
@@ -1089,7 +1098,7 @@
             fota_status.update_status[i].need_update = 1;
             delta_size+=delta_head[i];
         }
-        RLOGD("+[UA]: %s,delta size = %d, i=%d\n",partition_filename[i],delta_head[i], i);
+        RLOGE("+[UA]: %s,delta size = %d, i=%d\n",partition_filename[i],delta_head[i], i);
     }
 
     for(i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE); i++) {
@@ -1097,7 +1106,7 @@
             fota_status.update_status[i].need_update = 1;
             sha_size+=delta_head[i];
         }
-        RLOGD("+[UA]: %s,full size = %d, i=%d\n",partition_filename[i-MAX_OTA_ROLE/2],delta_head[i], i);
+        RLOGE("+[UA]: %s,full size = %d, i=%d\n",partition_filename[i-MAX_OTA_ROLE/2],delta_head[i], i);
     }
 
     core_num= check_cpu();
@@ -1106,22 +1115,22 @@
         cpu_flag = check(delta_head[64]);
         if(cpu_flag < 0)
         {
-            RLOGD("cpu core is error\n");
+            RLOGE("cpu core is error\n");
             system("echo fota-interface >/sys/power/wake_unlock");
             return -1;
         }
         else
         {
-            RLOGD("cpu core match\n");
+            RLOGE("cpu core match\n");
         }
     }
     else if(core_num == 4)
     {
-        RLOGD("the cpu core is four!!!\n");
+        RLOGE("the cpu core is four!!!\n");
     }
     else
     {
-        RLOGD("read the cpu core fail");
+        RLOGE("read the cpu core fail");
         system("echo fota-interface >/sys/power/wake_unlock");
         return -1;
     }
@@ -1142,8 +1151,18 @@
     memset(str_sha,0,40);
     if(g_addr_flag == 1)
     {
-        mtk_device_wrap_seek(fd_delta, sha_size + sizeof(delta_head), SEEK_SET);
-        mtk_device_wrap_read(fd_delta, digest_s, SHA_DIGEST_SIZE);
+        ret = mtk_device_wrap_seek(fd_delta, sha_size + sizeof(delta_head), SEEK_SET);
+        if(ret < 0)
+        {
+            RLOGE("mtk_device_wrap_seek fail\n");
+            return -1;
+        }
+        ret = mtk_device_wrap_read(fd_delta, digest_s, SHA_DIGEST_SIZE);
+        if(ret < 0)
+        {
+            RLOGE("mtk_device_wrap_read fail\n");
+            return -1;
+        }
     }
     else
     {
@@ -1152,7 +1171,7 @@
     }
 
     convert_hex(digest_s,str_sha);
-    RLOGD("+[UA]: delta save sha = %s\n",str_sha);
+    RLOGE("+[UA]: delta save sha = %s\n",str_sha);
     if(g_addr_flag == 1)
     {
         ROCK_SHA_FILE(fd_delta,sizeof(delta_head),sha_size,digest_t);
@@ -1163,14 +1182,14 @@
     }
     memset(str_sha,0,40);
     convert_hex(digest_t,str_sha);
-    RLOGD("+[UA]: delta calc sha = %s\n",str_sha);
+    RLOGE("+[UA]: delta calc sha = %s\n",str_sha);
     
     if(memcmp(digest_s,digest_t,SHA_DIGEST_SIZE)==0) {
 
-        RLOGD("sha verify pass\n");
+        RLOGE("sha verify pass\n");
     
     }else{
-        RLOGD("delta sha verify fial!\n");
+        RLOGE("delta sha verify fial!\n");
         
         system("echo fota-interface >/sys/power/wake_unlock");
         return -1;
@@ -1214,7 +1233,7 @@
             fd_partition_a = mtk_device_wrap_open(partition_filename_a[i],O_RDWR);
             if (fd_partition_a < 0) {
                 err = errno;
-                RLOGD("+[UA]: Error opening id_a[%d] file: %s\n",i,strerror(errno));
+                RLOGE("+[UA]: Error opening id_a[%d] file: %s\n",i,strerror(errno));
                 system("echo fota-interface >/sys/power/wake_unlock");
                 return -err;
             }
@@ -1222,7 +1241,7 @@
             fd_partition_b = mtk_device_wrap_open(partition_filename_b[i],O_RDWR);
             if (fd_partition_b < 0) {
                 err = errno;
-                RLOGD("+[UA]: Error opening id_b[%d] file: %s\n",i,strerror(errno));
+                RLOGE("+[UA]: Error opening id_b[%d] file: %s\n",i,strerror(errno));
                 system("echo fota-interface >/sys/power/wake_unlock");
                 return -err;
             }            
@@ -1244,9 +1263,9 @@
             up_info.ota_run = i+1;
             save_fota_info();
 
-            RLOGD("+[UA]: Start upgrading %s.\n",partition_filename[i]);
+            RLOGE("+[UA]: Start upgrading %s.\n",partition_filename[i]);
             status = iot_patch(&ctx);
-            RLOGD("+[UA]: %s upgrade result:%d\n",partition_filename[i],status);
+            RLOGE("+[UA]: %s upgrade result:%d\n",partition_filename[i],status);
         
             //up_info.ota_run = 0;
         
@@ -1259,7 +1278,7 @@
 
                 fota_status.update_status[i].check_delta = PASS;
                 fota_status.update_status[i].check_rom = PASS;
-                RLOGD("+[UA]: %s upgrade success!!!\n",partition_filename[i]);
+                RLOGE("+[UA]: %s upgrade success!!!\n",partition_filename[i]);
                
             }else if(status == E_ROCK_INVALID_DELTA) {
                 fota_status.update_status[i].check_delta = ERROR;
@@ -1316,7 +1335,7 @@
             if (mtk_device_wrap_seek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0)
             {
                 err = errno;
-                RLOGD("+[UA]: mtk_device_wrap_seek df_delta err\n");
+                RLOGE("+[UA]: mtk_device_wrap_seek df_delta err\n");
                 system("echo fota-interface >/sys/power/wake_unlock");
                 return -1;
             }
@@ -1328,7 +1347,7 @@
             if (lseek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0)
             {
                 err = errno;
-                RLOGD("+[UA]: mtk_device_wrap_seek df_delta err\n");
+                RLOGE("+[UA]: mtk_device_wrap_seek df_delta err\n");
                 system("echo fota-interface >/sys/power/wake_unlock");
                 return -1;
             }
@@ -1337,7 +1356,7 @@
 	}
 
         if (memcmp(full_header, "full-ota", DELTA_FULL_HEARD_SIZE) != 0) {
-            RLOGD("+[UA]: invalid full delta header\r\n");
+            RLOGE("+[UA]: invalid full delta header\r\n");
             up_info.fota_flag[0] = 'e';
             up_info.fota_flag[1] = 'n';
             up_info.fota_flag[2] = 'd';
@@ -1384,7 +1403,7 @@
                 fd_partition_a = mtk_device_wrap_open(partition_filename_a[i-MAX_OTA_ROLE/2],O_RDWR);
                 if (fd_partition_a < 0) {
                     err = errno;
-                    RLOGD("+[UA]: Error opening full id_a[%d] file: %s\n",i,strerror(errno));
+                    RLOGE("+[UA]: Error opening full id_a[%d] file: %s\n",i,strerror(errno));
                     system("echo fota-interface >/sys/power/wake_unlock");
                     return -err;
                 }
@@ -1393,7 +1412,7 @@
                 fd_partition_b = mtk_device_wrap_open(partition_filename_b[i-MAX_OTA_ROLE/2],O_RDWR);
                 if (fd_partition_b < 0) {
                     err = errno;
-                    RLOGD("+[UA]: Error opening full_id_b[%d] file: %s\n",i,strerror(errno));
+                    RLOGE("+[UA]: Error opening full_id_b[%d] file: %s\n",i,strerror(errno));
                     system("echo fota-interface >/sys/power/wake_unlock");
                     return -err;
                 }
@@ -1404,7 +1423,7 @@
             up_info.ota_run = i+1;
             save_fota_info();
             retry_cnt = 0;
-            RLOGD("+[UA]: Start upgrading %s full.\n",partition_filename[i-MAX_OTA_ROLE/2]);
+            RLOGE("+[UA]: Start upgrading %s full.\n",partition_filename[i-MAX_OTA_ROLE/2]);
             do{
                 status = delta_copyto_nand(delta_offset,delta_head[i]);
                 if(g_addr_flag == 1)
@@ -1421,7 +1440,7 @@
         
             mtk_device_wrap_close(fd_curr);
         
-            RLOGD("+[UA]: %s full retry_cnt = %d\n",partition_filename[i-MAX_OTA_ROLE/2],retry_cnt);
+            RLOGE("+[UA]: %s full retry_cnt = %d\n",partition_filename[i-MAX_OTA_ROLE/2],retry_cnt);
         
             if (retry_cnt>3) {
                 if (status == 0) {
@@ -1435,7 +1454,7 @@
                 }
             }
         
-            RLOGD("+[UA]: %s full upgrade result:%d\n",partition_filename[i-MAX_OTA_ROLE/2],status);
+            RLOGE("+[UA]: %s full upgrade result:%d\n",partition_filename[i-MAX_OTA_ROLE/2],status);
 
             fota_status.update_result = status;
             fota_status.update_status[i].update_result = status;
@@ -1496,12 +1515,12 @@
 
     slot = (current_slot == 0) ? 1 : 0;
     
-    RLOGD("+[UA]: slot SLOT = %d\n",slot);
+    RLOGE("+[UA]: slot SLOT = %d\n",slot);
     
         if(switch_slot_flag==1)
         {
             module->setActiveBootSlot(module,slot);
-            RLOGD("+[UA]: upgrade is success!!!!\n");
+            RLOGE("+[UA]: upgrade is success!!!!\n");
         }
 
     fota_status.ota_run = 0;
@@ -1540,21 +1559,29 @@
 {
 
     int ret = 0;
-    
-#if 0
-    
-    printf("-********copy delta ***-\n");
-    test_write_delta("/data/delta",DEV_DELTA);
-
-#endif 
-    
-        ret = rock_update_main(0, 0, 0, 0, first_run, 1, 1, 1);
-        RLOGD("rock_update_main ret = %d\n", ret);
-        if(ret)
+    int exit_status = 0;
+    pthread_mutex_lock(&s_update_main_mutex);
+    ret = system("lynq-fota-tool 1");
+    pthread_mutex_unlock(&s_update_main_mutex);
+    RLOGE("rock_update_main ret = %d\n", ret);
+    if (WIFEXITED(ret))
+    {
+        exit_status = WEXITSTATUS(ret);
+        if(exit_status != 0)
         {
-            RLOGD("fota update fail!\n");
+            ret = exit_status -256;
         }
-        return ret;
+
+        RLOGE("rock_update_main exit_status: %d\n", ret);
+    }
+    else
+    {
+        RLOGE("rock_update_main core dump\n");
+        ret = -1;
+    }
+
+
+    return ret;
 }
 
 #endif
@@ -2041,7 +2068,7 @@
     int is_other_slot_bootable;
     const hw_module_t* hw_module;
     //xf.li@20230822 add for ab backup end
-    RLOGD("[+UP]: ******lynq_fota_func start******\n");
+    RLOGE("[+UP]: ******lynq_fota_func start******\n");
     //xf.li@20230822 add for ab backup start
     //----------get current slot and whether other slot  is bootable
     hw_module = &HAL_MODULE_INFO_SYM;
@@ -2050,20 +2077,20 @@
         ret = -EINVAL;
     }
     if (ret != 0) {
-        RLOGD("+[UA]: Error loading boot_control HAL implementation.\n");
+        RLOGE("+[UA]: Error loading boot_control HAL implementation.\n");
         return -1;
     }
     module = (boot_control_module_t*)hw_module;
     module->init(module);
     if (module == NULL) {
-        RLOGD("+[UA]: Error getting bootctrl module.\n");
+        RLOGE("+[UA]: Error getting bootctrl module.\n");
         return  -1;
     }
     current_slot = module->getCurrentSlot(module);
     other_slot = (current_slot == 0) ? 1 : 0;
     is_other_slot_bootable = module->isSlotBootable(module, other_slot);
     //-----------end
-    RLOGD("current slot:%u, is_other_slot_bootable : %d\n",current_slot, is_other_slot_bootable);
+    RLOGE("current slot:%u, is_other_slot_bootable : %d\n",current_slot, is_other_slot_bootable);
     //xf.li@20230822 add for ab backup end
 
     memset(&lynq_up_info, 0, sizeof(lynq_up_info));
@@ -2096,16 +2123,15 @@
         reboot_device();
     }
 
-
     if(lynq_up_info.ota_run != 0)
     { 
         //Power off, call UA
-        RLOGD("[+UP]: ***Power off, call UA***\n");
+        RLOGE("[+UP]: ***Power off, call UA***\n");
         ret = rock_update_main(0, 0, 0, 0, first_run, 1, 0, 1);
-        RLOGD("rock_update_main ret = %d\n", ret);
+        RLOGE("rock_update_main ret = %d\n", ret);
         if(ret) 
         {
-            RLOGD("fota update fail!\n");
+            RLOGE("fota update fail!\n");
         }
     }
 
@@ -2113,35 +2139,35 @@
         ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A')))
     {
         //Upgrade the other side and call UA
-        RLOGD("[+UP]: ***Upgrade the other side and call UA***\n");
+        RLOGE("[+UP]: ***Upgrade the other side and call UA***\n");
         ret = rock_update_main(0, 0, 0, 0, first_run, 0, 0, 0);
-        RLOGD("rock_update_main ret = %d\n", ret);
+        RLOGE("rock_update_main ret = %d\n", ret);
         if(ret)
         {
-            RLOGD("fota update fail!\n");
+            RLOGE("fota update fail!\n");
         }
     }
     //xf.li@20230822 add for ab backup start
     else if(is_other_slot_bootable == 0) 
     {
-        RLOGD("need backup\n");
+        RLOGE("need backup\n");
         ret = lynq_backup_main();
         if(ret != 0)
         {
-            RLOGD("ERROE: backup fail!!!\n");
+            RLOGE("ERROE: backup fail!!!\n");
         }
         else
         {
-            RLOGD("backup success!!!\n");
+            RLOGE("backup success!!!\n");
             module->setCompleteBackup(module, current_slot);
         }
     }
     else
     {
-        RLOGD("Don't need backup\n");
+        RLOGE("Don't need backup\n");
     }
     //xf.li@20230822 add for ab backup end
-    
+
     return 0;
 }    
 
@@ -2220,17 +2246,26 @@
 {
 
     int ret = 0;
-#if 0
-    printf("-********copy delta ***-\n");
-    test_write_delta("/data/delta",DEV_DELTA);
-#endif
-
-    ret = rock_update_main(0, 0, 0, 0, 1, 1, 0, 1);
-    RLOGD("rock_update_nrestart ret = %d\n", ret);
-    if(ret)
+    int exit_status = 0;
+    pthread_mutex_lock(&s_update_main_mutex);
+    ret = system("lynq-fota-tool 0");
+    pthread_mutex_unlock(&s_update_main_mutex);
+    if (WIFEXITED(ret))
     {
-        RLOGD("fota update fail!\n");
+        exit_status = WEXITSTATUS(ret);
+        if(exit_status != 0)
+        {
+            ret = exit_status -256;
+        }
+
+        RLOGE("lynq_fota_nrestart exit_status: %d\n", ret);
     }
+    else
+    {
+        RLOGE("lynq_fota_nrestart core dump\n");
+        ret = -1;
+    }
+
     return ret;
 }
 
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/lib_wapper/lynq-ftp-fota-wapper.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/lib_wapper/lynq-ftp-fota-wapper.c
index c48adca..1dcaab8 100755
--- a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/lib_wapper/lynq-ftp-fota-wapper.c
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/lib_wapper/lynq-ftp-fota-wapper.c
@@ -171,11 +171,28 @@
 {
     int ret = 0;
     char cmd[1024] = {0};
+    int exit_status = 0;
     RLOGE("+[UA]: cy rock_update_main\n");
     sprintf(cmd, "lynq-ftp-fota-tool %d %d %d %d %d %d %d %d", rom_base, backup_base, backup_len, read_rom_directly, first_run, switch_slot_flag, reboot_flag, backup_mode);
     pthread_mutex_lock(&s_update_main_mutex);
     ret = system(cmd);
     pthread_mutex_unlock(&s_update_main_mutex);
+    if (WIFEXITED(ret))
+    {
+        exit_status = WEXITSTATUS(ret);
+        if(exit_status != 0)
+        {
+            ret = exit_status -256;
+        }
+
+        RLOGE("rock_update_main exit_status: %d\n", ret);
+    }
+    else
+    {
+        RLOGE("rock_update_main core dump\n");
+        ret = -1;
+    }
+
     return ret;
 }
 
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp
index aaa36da..0ede8f1 100755
--- a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp
@@ -1059,7 +1059,11 @@
     int is_successful = module->isSlotMarkedSuccessful(module, current_slot);
 
     RLOGD("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
-
+    if((current_slot != 0)&&(current_slot != 1))
+    {
+        RLOGE("+[UA]: get current slot fail\n");
+        return -1;
+    }
 
 
     memset(&ctx, 0, sizeof(ctx));
diff --git a/LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool/lynq_fota_tool.c b/LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool/lynq_fota_tool.c
new file mode 100755
index 0000000..904c69d
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool/lynq_fota_tool.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <include/iot_rock.h>
+
+
+
+
+int main(int argc, char** argv)
+{
+
+    int ret = 0;
+    int first_run=1;
+    if(argc <= 1)
+    {
+        return -1;
+    }
+    if (strcmp(argv[1],"0") == 0)
+    {
+        ret = lynq_fota_nrestart();
+    }
+    else if(strcmp(argv[1],"1") == 0)
+    {
+        ret = lynq_rock_main(first_run);
+    }
+    else
+    {
+        return -1;
+    }
+    
+    
+    return ret;
+
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool/makefile b/LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool/makefile
new file mode 100644
index 0000000..8c3edc9
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/packages/apps/lynq-fota-tool/makefile
@@ -0,0 +1,44 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -g -Os \
+                -flto \
+                -fpermissive \
+                -fPIC \
+
+
+
+LOCAL_CFLAGS += -DLYNQ_SW_INSIDE_VERSION=\"$(LYNQ_CONFIG_VERSION)\"
+LOCAL_CFLAGS += -DLYNQ_SW_VERSION=\"$(LYNQ_CONFIG_SW_VERSION)\"
+
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(ROOT)$(includedir)/logger \
+  -I$(ROOT)$(includedir)/liblog \
+
+
+LOCAL_LIBS := \
+    -L. \
+    -ldl \
+    -lpthread \
+    -llynq-fota-run \
+
+SOURCES = $(wildcard *.c)
+
+EXECUTABLE = lynq-fota-tool
+
+OBJECTS=$(SOURCES:.c=.o)
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.c
+	$(CC) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)