Squashed 'LYNQ_PUBLIC/' content from commit 79d8f932f

git-subtree-dir: LYNQ_PUBLIC
git-subtree-split: 79d8f932fb4ebc4b5aec6c5ace97634912394272
Change-Id: If2527ba937f56fe989487bf71e996f7cfd9fbe61
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5.c b/IC_src/mtk/lib/liblynq-fota/MD5/md5.c
new file mode 100755
index 0000000..5dd9ff3
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/main\0507919\051.c" "b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/main\0507919\051.c"
new file mode 100755
index 0000000..2d0b84b
--- /dev/null
+++ "b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/main\0507919\051.c"
@@ -0,0 +1,12 @@
+#include <stdio.h>

+#incldue "md5_encode.h"

+

+int main()

+{

+	int ret;

+	ret=md5_file_verfy("111","222");

+	printf("ret:%d\n",ret);

+

+	return 0;	

+	

+}
\ No newline at end of file
diff --git "a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0502203\051.h" "b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0502203\051.h"
new file mode 100755
index 0000000..89939b0
--- /dev/null
+++ "b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0502203\051.h"
@@ -0,0 +1,15 @@
+
+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);
+
+int md5_file_verfy(char* filePath, char* file_md5);
+
+
+
+
+
diff --git "a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0505411\051.c" "b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0505411\051.c"
new file mode 100755
index 0000000..106cee1
--- /dev/null
+++ "b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0505411\051.c"
@@ -0,0 +1,82 @@
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "md5.h"
+
+
+
+
+int ota_file_open(char* path, char* flag)
+{
+#if 0
+	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);
+}
+
+
+int md5_file_verfy(char* filePath, char* file_md5)
+{
+	int ret = FALSE;
+	int handle;
+
+	printf("calc file md5: %s\n", filePath);
+	handle = ota_file_open(filePath, "rb",0);	
+	if(handle >= 0){
+		ota_file_seek(handle, 0, SEEK_END,0);
+		
+		{
+			int read_len = 0; 
+			unsigned char buffer[1024] = {0};
+			unsigned char decrypt[16];
+			int i;
+			MD5_CTX md5;  
+			MD5Init(&md5);
+			while ((read_len = ota_file_read(buffer, 1, 1024, handle,0))){   
+				MD5Update(&md5, (unsigned char*)buffer, read_len); 
+			}
+			MD5Final(&md5, (unsigned char*)decrypt);
+			memset(buffer, 0, 1024);
+			for(i = 0; i < 16; i++)  
+			{  
+				sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);  
+			}
+			printf("md5:%s\n", buffer);
+			printf("md5:%s\n", file_md5);
+			
+			ret = strcmp((const char*)buffer, (const char*)file_md5) == 0;
+		}
+		ota_file_close(handle,0);
+	}
+	return ret;
+}
+
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/main.c.sisc b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/main.c.sisc
new file mode 100755
index 0000000..70e9321
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/main.c.sisc
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.c.sisc b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.c.sisc
new file mode 100755
index 0000000..934a8b0
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.c.sisc
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.h.sisc b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.h.sisc
new file mode 100755
index 0000000..5ecf4aa
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.h.sisc
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.c.sisc b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.c.sisc
new file mode 100755
index 0000000..913feaa
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.c.sisc
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.h.sisc b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.h.sisc
new file mode 100755
index 0000000..09ce7a0
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.h.sisc
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.bookmarks.xml b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.bookmarks.xml
new file mode 100755
index 0000000..2e78352
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.bookmarks.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>

+<SourceInsightBookmarks

+	AppVer="4.00.0096"

+	AppVerMinReader="4.00.0009"

+	>

+	<Bookmarks/>

+</SourceInsightBookmarks>

diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siproj_settings.xml b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siproj_settings.xml
new file mode 100755
index 0000000..53541bc
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siproj_settings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>

+<ProjectSettings

+	AppVer="4.00.0096"

+	AppVerMinReader="4.00.0034"

+	GlobalConfiguration="1"

+	GlobalWorkspace="0"

+	LocalsInDb="0"

+	IndexMembers="1"

+	IndexFragments="1"

+	UseMasterFileList="0"

+	SourceDir="..\"

+	BackupDir="%PROJECT_DATA_DIR%\Backup"

+	MasterFileList="%PROJECT_SOURCE_DIR%\%PROJECT_NAME%_filelist.txt"

+	IsImportProject="0"

+	>

+	<Imports>

+		<ImportedLibs/>

+	</Imports>

+	<ParseConditions>

+		<Defines/>

+	</ParseConditions>

+</ProjectSettings>

diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siwork b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siwork
new file mode 100755
index 0000000..bcd4a37
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siwork
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/MD5/md5_encode.c b/IC_src/mtk/lib/liblynq-fota/MD5/md5_encode.c
new file mode 100755
index 0000000..918d634
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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/IC_src/mtk/lib/liblynq-fota/include/iot_rock.h b/IC_src/mtk/lib/liblynq-fota/include/iot_rock.h
new file mode 100755
index 0000000..a6e6821
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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);

+

+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/IC_src/mtk/lib/liblynq-fota/include/iot_rock_ipl.h b/IC_src/mtk/lib/liblynq-fota/include/iot_rock_ipl.h
new file mode 100755
index 0000000..77c7c2a
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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/IC_src/mtk/lib/liblynq-fota/include/md5.h b/IC_src/mtk/lib/liblynq-fota/include/md5.h
new file mode 100755
index 0000000..f0e3a1b
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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/IC_src/mtk/lib/liblynq-fota/include/md5_encode.h b/IC_src/mtk/lib/liblynq-fota/include/md5_encode.h
new file mode 100755
index 0000000..c3e5d38
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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/IC_src/mtk/lib/liblynq-fota/include/sha.h b/IC_src/mtk/lib/liblynq-fota/include/sha.h
new file mode 100755
index 0000000..05f9941
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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/IC_src/mtk/lib/liblynq-fota/lib/libiotpatch.a b/IC_src/mtk/lib/liblynq-fota/lib/libiotpatch.a
new file mode 100755
index 0000000..023c16e
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/lib/libiotpatch.a
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/lib/libmd5.a b/IC_src/mtk/lib/liblynq-fota/lib/libmd5.a
new file mode 100755
index 0000000..1cebf1f
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/lib/libmd5.a
Binary files differ
diff --git a/IC_src/mtk/lib/liblynq-fota/makefile b/IC_src/mtk/lib/liblynq-fota/makefile
new file mode 100755
index 0000000..4fe83ea
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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.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)
\ No newline at end of file
diff --git a/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c b/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c
new file mode 100755
index 0000000..c970ce1
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/rock_ua/rock_ua.c
@@ -0,0 +1,2079 @@
+// 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
+
+
+
+//#define DEV_DELTA       "/dev/disk/by-partlabel/delta"
+#if 0
+#define DEV_DELTA       "/dev/disk/by-partlabel/delta"
+#else
+#define DEV_DELTA       "/dev/mtd41"    
+#endif
+
+
+
+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_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];
+
+
+
+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);
+}
+
+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){
+    //rock_trace(ctx, "rock update progress block %d\n", 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 (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 */
+
+
+
+static int init_dev_fd()
+{
+
+    int err;
+    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);
+    fd_delta = open(lynq_fota_addr,O_RDWR);
+
+    if (fd_delta < 0) {
+        err = errno;
+        RLOGD("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+
+    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));
+        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 delta_data[ROCK_DEFAULT_BLOCK_SIZE];
+     
+    fd_source = 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) {
+        mtk_device_wrap_close(fd_target);
+        close(fd_source);
+        RLOGD("+[UA]: open target  error\n");
+        return 1;
+    } 
+    
+    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) {
+        RLOGD("+[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);
+        RLOGD("+[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 (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];
+
+
+    RLOGD("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
+    {
+        RLOGD("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)
+    {
+        RLOGD("+[UA]: can't open file /tmp/update_flag.\n");
+        return -1;
+    }
+    close(fd);
+//xf.li@20230830 add for ab_recover end
+    hw_module = &HAL_MODULE_INFO_SYM;
+
+    if (!hw_module ||
+        strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+        ret = -EINVAL;
+    }
+    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();
+    lynq_fota_grab_artial_wake_lock();
+     /*************    Bootctrl Init  End  *************/
+
+    current_slot = module->getCurrentSlot(module);
+    
+    int is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+  
+    RLOGD("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
+
+
+
+    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())
+    {
+        RLOGD("+[UA]: get fota addr error\n");
+        system("echo fota-interface >/sys/power/wake_unlock");
+        return E_ROCK_FOTA_ADDR;
+    }
+
+
+    memset(&fota_status,0,sizeof(fota_status));
+    RLOGD("+[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;
+    }
+    
+    RLOGD("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag);
+    RLOGD("+[UA]: update_mode = %d\n",update_mode);
+    
+    //memset(&da_head, 0, sizeof(da_head));
+
+    //read(fd_delta, (unsigned char*)&da_head, sizeof(da_head));
+
+    memset(&delta_head, 0, sizeof(delta_head));
+    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];
+            
+        }
+        RLOGD("+[UA]: %s,delta size = %d\n",partition_filename[i],delta_head[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];
+        }
+        RLOGD("+[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)
+        {
+            RLOGD("cpu core is error\n");
+            system("echo fota-interface >/sys/power/wake_unlock");
+            return -1;
+        }
+        else
+        {
+            RLOGD("cpu core match\n");
+        }
+    }
+    else if(core_num == 4)
+    {
+        RLOGD("the cpu core is four!!!\n");
+    }
+    else
+    {
+        RLOGD("read the cpu core fail");
+        system("echo fota-interface >/sys/power/wake_unlock");
+        return -1;
+    }
+
+    fota_status.switch_slot = WAIT;
+    save_fota_status();
+
+    //delta_size = da_head.sys + da_head.boot + da_head.tee + da_head.md1img + da_head.md1dsp + da_head.vbmeta + da_head.oemapp + da_head.oemapp2 + da_head.medmcu+da_head.bl33;
+    
+    //sha_size = da_head.full_sys + da_head.full_boot + da_head.full_tee + da_head.full_md1img + da_head.full_md1dsp + da_head.full_vbmeta + da_head.full_oemapp + da_head.full_oemapp2 + da_head.full_medmcu+da_head.full_bl33
+
+
+
+
+    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);
+    
+    lseek(fd_delta, sha_size + sizeof(delta_head), SEEK_SET);
+    read(fd_delta, digest_s, SHA_DIGEST_SIZE);
+    convert_hex(digest_s,str_sha);
+    RLOGD("+[UA]: delta save sha = %s\n",str_sha);
+    
+    ROCK_SHA_FILE_COMMON(fd_delta,sizeof(delta_head),sha_size,digest_t);
+    memset(str_sha,0,40);
+    convert_hex(digest_t,str_sha);
+    RLOGD("+[UA]: delta calc sha = %s\n",str_sha);
+    
+    if(memcmp(digest_s,digest_t,SHA_DIGEST_SIZE)==0) {
+    
+        RLOGD("sha verify pass\n");
+    
+    }else{
+        RLOGD("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;
+                RLOGD("+[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;
+                RLOGD("+[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;
+            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();
+
+            RLOGD("+[UA]: Start upgrading %s.\n",partition_filename[i]);
+            status = iot_patch(&ctx);
+            RLOGD("+[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;
+                RLOGD("+[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;
+        
+        memset(&fota_status,0,sizeof(fota_status));
+        fota_status.switch_slot = WAIT;
+        save_fota_status();
+        
+        if (lseek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0) {
+            err = errno;
+            RLOGD("+[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) {
+            RLOGD("+[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;
+                    RLOGD("+[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;
+                    RLOGD("+[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;
+            RLOGD("+[UA]: Start upgrading %s full.\n",partition_filename[i-MAX_OTA_ROLE/2]);
+            do{
+                status = delta_copyto_nand(delta_offset,delta_head[i]);
+
+                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);
+        
+            RLOGD("+[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]);
+                }
+            }
+        
+            RLOGD("+[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;
+    
+    RLOGD("+[UA]: slot SLOT = %d\n",slot);
+    
+        if(switch_slot_flag==1)
+        {
+            module->setActiveBootSlot(module,slot);
+            RLOGD("+[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;
+    
+#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)
+        {
+            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];
+    if(strcmp(name, "oemapp") == 0)
+    {
+        RLOGD("lynq_check_oemapp oemapp");
+        if(system("df -lh|grep oemapp |grep -v oemapp2") != 0)
+        {
+            return 0;
+        }
+        else
+        {
+            return 1;
+        }
+    }
+    else if(strcmp(name, "oemapp2") == 0)
+    {
+        RLOGD("lynq_check_oemapp oemapp2");
+        if(system("df -lh|grep oemapp2") != 0)
+        {
+            return 0;
+        }
+        else
+        {
+            return 1;
+        }
+    }
+}
+
+//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
+    RLOGD("[+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) {
+        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;
+    }
+    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);
+    //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
+        RLOGD("[+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);
+        if(ret) 
+        {
+            RLOGD("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
+        RLOGD("[+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);
+        if(ret)
+        {
+            RLOGD("fota update fail!\n");
+        }
+    }
+    //xf.li@20230822 add for ab backup start
+    else if(is_other_slot_bootable == 0) 
+    {
+        RLOGD("need backup\n");
+        ret = lynq_backup_main();
+        if(ret != 0)
+        {
+            RLOGD("ERROE: backup fail!!!\n");
+        }
+        else
+        {
+            RLOGD("backup success!!!\n");
+            module->setCompleteBackup(module, current_slot);
+        }
+    }
+    else
+    {
+        RLOGD("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/IC_src/mtk/lib/liblynq-fota/rock_ua/sha.c b/IC_src/mtk/lib/liblynq-fota/rock_ua/sha.c
new file mode 100755
index 0000000..5ac6b53
--- /dev/null
+++ b/IC_src/mtk/lib/liblynq-fota/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;
+}