[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5.c b/src/lynq/lib/liblynq-fota/MD5/md5.c
new file mode 100644
index 0000000..5dd9ff3
--- /dev/null
+++ b/src/lynq/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/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/main\0507919\051.c" "b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/main\0507919\051.c"
new file mode 100644
index 0000000..2d0b84b
--- /dev/null
+++ "b/src/lynq/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/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0502203\051.h" "b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0502203\051.h"
new file mode 100644
index 0000000..89939b0
--- /dev/null
+++ "b/src/lynq/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/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0505411\051.c" "b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/Backup/md5_encode\0505411\051.c"
new file mode 100644
index 0000000..106cee1
--- /dev/null
+++ "b/src/lynq/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/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/main.c.sisc b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/main.c.sisc
new file mode 100644
index 0000000..70e9321
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/main.c.sisc
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.c.sisc b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.c.sisc
new file mode 100644
index 0000000..934a8b0
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.c.sisc
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.h.sisc b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.h.sisc
new file mode 100644
index 0000000..5ecf4aa
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5.h.sisc
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.c.sisc b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.c.sisc
new file mode 100644
index 0000000..913feaa
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.c.sisc
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.h.sisc b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.h.sisc
new file mode 100644
index 0000000..09ce7a0
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/cache/parse/md5_encode.h.sisc
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.bookmarks.xml b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.bookmarks.xml
new file mode 100644
index 0000000..2e78352
--- /dev/null
+++ b/src/lynq/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/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siproj_settings.xml b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siproj_settings.xml
new file mode 100644
index 0000000..53541bc
--- /dev/null
+++ b/src/lynq/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/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siwork b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siwork
new file mode 100644
index 0000000..bcd4a37
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_0628.si4project/md5_0628.siwork
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/MD5/md5_encode.c b/src/lynq/lib/liblynq-fota/MD5/md5_encode.c
new file mode 100644
index 0000000..10ccab7
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/MD5/md5_encode.c
@@ -0,0 +1,141 @@
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "md5.h"
+#include "mtk_device_wrap.h"
+#include "liblog/lynq_deflog.h"
+
+
+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 2*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;
+}
+
+#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/src/lynq/lib/liblynq-fota/include/iot_rock.h b/src/lynq/lib/liblynq-fota/include/iot_rock.h
new file mode 100644
index 0000000..b87bf51
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/include/iot_rock.h
@@ -0,0 +1,121 @@
+#ifndef _IOT_ROCK_H_

+#define _IOT_ROCK_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 PATCH_SYSTEM    (1)

+#define PATCH_BOOT      (2)

+#define PATCH_TEE       (3)

+#define PATCH_MD1IMG    (4)

+#define PATCH_VBMETA   (5)

+#define PATCH_BL33      (6) 

+#define FULL_SYSTEM    (7)

+#define FULL_BOOT      (8)

+#define FULL_TEE       (9)

+#define FULL_MD1IMG    (10)

+#define FULL_VBMETA    (11)

+#define FULL_BL33      (12) 

+

+#define MAX_OTA_ROLE   (12) 

+

+

+

+#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 {

+	unsigned int sys;	//system 差分包大小

+	unsigned int boot;	//boot   差分包大小

+    unsigned int tee;	//tee    差分包大小

+    unsigned int md1img;	//md1img    差分包大小

+	unsigned int vbmeta;   //vbmeta   差分包大小

+    unsigned int bl33;	//bl33   差分包大小

+	unsigned int full_sys;	//system 整包大小

+	unsigned int full_boot;	//boot   

+    unsigned int full_tee;	//tee    整包大小

+    unsigned int full_md1img;	//    整包大小

+	unsigned int full_vbmeta;	//vbmeta  整包大小

+    unsigned int full_bl33;	//bl33   整包大小

+} DELTA_HEAD;

+

+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*6 + 4*6)

+#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);

+//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);

+#endif

+

+

+

diff --git a/src/lynq/lib/liblynq-fota/include/iot_rock_ipl.h b/src/lynq/lib/liblynq-fota/include/iot_rock_ipl.h
new file mode 100644
index 0000000..77c7c2a
--- /dev/null
+++ b/src/lynq/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/src/lynq/lib/liblynq-fota/include/md5.h b/src/lynq/lib/liblynq-fota/include/md5.h
new file mode 100644
index 0000000..f0e3a1b
--- /dev/null
+++ b/src/lynq/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/src/lynq/lib/liblynq-fota/include/md5_encode.h b/src/lynq/lib/liblynq-fota/include/md5_encode.h
new file mode 100644
index 0000000..d106eac
--- /dev/null
+++ b/src/lynq/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 lynq_md5_file_verfy(char* filePath, char* file_md5);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/lynq/lib/liblynq-fota/include/sha.h b/src/lynq/lib/liblynq-fota/include/sha.h
new file mode 100644
index 0000000..05f9941
--- /dev/null
+++ b/src/lynq/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/src/lynq/lib/liblynq-fota/lib/libiotpatch.a b/src/lynq/lib/liblynq-fota/lib/libiotpatch.a
new file mode 100644
index 0000000..3f4138e
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/lib/libiotpatch.a
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/lib/libmd5.a b/src/lynq/lib/liblynq-fota/lib/libmd5.a
new file mode 100644
index 0000000..209dbf4
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/lib/libmd5.a
Binary files differ
diff --git a/src/lynq/lib/liblynq-fota/makefile b/src/lynq/lib/liblynq-fota/makefile
new file mode 100644
index 0000000..6198bcb
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/makefile
@@ -0,0 +1,107 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -DRIL_SHLIB \
+                -DATCI_PARSE \
+                -DKEEP_ALIVE \
+                -DECALL_SUPPORT \
+                -fpermissive \
+
+CFLAGS += -fPIC -O2 $(INCLUDE) -D_LARGEFILE64_SOURCE
+
+$(warning ################# C2K support: $(RAT_CONFIG_C2K_SUPPORT))
+ifeq ($(strip $(RAT_CONFIG_C2K_SUPPORT)), yes)
+    LOCAL_CFLAGS += -DC2K_SUPPORT
+
+endif
+
+ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsds)
+    LOCAL_CFLAGS += -DANDROID_SIM_COUNT_2 \
+                     -DANDROID_MULTI_SIM \
+                     -DMODE_DSDS
+endif
+
+ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsss)
+    LOCAL_CFLAGS += -DMODE_DSSS
+endif
+
+$(warning ################# TARGET_PLATFORM: $(TARGET_PLATFORM))
+ifeq ($(strip $(TARGET_PLATFORM)), mt2731)
+#$(warning #################add for debug $(ROOT), $(includedir))
+$(warning ################# TARGET_PLATFORM_MT2731)
+    LOCAL_CFLAGS += -DTARGET_PLATFORM_MT2731 \
+                    -DMD_93_SUPPORT
+else ifeq ($(strip $(TARGET_PLATFORM)), mt2635)
+$(warning ################# TARGET_PLATFORM_MT2635)
+    LOCAL_CFLAGS += -DTARGET_PLATFORM_MT2635 \
+                    -DMD_90_SUPPORT
+endif
+
+$(warning ################# liblynq_fota 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 \
+    -llog \
+    -lstdc++ \
+    -liotpatch \
+	-lmd5	\
+    -lnandapi  \
+    -lbootctrl  \
+    -llynq-log \
+    -llynq-protcl \
+
+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)
+
+
diff --git a/src/lynq/lib/liblynq-fota/rock_ua/rock_ua.c b/src/lynq/lib/liblynq-fota/rock_ua/rock_ua.c
new file mode 100644
index 0000000..23f85f5
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/rock_ua/rock_ua.c
@@ -0,0 +1,1874 @@
+// 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 <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+//#include <hardware/hardware.h>
+
+//#define off64_t __off64_t
+
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+#include <sys/reboot.h>
+
+
+
+#include "liblog/lynq_deflog.h"
+#include "mtk_device_wrap.h"
+
+#define ROCK_DEFAULT_BLOCK_SIZE 0x20000
+#define ROCK_RAM_LEN  (1024*1024)
+
+
+#define ROCK_BACKUP_LEN ROCK_DEFAULT_BLOCK_SIZE
+
+
+#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_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         "/dev/disk/by-partlabel/bl2"
+#define DEV_BL33        "/dev/disk/by-partlabel/bl33"
+
+#define DEV_MISC        "/dev/disk/by-partlabel/misc"
+
+
+
+//#define DEV_DELTA       "/dev/disk/by-partlabel/delta"
+#define DEV_DELTA       "/dev/disk/by-partlabel/delta"
+
+
+
+#define FILE_UPDATE_STATE  "/data/.update_status"
+#define FILE_FOTA_STATE    "/data/.fota_status"
+
+#define NAND_PAGE_SIZE  2048
+
+
+#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"
+
+
+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_vbmeta_a,fd_vbmeta_b;
+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];
+
+DELTA_HEAD  da_head;
+
+OTA_STATUS  fota_status;
+
+
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+boot_control_module_t* module;
+
+
+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);
+	//fd_update_status = open(FILE_UPDATE_STATE,O_RDWR);
+
+    if (fd_fota_status < 0) {
+        err = errno;
+        LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+    
+	write(fd_fota_status, &fota_status,sizeof(fota_status));
+	sync();
+	
+	close(fd_fota_status);
+}
+
+
+void rock_progress(void* ctx, int percent) {
+	int i = 0;
+    rock_trace(ctx, "rock update progress %d\n", 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 (mtk_device_wrap_seek(fd_delta, offset + delta_offset, SEEK_SET) < 0) {
+        err = -errno;
+        rock_trace(ctx, "mtk_device_wrap_seek df_delta err\n");
+		return err;
+    }
+
+    do {
+
+        ret = mtk_device_wrap_read(fd_delta, dest, size);
+
+        if (ret == 0) {
+            break;
+        } else if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            err = -errno;
+            rock_trace(ctx," Error reading metadata file\n");
+
+            mtk_device_wrap_close(fd_delta);
+
+            return err;
+        }
+        size -= ret;
+        dest += ret;
+    } while(size > 0);
+
+    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;
+
+    //fd_delta = mtk_device_wrap_open(DEV_DELTA,O_RDONLY);
+    fd_delta = mtk_device_wrap_open(DEV_DELTA,O_RDWR);
+
+    if (fd_delta < 0) {
+        err = errno;
+        LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+
+    fd_update_status = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777);
+	//fd_update_status = open(FILE_UPDATE_STATE,O_RDWR);
+
+    if (fd_update_status < 0) {
+        err = errno;
+        LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+        return -err;
+    }
+
+    return 0;
+}
+
+
+
+
+
+static int close_dev_fd(int fd)
+{
+    mtk_device_wrap_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) {
+	    LYERRLOG("+[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);
+        LYERRLOG("+[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) {
+	    LYERRLOG("+[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);
+        LYERRLOG("+[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 (mtk_device_wrap_seek(fd_delta, start, SEEK_SET) < 0) {
+        LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+		return -1;
+    }
+ 
+ 	if (mtk_device_wrap_seek(fd_curr, 0, SEEK_SET) < 0) {
+        LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+		return -1;
+    }
+ 
+ 
+    do {
+
+        ret = mtk_device_wrap_read(fd_delta, delta_data, NAND_PAGE_SIZE);
+
+        if (ret == 0) {
+            break;
+        } else if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            err = -errno;
+
+            return err;
+        }
+  
+        size -= NAND_PAGE_SIZE;
+		//mtk_device_wrap_write(fd_curr,delta_data,NAND_PAGE_SIZE);
+		mtk_device_wrap_write(fd_curr,delta_data,ret);
+
+    } while(size > 0);
+  
+ 
+ return 0;
+ 
+}
+
+
+
+
+
+unsigned char ram_buffer[ROCK_RAM_LEN];
+
+
+
+
+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 status,err,start;
+    int ret = 0;
+	int i = 0;
+	int retry_cnt = 0;
+	
+	IOT_UPDATA_CONTEXT ctx;
+	UPDATE_INFO up_info;
+	//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];
+
+	
+    hw_module = &HAL_MODULE_INFO_SYM;
+
+    if (!hw_module ||
+        strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+        ret = -EINVAL;
+    }
+    if (ret != 0) {
+        LYERRLOG("+[UA]: Error loading boot_control HAL implementation.\n");
+        return -1;
+    }
+
+    module = (boot_control_module_t*)hw_module;
+    module->init(module);
+
+
+    if (module == NULL) {
+        LYERRLOG("+[UA]: Error getting bootctrl module.\n");
+	    return  -1;
+    }
+     /*************    Bootctrl Init  End  *************/
+
+    current_slot = module->getCurrentSlot(module);
+    
+    int is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+  
+    LYVERBLOG("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.update_nvram = 0;
+	ctx.read_rom_directly = read_rom_directly;
+    //ctx.first_run = first_run;
+    ctx.first_run = 1;
+
+	
+    init_dev_fd();
+	
+
+    memset(&up_info, 0, sizeof(up_info));
+	
+	memset(&fota_status,0,sizeof(fota_status));
+
+	
+    lseek(fd_update_status,0,SEEK_SET);
+    read(fd_update_status,(unsigned char *)&up_info,sizeof(up_info));
+
+	LYVERBLOG("+[UA]: up_info.ota_run = %d\n",up_info.ota_run);
+	
+	
+	if ((up_info.ota_run>PATCH_BL33)||(up_info.ota_run<PATCH_SYSTEM))
+	{
+		up_info.ota_run = 0;
+	}	
+	
+	up_info.ota_run = 0;
+	
+	if((up_info.fota_flag[0]=='A')&&(up_info.fota_flag[1]=='-')&&(up_info.fota_flag[2]=='B')){
+		update_mode = MODE_A2B;
+	}else if((up_info.fota_flag[0]=='B')&&(up_info.fota_flag[1]=='-')&&(up_info.fota_flag[2]=='A')){
+		update_mode = MODE_B2A;
+	}else{
+		update_mode = MODE_NORMAL;
+	}
+	
+	LYVERBLOG("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag);
+	LYVERBLOG("+[UA]: update_mode = %d\n",update_mode);
+	
+    memset(&da_head, 0, sizeof(da_head));
+
+	mtk_device_wrap_read(fd_delta, (unsigned char*)&da_head, sizeof(da_head));
+
+
+    rock_trace(&ctx, "da_head.sys:%d,da_head.boot:%d,da_head.tee:%d,da_head.md1img=%d,da_head.vbmeta=%d,da_head.bl33=%d\n", da_head.sys, da_head.boot,da_head.tee,da_head.md1img,da_head.vbmeta,da_head.bl33);
+    rock_trace(&ctx, "da_head.fullsys:%d,da_head.fullboot:%d,da_head.fulltee:%d,da_head.fullmd1img=%d,da_head.fullvbmeta=%d,da_head.fullbl33=%d\n", da_head.full_sys, da_head.full_boot,da_head.full_tee, da_head.full_md1img,da_head.full_vbmeta,da_head.full_bl33);
+
+    
+    if (da_head.sys>0) {
+	    fota_status.update_status[PATCH_SYSTEM - 1].need_update = 1;
+	}
+	if (da_head.boot>0) {
+		fota_status.update_status[PATCH_BOOT - 1].need_update = 1;
+	}
+	if (da_head.tee>0) {
+		fota_status.update_status[PATCH_TEE - 1].need_update = 1;
+	}
+	if (da_head.md1img>0) {
+		fota_status.update_status[PATCH_MD1IMG - 1].need_update = 1;
+	}
+	
+	if (da_head.vbmeta>0) {
+		fota_status.update_status[PATCH_VBMETA - 1].need_update = 1;
+	}
+	if (da_head.bl33>0) {
+		fota_status.update_status[PATCH_BL33 - 1].need_update = 1;
+	}
+	
+	if (da_head.full_sys>0) {
+		fota_status.update_status[FULL_SYSTEM - 1].need_update = 1;
+	}
+	if (da_head.full_boot>0) {
+		fota_status.update_status[FULL_BOOT - 1].need_update = 1;
+	}
+	if (da_head.full_tee>0) {
+		fota_status.update_status[FULL_TEE - 1].need_update = 1;
+	}
+	if (da_head.full_md1img>0) {
+		fota_status.update_status[FULL_MD1IMG - 1].need_update = 1;
+	}
+	if (da_head.full_bl33>0) {
+		fota_status.update_status[FULL_BL33 - 1].need_update = 1;
+	}
+
+	if(da_head.full_vbmeta>0) {
+		fota_status.update_status[FULL_VBMETA - 1].need_update = 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.vbmeta + da_head.bl33;
+	
+
+    if ((da_head.sys>0) && (up_info.ota_run <= PATCH_SYSTEM))
+	{
+
+        now_patch = PATCH_SYSTEM;
+        delta_offset = DELTA_HEARD_SIZE;
+  
+#if 0		
+		if (up_info.ota_run == PATCH_SYSTEM) 
+		{
+			ctx.first_run = 0;
+
+		}else{
+		    ctx.first_run = 1;
+		}
+
+		//up_info.ota_run = 0;
+
+		
+
+        if(current_slot==SLOT_B) {
+	        fd_system_a = mtk_device_wrap_open(DEV_SYSTEM_A,O_RDWR);
+            if (fd_system_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_system_a;
+		}else{
+	        fd_system_b = mtk_device_wrap_open(DEV_SYSTEM_B,O_RDWR);
+            if (fd_system_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_system_b;			
+		}
+
+#endif 
+
+
+        ctx.first_run = 1;   // always
+		
+	
+		
+		if(current_slot==SLOT_B) {
+		    system("flash_eraseall /dev/disk/by-partlabel/system_a");
+		} else {
+			system("flash_eraseall /dev/disk/by-partlabel/system_b");
+		}
+
+		
+//        if(current_slot==SLOT_B) {
+	        fd_system_a = mtk_device_wrap_open(DEV_SYSTEM_A,O_RDWR);
+            if (fd_system_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_system_a;
+//		}else{
+	        fd_system_b = mtk_device_wrap_open(DEV_SYSTEM_B,O_RDWR);
+            if (fd_system_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_system_b;			
+//		}
+		
+		if(current_slot==SLOT_B){
+			fd_read  = fd_system_b;
+			fd_write = fd_system_a;	
+		} else {
+			fd_read  = fd_system_a;
+			fd_write = fd_system_b;
+		}
+
+		
+		fota_status.ota_run = PATCH_SYSTEM;
+        fota_status.update_status[PATCH_SYSTEM -1].check_delta = WAIT;
+		fota_status.update_status[PATCH_SYSTEM -1].check_rom = WAIT;
+		fota_status.update_status[PATCH_SYSTEM-1].update_result= WAIT;
+
+		save_fota_status();
+		
+		up_info.ota_run = PATCH_SYSTEM;
+		lseek(fd_update_status,0,SEEK_SET);
+	    write(fd_update_status, &up_info,sizeof(up_info));
+		sync();
+		LYVERBLOG("+[UA]: Start upgrading system.\n");
+        status = iot_patch(&ctx);
+		LYVERBLOG("+[UA]: system upgrade result:%d\n",status);
+		
+        //fota_status.ota_run = 0;
+		fota_status.update_status[PATCH_SYSTEM -1].update_result= status; 
+		fota_status.update_result= status;
+
+        if((status == 0)||(status ==1))
+        {
+
+            fota_status.update_status[PATCH_SYSTEM -1].check_delta = PASS;
+		    fota_status.update_status[PATCH_SYSTEM -1].check_rom = PASS;
+               
+		}else if(status == E_ROCK_INVALID_DELTA) {
+            fota_status.update_status[PATCH_SYSTEM -1].check_delta = ERROR;
+		    fota_status.update_status[PATCH_SYSTEM -1].check_rom = WAIT;
+		}else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+            fota_status.update_status[PATCH_SYSTEM -1].check_delta = PASS;
+		    fota_status.update_status[PATCH_SYSTEM -1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+            close(fd_update_status);
+			
+			mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write);
+	
+            return status;
+		}
+			mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write);
+		
+
+    }
+	
+	
+	
+	
+
+    if ((da_head.boot>0) && (up_info.ota_run <= PATCH_BOOT))
+	{
+
+        now_patch = PATCH_BOOT;
+        delta_offset = DELTA_HEARD_SIZE + da_head.sys;
+
+		
+		if (up_info.ota_run == PATCH_BOOT)
+		{
+			ctx.first_run = 0;
+
+		}else{
+		    ctx.first_run = 1;
+		}
+
+		if(current_slot==SLOT_B) {
+		    system("flash_eraseall /dev/disk/by-partlabel/boot_a");
+		} else {
+			system("flash_eraseall /dev/disk/by-partlabel/boot_b");
+		}
+		
+        //if(current_slot==SLOT_B) {
+	        fd_boot_a = mtk_device_wrap_open(DEV_BOOT_A,O_RDWR);
+            if (fd_boot_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_boot_a;
+//		}else{
+	        fd_boot_b = mtk_device_wrap_open(DEV_BOOT_B,O_RDWR);
+            if (fd_boot_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_boot_b;			
+//		}
+
+
+		if(current_slot==SLOT_B){
+			fd_read  = fd_boot_b;
+			fd_write = fd_boot_a;	
+		} else {
+			fd_read  = fd_boot_a;
+			fd_write = fd_boot_b;
+		}
+
+		fota_status.ota_run = PATCH_BOOT;
+        fota_status.update_status[PATCH_BOOT-1].check_delta = WAIT;
+		fota_status.update_status[PATCH_BOOT-1].check_rom = WAIT;
+		fota_status.update_status[PATCH_BOOT-1].update_result= WAIT;
+
+		save_fota_status();
+
+		
+	    up_info.ota_run = PATCH_BOOT;
+		lseek(fd_update_status,0,SEEK_SET);
+	    write(fd_update_status, &up_info,sizeof(up_info));
+		sync();
+		
+		
+		
+        LYVERBLOG("+[UA]: Start upgrading boot.\n");
+        status = iot_patch(&ctx);
+		LYVERBLOG("+[UA]: boot upgrade result:%d\n",status);
+        //up_info.ota_run = 0;
+
+        //fota_status.ota_run = 0;
+		fota_status.update_status[PATCH_BOOT-1].update_result= status; 
+		fota_status.update_result= status;
+
+        if((status == 0)||(status ==1))
+        {
+
+            fota_status.update_status[PATCH_BOOT-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_BOOT-1].check_rom = PASS;
+               
+		}else if(status == E_ROCK_INVALID_DELTA) {
+            fota_status.update_status[PATCH_BOOT-1].check_delta = ERROR;
+		    fota_status.update_status[PATCH_BOOT-1].check_rom = WAIT;
+		}else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+            fota_status.update_status[PATCH_BOOT-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_BOOT-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+            close(fd_update_status);
+			mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write);
+	
+            return status;
+		}
+			mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write);
+
+    }
+	
+	
+	
+	
+
+    if ((da_head.tee>0) && (up_info.ota_run <= PATCH_TEE))
+	{
+
+        now_patch = PATCH_TEE;
+        delta_offset = DELTA_HEARD_SIZE + da_head.sys + da_head.boot;
+ 
+		
+		if (up_info.ota_run == PATCH_TEE) 
+		{
+			ctx.first_run = 0;
+
+		}else{
+		    ctx.first_run = 1;
+		}
+
+
+		if(current_slot==SLOT_B) {
+		    system("flash_eraseall /dev/disk/by-partlabel/tee_a");
+		} else {
+			system("flash_eraseall /dev/disk/by-partlabel/tee_b");
+		}
+//        if(current_slot==SLOT_B) {
+	        fd_tee_a = mtk_device_wrap_open(DEV_TEE_A,O_RDWR);
+            if (fd_tee_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_tee_a;
+//		}else{
+	        fd_tee_b = mtk_device_wrap_open(DEV_TEE_B,O_RDWR);
+            if (fd_tee_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_tee_b;			
+//		}
+
+
+		if(current_slot==SLOT_B){
+			fd_read  = fd_tee_b;
+			fd_write = fd_tee_a;	
+		} else {
+			fd_read  = fd_tee_a;
+			fd_write = fd_tee_b;
+		}
+
+		fota_status.ota_run = PATCH_TEE;
+        fota_status.update_status[PATCH_TEE-1].check_delta = WAIT;
+		fota_status.update_status[PATCH_TEE-1].check_rom = WAIT;
+		fota_status.update_status[PATCH_TEE-1].update_result= WAIT;
+		
+		save_fota_status();
+		
+		up_info.ota_run = PATCH_TEE;
+
+		lseek(fd_update_status,0,SEEK_SET);
+	    write(fd_update_status, &up_info,sizeof(up_info));
+		sync();
+
+        LYVERBLOG("+[UA]: Start upgrading tee.\n");
+        status = iot_patch(&ctx);
+		LYVERBLOG("+[UA]: tee upgrade result:%d\n",status);
+        //up_info.ota_run = 0;
+        //fota_status.ota_run = 0;
+		fota_status.update_status[PATCH_TEE-1].update_result= status; 
+		fota_status.update_result= status;
+
+        if((status == 0)||(status ==1))
+        {
+
+            fota_status.update_status[PATCH_TEE-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_TEE-1].check_rom = PASS;
+               
+		}else if(status == E_ROCK_INVALID_DELTA) {
+            fota_status.update_status[PATCH_TEE-1].check_delta = ERROR;
+		    fota_status.update_status[PATCH_TEE-1].check_rom = WAIT;
+		}else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+            fota_status.update_status[PATCH_TEE-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_TEE-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+			mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write);
+            return status;
+		}
+		mtk_device_wrap_close(fd_read);
+		mtk_device_wrap_close(fd_write);
+
+    }
+	
+	
+	
+
+    if ((da_head.md1img>0) && (up_info.ota_run <= PATCH_MD1IMG))
+	{
+
+        now_patch = PATCH_MD1IMG;
+        delta_offset = DELTA_HEARD_SIZE + da_head.sys + da_head.boot + da_head.tee;
+
+		
+		if (up_info.ota_run == PATCH_MD1IMG) 
+		{
+			ctx.first_run = 0;
+
+		}else{
+		    ctx.first_run = 1;
+		}
+
+
+		if(current_slot==SLOT_B) {
+		    system("flash_eraseall /dev/disk/by-partlabel/md1img_a");
+		} else {
+			system("flash_eraseall /dev/disk/by-partlabel/md1img_b");
+		}
+//        if(current_slot==SLOT_B) {
+	        fd_md1img_a = mtk_device_wrap_open(DEV_MD1IMG_A,O_RDWR);
+            if (fd_md1img_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_md1img_a;
+//		}else{
+	        fd_md1img_b = mtk_device_wrap_open(DEV_MD1IMG_B,O_RDWR);
+            if (fd_md1img_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_md1img_b;			
+//		}
+
+
+		if(current_slot==SLOT_B){
+			fd_read  = fd_md1img_b;
+			fd_write = fd_md1img_a;	
+		} else {
+			fd_read  = fd_md1img_a;
+			fd_write = fd_md1img_b;
+		}
+
+		fota_status.ota_run = PATCH_MD1IMG;
+        fota_status.update_status[PATCH_MD1IMG-1].check_delta = WAIT;
+		fota_status.update_status[PATCH_MD1IMG-1].check_rom = WAIT;
+		fota_status.update_status[PATCH_MD1IMG-1].update_result= WAIT;
+
+		save_fota_status();
+		
+		up_info.ota_run = PATCH_MD1IMG;
+
+		lseek(fd_update_status,0,SEEK_SET);
+	    write(fd_update_status, &up_info,sizeof(up_info));
+		sync();		
+		
+
+        LYVERBLOG("+[UA]: Start upgrading md1img.\n");
+        status = iot_patch(&ctx);
+		LYVERBLOG("+[UA]: md1img upgrade result:%d\n",status);
+
+        //fota_status.ota_run = 0;
+		fota_status.update_status[PATCH_MD1IMG-1].update_result= status; 
+		fota_status.update_result= status;
+
+        if((status == 0)||(status ==1))
+        {
+
+            fota_status.update_status[PATCH_MD1IMG-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_MD1IMG-1].check_rom = PASS;
+               
+		}else if(status == E_ROCK_INVALID_DELTA) {
+            fota_status.update_status[PATCH_MD1IMG-1].check_delta = ERROR;
+		    fota_status.update_status[PATCH_MD1IMG-1].check_rom = WAIT;
+		}else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+            fota_status.update_status[PATCH_MD1IMG-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_MD1IMG-1].check_rom = ERROR;
+
+		}else{
+		
+			//fota_status.update_status[PATCH_MD1IMG -1].check_delta = PASS;
+			//fota_status.update_status[PATCH_MD1IMG -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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+	        mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write);
+            return status;
+		}
+        mtk_device_wrap_close(fd_read);
+		mtk_device_wrap_close(fd_write);
+
+
+    }
+	
+	
+	
+	
+    
+
+	if ((da_head.vbmeta>0) && (up_info.ota_run <= PATCH_VBMETA))
+	{
+
+        now_patch = PATCH_VBMETA;
+        delta_offset = DELTA_HEARD_SIZE + da_head.sys + da_head.boot + da_head.tee + da_head.md1img;
+
+		
+		if (up_info.ota_run == PATCH_VBMETA) 
+		{
+			ctx.first_run = 0;
+
+		}else{
+		    ctx.first_run = 1;
+		
+		}
+
+		if(current_slot==SLOT_B) {
+		    system("flash_eraseall /dev/disk/by-partlabel/vbmeta_a");
+		} else {
+			system("flash_eraseall /dev/disk/by-partlabel/vbmeta_b");
+		}
+//		if(current_slot==SLOT_B) {
+	        fd_vbmeta_a = mtk_device_wrap_open(DEV_VBMETA_A,O_RDWR);
+            if (fd_vbmeta_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_vbmeta_a;
+//		}else{
+	        fd_vbmeta_b = mtk_device_wrap_open(DEV_VBMETA_B,O_RDWR);
+            if (fd_vbmeta_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+//			fd_curr = fd_vbmeta_b;			
+//		}
+
+		if(current_slot==SLOT_B){
+			fd_read  = fd_vbmeta_b;
+			fd_write = fd_vbmeta_a;	
+		} else {
+			fd_read  = fd_vbmeta_a;
+			fd_write = fd_vbmeta_b;
+		}
+		fota_status.ota_run = PATCH_VBMETA;
+        fota_status.update_status[PATCH_VBMETA-1].check_delta = WAIT;
+		fota_status.update_status[PATCH_VBMETA-1].check_rom = WAIT;
+		fota_status.update_status[PATCH_VBMETA-1].update_result= WAIT;
+
+		save_fota_status();
+		
+		up_info.ota_run = PATCH_VBMETA;
+
+		lseek(fd_update_status,0,SEEK_SET);
+	    write(fd_update_status, &up_info,sizeof(up_info));
+		sync();
+
+        LYVERBLOG("+[UA]: Start upgrading vbmeta.\n");
+        status = iot_patch(&ctx);
+		LYVERBLOG("+[UA]: vbmeta upgrade result:%d\n",status);
+		up_info.ota_run = 0;
+		//fota_status.ota_run = 0;
+		fota_status.update_status[PATCH_VBMETA-1].update_result= status; 
+		fota_status.update_result= status;
+
+        
+		if((status == 0)||(status ==1))
+        {
+			fota_status.update_status[PATCH_VBMETA-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_VBMETA-1].check_rom = PASS;
+               
+		}else if(status == E_ROCK_INVALID_DELTA) {
+            fota_status.update_status[PATCH_VBMETA-1].check_delta = ERROR;
+		    fota_status.update_status[PATCH_VBMETA-1].check_rom = WAIT;
+		}else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+            fota_status.update_status[PATCH_VBMETA-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_VBMETA-1].check_rom = ERROR;
+		}else{
+		
+			//fota_status.update_status[PATCH_MD1IMG -1].check_delta = PASS;
+			//fota_status.update_status[PATCH_MD1IMG -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;
+            
+			lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+	        mtk_device_wrap_close(fd_read);
+			mtk_device_wrap_close(fd_write); 
+            return status;
+		}
+        mtk_device_wrap_close(fd_read);
+		mtk_device_wrap_close(fd_write);
+
+
+    }
+
+    if ((da_head.bl33>0) && (up_info.ota_run <= PATCH_BL33))
+	{
+
+        now_patch = PATCH_BL33;
+        delta_offset = DELTA_HEARD_SIZE + da_head.sys + da_head.boot + da_head.tee + da_head.md1img + da_head.vbmeta;
+
+		if (up_info.ota_run == PATCH_BL33) 
+		{
+			ctx.first_run = 0;
+
+		}else{
+		    ctx.first_run = 1;
+		}
+
+	    fd_bl33 = mtk_device_wrap_open(DEV_BL33,O_RDWR);
+        if (fd_bl33 < 0) {
+            err = errno;
+            LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+            return -err;
+        }
+	    fd_curr = fd_bl33;
+
+		fota_status.ota_run = PATCH_BL33;
+        fota_status.update_status[PATCH_BL33-1].check_delta = WAIT;
+		fota_status.update_status[PATCH_BL33-1].check_rom = WAIT;
+		fota_status.update_status[PATCH_BL33-1].update_result= WAIT;
+
+		save_fota_status();
+		up_info.ota_run = PATCH_BL33;
+
+		lseek(fd_update_status,0,SEEK_SET);
+	    write(fd_update_status, &up_info,sizeof(up_info));
+		sync();
+        LYVERBLOG("+[UA]: Start upgrading bl33.\n");
+        status = iot_patch(&ctx);
+		LYVERBLOG("+[UA]: bl33 upgrade result:%d\n",status);
+
+		up_info.ota_run = 0;
+        //fota_status.ota_run = 0;
+		fota_status.update_status[PATCH_BL33-1].update_result= status; 
+        fota_status.update_result= status;
+        if((status == 0)||(status ==1))
+        {
+
+            fota_status.update_status[PATCH_BL33-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_BL33-1].check_rom = PASS;
+               
+		}else if(status == E_ROCK_INVALID_DELTA) {
+            fota_status.update_status[PATCH_BL33-1].check_delta = ERROR;
+		    fota_status.update_status[PATCH_BL33-1].check_rom = WAIT;
+		}else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) {
+            fota_status.update_status[PATCH_BL33-1].check_delta = PASS;
+		    fota_status.update_status[PATCH_BL33-1].check_rom = ERROR;
+
+		}else{
+		
+			//fota_status.update_status[PATCH_BL33 -1].check_delta = PASS;
+			//fota_status.update_status[PATCH_BL33 -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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+	        mtk_device_wrap_close(fd_curr);
+			sync();
+			close(fd_update_status);
+            return status;
+		}
+        mtk_device_wrap_close(fd_curr);
+
+    }
+		
+
+    
+	//if(current_slot==SLOT_B)
+		
+    
+	
+	if ((da_head.full_sys>0)|| (da_head.full_boot>0)|| (da_head.full_tee>0)||(da_head.full_md1img>0)||(da_head.full_vbmeta>0)||(da_head.full_bl33>0))
+	{
+
+	    now_patch = 0;
+		up_info.ota_run = 0;
+		
+		memset(&fota_status,0,sizeof(fota_status));
+		fota_status.switch_slot = WAIT;
+		save_fota_status();
+		
+	    if (mtk_device_wrap_seek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0) {
+            err = errno;
+            LYERRLOG("+[UA]: mtk_device_wrap_seek df_delta err\n");
+		    return -1;
+        }
+		
+		mtk_device_wrap_read(fd_delta, full_header, DELTA_FULL_HEARD_SIZE);
+		
+
+	    if (memcmp(full_header, "full-ota", DELTA_FULL_HEARD_SIZE) != 0) {
+	        LYERRLOG("+[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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+	        //mtk_device_wrap_close(fd_curr);
+			sync();
+			close(fd_update_status);
+
+			for (i = FULL_SYSTEM;i<=FULL_BL33;i++){
+                if (fota_status.update_status[i-1].need_update ==1) {
+                    fota_status.ota_run = i;
+					fota_status.update_status[i-1].check_delta = ERROR;
+					fota_status.update_status[i-1].check_rom= WAIT;
+					fota_status.update_status[i-1].update_result= ERROR;
+				}
+			}
+            fota_status.update_result = ERROR;
+			save_fota_status();
+	        return -1;
+	    }
+	}
+	
+	
+
+	
+	
+	if(da_head.full_sys>0) {
+	
+	    delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE;
+	    
+		if(current_slot==SLOT_B) {
+	        fd_system_a = mtk_device_wrap_open(DEV_SYSTEM_A,O_RDWR);
+            if (fd_system_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_system_a;
+		}else{
+	        fd_system_b = mtk_device_wrap_open(DEV_SYSTEM_B,O_RDWR);
+            if (fd_system_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_system_b;			
+		}
+        fota_status.ota_run = FULL_SYSTEM;
+        save_fota_status();
+		
+		retry_cnt = 0;
+		LYVERBLOG("+[UA]: Start upgrading system full.\n");
+        do {
+            status = delta_copyto_nand(delta_offset,da_head.full_sys);
+		
+	        ROCK_SHA_FILE(fd_delta,delta_offset,da_head.full_sys,digest_s);
+		    ROCK_SHA_FILE(fd_curr,0,da_head.full_sys,digest_t);
+		    retry_cnt++;
+        }while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+		
+		mtk_device_wrap_close(fd_curr);
+		
+		LYVERBLOG("+[UA]: system full retry_cnt = %d\n",retry_cnt);
+        
+		if (retry_cnt>3) {
+		    if (status == 0) {
+				status = retry_cnt;
+			}
+			if(current_slot==SLOT_B) {
+			    nand_copyto_nand(DEV_SYSTEM_B,DEV_SYSTEM_A);
+			}
+		    else{
+				nand_copyto_nand(DEV_SYSTEM_A,DEV_SYSTEM_B);
+			}
+		}
+		
+		LYVERBLOG("+[UA]: system full upgrade result:%d\n",status);
+
+		fota_status.update_result = status;
+		fota_status.update_status[FULL_SYSTEM-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+            return status;
+		}		
+		
+	
+	}
+	
+	
+	
+	if(da_head.full_boot>0) {
+	
+	    delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE + da_head.full_sys;
+	    
+		if(current_slot==SLOT_B) {
+	        fd_boot_a = mtk_device_wrap_open(DEV_BOOT_A,O_RDWR);
+            if (fd_boot_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_boot_a;
+		}else{
+	        fd_boot_b = mtk_device_wrap_open(DEV_BOOT_B,O_RDWR);
+            if (fd_boot_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_boot_b;					
+		}
+		fota_status.ota_run = FULL_BOOT;
+        save_fota_status();
+        retry_cnt = 0;
+		LYVERBLOG("+[UA]: Start upgrading boot full.\n");
+        do {
+            status = delta_copyto_nand(delta_offset,da_head.full_boot);
+			ROCK_SHA_FILE(fd_delta,delta_offset,da_head.full_boot,digest_s);
+		    ROCK_SHA_FILE(fd_curr,0,da_head.full_boot,digest_t);
+		    retry_cnt++;	
+		}while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+		
+		LYVERBLOG("+[UA]: boot full retry_cnt = %d\n",retry_cnt);
+		mtk_device_wrap_close(fd_curr);
+		
+		if (retry_cnt>3) {
+		    if (status == 0) {
+				status = retry_cnt;
+			}
+			if(current_slot==SLOT_B) {
+			    nand_copyto_nand(DEV_BOOT_B,DEV_BOOT_A);
+			}
+		    else{
+				nand_copyto_nand(DEV_BOOT_A,DEV_BOOT_B);
+			}
+		}
+		
+		
+		LYVERBLOG("+[UA]: boot full upgrade result:%d\n",status);
+		fota_status.update_result = status;
+		fota_status.update_status[FULL_BOOT-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+            return status;
+		}			
+	
+	}
+	
+	
+	if(da_head.full_tee>0) {
+	
+	    delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE + da_head.full_sys + da_head.full_boot;
+	    
+		if(current_slot==SLOT_B) {
+	        fd_tee_a = mtk_device_wrap_open(DEV_TEE_A,O_RDWR);
+            if (fd_tee_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_tee_a;
+		}else{
+	        fd_tee_b = mtk_device_wrap_open(DEV_TEE_B,O_RDWR);
+            if (fd_tee_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_tee_b;			
+		}
+		fota_status.ota_run = FULL_TEE;
+        save_fota_status();
+        retry_cnt = 0;
+		LYVERBLOG("+[UA]: Start upgrading tee full.\n");
+        do {
+            status = delta_copyto_nand(delta_offset,da_head.full_tee);
+			ROCK_SHA_FILE(fd_delta,delta_offset,da_head.full_tee,digest_s);
+		    ROCK_SHA_FILE(fd_curr,0,da_head.full_tee,digest_t);
+		    retry_cnt++;	
+		}while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+		mtk_device_wrap_close(fd_curr);
+		LYVERBLOG("+[UA]: tee full retry_cnt = %d\n",retry_cnt);		
+		if (retry_cnt>3) {
+		    if (status == 0) {
+				status = retry_cnt;
+			}
+			if(current_slot==SLOT_B) {
+			    nand_copyto_nand(DEV_TEE_B,DEV_TEE_A);
+			}
+		    else{
+				nand_copyto_nand(DEV_TEE_A,DEV_TEE_B);
+			}
+		}
+		
+		printf("+[UA] tee full upgrade result:%d\n",status);
+		fota_status.update_result = status;
+		fota_status.update_status[FULL_TEE-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+            return status;
+		}		
+
+	
+	}
+	
+
+	if(da_head.full_md1img>0) {
+	
+	    delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE + da_head.full_sys + da_head.full_tee;
+	    
+		if(current_slot==SLOT_B) {
+	        fd_md1img_a = mtk_device_wrap_open(DEV_MD1IMG_A,O_RDWR);
+            if (fd_md1img_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_md1img_a;
+		}else{
+	        fd_md1img_b = mtk_device_wrap_open(DEV_MD1IMG_B,O_RDWR);
+            if (fd_md1img_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_md1img_b;			
+		}
+		fota_status.ota_run = FULL_MD1IMG;
+        save_fota_status();
+        retry_cnt = 0;
+		LYVERBLOG("+[UA]: Start upgrading md1img full.\n");
+        do {       
+		    status = delta_copyto_nand(delta_offset,da_head.full_md1img);
+			ROCK_SHA_FILE(fd_delta,delta_offset,da_head.full_md1img,digest_s);
+		    ROCK_SHA_FILE(fd_curr,0,da_head.full_md1img,digest_t);
+		    retry_cnt++;	
+		}while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+		mtk_device_wrap_close(fd_curr);
+		
+		LYVERBLOG("+[UA]: md1img full retry_cnt = %d\n",retry_cnt);
+		if (retry_cnt>3) {
+		    if (status == 0) {
+				status = retry_cnt;
+			}
+			if(current_slot==SLOT_B) {
+			    nand_copyto_nand(DEV_MD1IMG_B,DEV_MD1IMG_A);
+			}
+		    else{
+				nand_copyto_nand(DEV_MD1IMG_A,DEV_MD1IMG_B);
+			}
+		}
+				
+		LYVERBLOG("+[UA]: md1img upgrade result:%d\n",status);
+		fota_status.update_result = status;
+		fota_status.update_status[FULL_MD1IMG-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+            return status;
+		}
+		
+	
+	}
+		
+	
+	if(da_head.full_vbmeta>0) {
+	
+	    delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE + da_head.full_sys + da_head.full_tee + da_head.full_md1img;
+	    
+		if(current_slot==SLOT_B) {
+	        fd_vbmeta_a = mtk_device_wrap_open(DEV_VBMETA_A,O_RDWR);
+            if (fd_vbmeta_a < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_vbmeta_a;
+		}else{
+	        fd_vbmeta_b = mtk_device_wrap_open(DEV_VBMETA_B,O_RDWR);
+            if (fd_vbmeta_b < 0) {
+                err = errno;
+                LYERRLOG("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+                return -err;
+            }
+			fd_curr = fd_vbmeta_b;			
+		}
+		fota_status.ota_run = FULL_VBMETA;
+        save_fota_status();
+        retry_cnt = 0;
+		LYVERBLOG("+[UA]: Start upgrading vbmeta full.\n");
+		do {       
+		    status = delta_copyto_nand(delta_offset,da_head.full_vbmeta);
+			ROCK_SHA_FILE(fd_delta,delta_offset,da_head.full_vbmeta,digest_s);
+		    ROCK_SHA_FILE(fd_curr,0,da_head.full_vbmeta,digest_t);
+		    retry_cnt++;	
+		}while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+		mtk_device_wrap_close(fd_curr);
+		
+		LYVERBLOG("+[UA]: vbmeta full retry_cnt = %d\n",retry_cnt);
+		if (retry_cnt>3) {
+		    if (status == 0) {
+				status = retry_cnt;
+			}
+			if(current_slot==SLOT_B) {
+			    nand_copyto_nand(DEV_VBMETA_B,DEV_VBMETA_A);
+			}
+		    else{
+				nand_copyto_nand(DEV_VBMETA_A,DEV_VBMETA_B);
+			}
+		}
+				
+		LYVERBLOG("+[UA]: vbmeta upgrade result:%d\n",status);
+		fota_status.update_result = status;
+		fota_status.update_status[FULL_VBMETA-1].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;
+            lseek(fd_update_status,0,SEEK_SET);
+			write(fd_update_status, &up_info,sizeof(up_info));
+			sync();
+			close(fd_update_status);
+            return status;
+		}
+		
+	
+	}	
+	
+	if(da_head.full_bl33>0) {
+		
+	}
+
+
+
+    if(update_mode == MODE_NORMAL){ //need A VS B
+	    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;
+    lseek(fd_update_status,0,SEEK_SET);       
+	write(fd_update_status, &up_info,sizeof(up_info));
+    sync();
+           
+    close_dev_fd(fd_delta);
+
+    //close_dev_fd(fd_curr);
+	
+
+	
+    close(fd_update_status);
+	sync();
+	
+
+	slot = (current_slot == 0) ? 1 : 0;
+	
+	LYVERBLOG("+[UA]: slot SLOT = %d\n\n",slot);
+	
+	if(update_mode==MODE_NORMAL){
+	    module->setActiveBootSlot(module,slot);
+		LYVERBLOG("+[UA]: upgrade is success!!!!\n");
+	}
+
+    fota_status.ota_run = 0;
+	fota_status.switch_slot = PASS;
+	fota_status.update_result = status;
+    save_fota_status();
+	
+	if(update_mode==MODE_NORMAL){
+	LYVERBLOG("+[UA]: reboot_device\n");
+	reboot_device();
+	}	
+	
+	return status;
+}
+
+
+
+static void rock_fail_handler() {
+	
+}
+
+
+
+
+/* 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);
+	if(ret) {
+		rock_fail_handler();
+	}
+	return ret;
+}
+
+#endif
+
+//lt add @2021.9.23 for  deal with power down \ backup or upgrade.
+int lynq_fota_func(void) 
+{
+
+ int fd;
+ int first_run = 1;   
+ UPDATE_INFO lynq_up_info;
+
+ 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);
+
+ if(lynq_up_info.ota_run != 0) { 
+      //Power off, call UA
+	    LYVERBLOG("[+UP]: ***Power off, call UA***\n");
+	   lynq_rock_main(first_run);
+ }else 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
+	  LYVERBLOG("[+UP]: ***Upgrade the other side and call UA***\n");
+	   lynq_rock_main(first_run);
+ }
+/*
+ else{
+      //Normal procedure before, to check the upgrade package
+//	LYVERBLOG("[+UP]: ***Normal procedure before, to check the upgrade package***\n");
+//	lynq_rock_main(first_run);
+ }*/
+ return 0;
+}	
diff --git a/src/lynq/lib/liblynq-fota/rock_ua/sha.c b/src/lynq/lib/liblynq-fota/rock_ua/sha.c
new file mode 100644
index 0000000..1989113
--- /dev/null
+++ b/src/lynq/lib/liblynq-fota/rock_ua/sha.c
@@ -0,0 +1,382 @@
+/* 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  2048
+
+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;
+	char data[NAND_PAGE_SIZE];
+	
+
+	mtk_device_wrap_seek(fd_sha, offset, SEEK_SET);
+    SHA_CTX ctx;
+    SHA_init(&ctx);
+
+	do {    
+        size = mtk_device_wrap_read(fd_sha,data,NAND_PAGE_SIZE);   
+		SHA_update(&ctx, data, size);
+		totle_size -= NAND_PAGE_SIZE;
+
+	}while(totle_size>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;
+}