Add mbtk_otad
Change-Id: I472a8f3acdc6207a17800352bf7ce5e6fff167a9
diff --git a/build.sh b/build.sh
index cf928cd..4943e94 100755
--- a/build.sh
+++ b/build.sh
@@ -96,7 +96,7 @@
[ -f out/bin/mbtk_servicesd ] && cp -f out/bin/mbtk_servicesd $1/bin
[ -f out/bin/aboot-tiny ] && cp -f out/bin/aboot-tiny $1/bin
[ -f out/bin/mbtk_rtpd ] && cp -f out/bin/mbtk_rtpd $1/bin
-
+ [ -f out/bin/mbtk_otad ] && cp -f out/bin/mbtk_otad $1/bin
# Copy GNSS(5311) bin files.
[ -f mbtk/aboot-tiny/files/release/jacana_fw.bin ] && cp -f mbtk/aboot-tiny/files/release/jacana_fw.bin $1/etc
diff --git a/mbtk/Makefile b/mbtk/Makefile
index c5926ef..20257fa 100755
--- a/mbtk/Makefile
+++ b/mbtk/Makefile
@@ -15,7 +15,7 @@
DIRS += mbtk_rild mbtk_servicesd mbtk_sdk_ready
endif
-DIRS += aboot-tiny mbtk_adbd mbtk_logd mbtk_utils mbtk_utils_linux mbtk_gnssd mbtk_rtpd
+DIRS += aboot-tiny mbtk_adbd mbtk_logd mbtk_utils mbtk_utils_linux mbtk_gnssd mbtk_rtpd mbtk_otad
# Build test file.
DIRS += test
diff --git a/mbtk/mbtk_otad/Makefile b/mbtk/mbtk_otad/Makefile
new file mode 100755
index 0000000..28ba357
--- /dev/null
+++ b/mbtk/mbtk_otad/Makefile
@@ -0,0 +1,40 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_otad
+
+INC_DIR += \
+ -I$(LOCAL_PATH)/inc
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lprop2uci -lubus -lubox -lutil -luci -lhttpclient
+
+# -Wno-error=unused-function
+CFLAGS +=
+
+DEFINE += -DCONFIG_AB_SYSTEM
+
+MY_FILES_PATH:=$(LOCAL_PATH)/src
+
+LOCAL_SRC_FILES = $(wildcard src/*.c) $(wildcard src/*.cpp)
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/bin/mbtk_otad
+
+all: $(dtarget)
+
+$(dtarget): $(OBJS)
+ @echo " BIN $@"
+ $(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+
+%.o:%.c
+ $(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+ $(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+ rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/mbtk_otad/inc/getfotav.c b/mbtk/mbtk_otad/inc/getfotav.c
new file mode 100755
index 0000000..fb65265
--- /dev/null
+++ b/mbtk/mbtk_otad/inc/getfotav.c
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <string.h>
+
+#define FOTA_FBFVERSION_IMAGEID 0x464F5456 //"FOTV"
+
+#if 0
+static int get_fota_version(const char *fname, char *mversion, size_t msize)
+{
+ FILE *fp;
+ int ret;
+ fp = fopen(fname, "rb");
+ if (fp == NULL)
+ {
+ perror("fopen");
+ return 1;
+ }
+ ret = 0;
+ do
+ {
+ int num_img;
+ size_t sz;
+ char buf[64];
+ sz = fread(buf, 1, 32, fp);
+ if (sz < 32 || strncmp(buf, "Marvell_FBF", 11)) /* check FBF magic */
+ {
+ ret = 2;
+ break;
+ }
+ sz = fread(buf, 1, 2, fp);
+ if (sz < 2 || buf[0] != 11 || buf[1] != 0) /* check format version */
+ {
+ ret = 3;
+ break;
+ }
+ ret = fseek(fp, 0x13C, SEEK_SET);
+ if (ret)
+ {
+ perror("fseek");
+ ret = 1;
+ break;
+ }
+ sz = fread(&num_img, 1, 4, fp);
+ if (sz < 4 || num_img <= 0) /* check number of images */
+ {
+ ret = 4;
+ break;
+ }
+ ret = 5; /* not found */
+ while (num_img--)
+ {
+ sz = fread(buf, 1, 52, fp);
+ if (sz < 52) /* check ImageStruct_11 size */
+ {
+ ret = 6;
+ break;
+ }
+ if (*(int *)buf == FOTA_FBFVERSION_IMAGEID) /* check image ID */
+ {
+ unsigned offset = ((int *)buf)[5];
+ offset <<= 13; /* 8KB sectors */
+ ret = fseek(fp, offset, SEEK_SET);
+ if (ret)
+ {
+ perror("fseek");
+ ret = 1;
+ break;
+ }
+ sz = fread(mversion, 1, msize, fp);
+ if (sz < msize || strnlen(mversion, sz) == sz) /* check ASCIIZ */
+ {
+ ret = 7;
+ break;
+ }
+ if (strncmp(mversion, "OTA", 3)) /* check prefix */
+ {
+ /* treat as successful */
+ }
+ else
+ {
+ char *p;
+ switch (mversion[3])
+ {
+ case '0': /* FOTA */
+ p = strchr(mversion, ';');
+ if (p)
+ {
+ sz = p - mversion - 4;
+ memmove(mversion, mversion + 4, sz);
+ mversion[sz] = '\0';
+ }
+ else
+ {
+ ret = 8;
+ }
+ break;
+ case '4': /* DFOTA */
+ p = strchr(mversion, ';');
+ if (p)
+ {
+ char *q = p + 1;
+ p = strchr(q, ';');
+ if (p)
+ {
+ sz = p - q;
+ memmove(mversion, q, sz);
+ mversion[sz] = '\0';
+ }
+ else
+ {
+ ret = 9;
+ }
+ }
+ else
+ {
+ ret = 8;
+ }
+ break;
+ default:
+ ret = 7;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ } while (0);
+ fclose(fp);
+ return ret;
+}
+#endif
diff --git a/mbtk/mbtk_otad/inc/otad.h b/mbtk/mbtk_otad/inc/otad.h
new file mode 100755
index 0000000..b4f61e0
--- /dev/null
+++ b/mbtk/mbtk_otad/inc/otad.h
@@ -0,0 +1,23 @@
+#ifndef _OTAD_H_
+#define _OTAD_H_
+
+#include "mbtk_log.h"
+
+
+#define OTA_DEBUG LOGD
+#define OTA_ERR LOGE
+#define UBUS_UNIX_SOCKET "/var/run/ubus/ubus.sock"
+
+enum {
+ OTA_TYPE_HTTP,
+ OTA_TYPE_UDP,
+ OTA_TYPE_SD,
+};
+
+
+// Add by liubin
+void revision_out_find(char *data, int len, unsigned int processed_cnt);
+int revision_out_update();
+// End by liubin
+#endif
+
diff --git a/mbtk/mbtk_otad/inc/tim.c b/mbtk/mbtk_otad/inc/tim.c
new file mode 100755
index 0000000..b7c2ae5
--- /dev/null
+++ b/mbtk/mbtk_otad/inc/tim.c
@@ -0,0 +1,471 @@
+#include "tim.h"
+
+#define DTIM_MAX_SIZE (128 * 1024)
+
+#if 0
+
+static const char *id2str(unsigned int id)
+{
+ switch (id) {
+ case IMAGE_ID_ARBEL:
+ return "ARBEL";
+ case IMAGE_ID_DTIM_A:
+ return "DTIM_A";
+ case IMAGE_ID_DTIM_B:
+ return "DTIM_B";
+ case IMAGE_ID_KERNEL:
+ return "KERNEL";
+ case IMAGE_ID_MSA:
+ return "MSA";
+ case IMAGE_ID_OEMD:
+ return "OEMD";
+ case IMAGE_ID_RF:
+ return "RF";
+ case IMAGE_ID_ROOTFS:
+ return "ROOTFS";
+ case IMAGE_ID_UBOOT:
+ return "UBOOT";
+ default:
+ OTA_ERR("Unkown id: 0x%x\n", id);
+ return "NULL";
+ }
+}
+#endif
+
+static int SetTIMPointers( void *pStartAddr, TIM *pTIM_h)
+{
+ pTIM_h->pConsTIM = (pCTIM) pStartAddr; // Overlap Contant Part of TIM with actual TIM...
+
+ if ((pTIM_h->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER) ||
+ (pTIM_h->pConsTIM->VersionBind.Version < TIM_3_2_00)) {
+ /* incorrect tim */
+ pTIM_h->pConsTIM = NULL;
+ return -1;
+ }
+
+ // Assign a pointer to start of Images Area
+ pTIM_h->pImg = (pIMAGE_INFO_3_4_0) (pStartAddr + sizeof (CTIM));
+
+ // Assign a pointer to start of Key Area
+ if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00)
+ pTIM_h->pKey = (pKEY_MOD_3_4_0) ((UINT_T)pTIM_h->pImg + ((pTIM_h->pConsTIM->NumImages) * sizeof (IMAGE_INFO_3_4_0)));
+ else
+ pTIM_h->pKey = (pKEY_MOD_3_4_0) ((UINT_T)pTIM_h->pImg + ((pTIM_h->pConsTIM->NumImages) * sizeof (IMAGE_INFO_3_2_0)));
+
+ // Assign a pointer to start of reserved area
+ if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00)
+ pTIM_h->pReserved = (PUINT) ((UINT_T)pTIM_h->pKey + ((pTIM_h->pConsTIM->NumKeys) * sizeof (KEY_MOD_3_4_0)));
+ else if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_3_00)
+ pTIM_h->pReserved = (PUINT) ((UINT_T)pTIM_h->pKey + ((pTIM_h->pConsTIM->NumKeys) * sizeof (KEY_MOD_3_3_0)));
+ else
+ pTIM_h->pReserved = (PUINT) ((UINT_T)pTIM_h->pKey + ((pTIM_h->pConsTIM->NumKeys) * sizeof (KEY_MOD_3_2_0)));
+
+ // Assign a pointer to start of DS
+ pTIM_h->pTBTIM_DS = (pPLAT_DS) ((UINT_T)pTIM_h->pReserved + pTIM_h->pConsTIM->SizeOfReserved);
+ return (NoError);
+}
+
+#if 0
+static void dump_dtim(pTIM t)
+{
+ int i;
+ pIMAGE_INFO_3_4_0 pImg;
+ OTA_DEBUG("### Image in dtim ###\n");
+ OTA_DEBUG("Images number: %d\n", t->pConsTIM->NumImages);
+ for (i = 0; i < t->pConsTIM->NumImages; i++) {
+ pImg = (pIMAGE_INFO_3_4_0)(t->pImg + i);
+ OTA_DEBUG("[%d] ID: %s, NextID: %s, Offset: 0x%x, "
+ "LoadAddr: 0x%x, Size: %d, SizeToHash: %d, HashAlgorithmID: 0x%x\n", i,
+ id2str(pImg->ImageID), id2str(pImg->NextImageID), pImg->FlashEntryAddr,
+ pImg->LoadAddr, pImg->ImageSize, pImg->ImageSizeToHash,
+ pImg->HashAlgorithmID);
+ OTA_DEBUG("[%d] Hash: 0x%x, 0x%x, 0x%x, 0x%x, "
+ "0x%x, 0x%x, 0x%x, 0x%x, "
+ "0x%x, 0x%x, 0x%x, 0x%x, "
+ "0x%x, 0x%x, 0x%x, 0x%x\n", i,
+ pImg->Hash[0], pImg->Hash[1], pImg->Hash[2], pImg->Hash[3],
+ pImg->Hash[4], pImg->Hash[5], pImg->Hash[6], pImg->Hash[7],
+ pImg->Hash[8], pImg->Hash[9], pImg->Hash[10], pImg->Hash[11],
+ pImg->Hash[12], pImg->Hash[13], pImg->Hash[14], pImg->Hash[15]);
+ }
+}
+
+static void *load_dtim(const char *dev)
+{
+ int fd = -1;
+
+ char _dev[32] = {0};
+ char *buf = malloc(DTIM_MAX_SIZE);
+ if (!buf) {
+ OTA_ERR("failed to malloc 0x%x for dtim.\n", DTIM_MAX_SIZE);
+ goto out;
+ }
+
+ sprintf(_dev, "/dev/%s", dev);
+ fd = open(_dev, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ OTA_ERR("failed to open %s.\n", _dev);
+ free(buf);
+ buf = NULL;
+ goto out;
+ }
+
+ if (complete_read(fd, buf, DTIM_MAX_SIZE) < 0) {
+ OTA_ERR("failed to load %s.\n", _dev);
+ free(buf);
+ buf = NULL;
+ goto out;
+ }
+
+out:
+ if (fd >= 0)
+ close(fd);
+ return buf;
+}
+
+static int __save_dtim(int fd, pTIM pTIM_h)
+{
+ int r = -1;
+ struct erase_info_user mtdEraseInfo;
+ struct mtd_info_user mtdInfo;
+
+ if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ OTA_ERR("could not get MTD device info.\n");
+ goto out;
+ }
+ mtdEraseInfo.start = 0;
+ mtdEraseInfo.length = mtdInfo.erasesize;
+
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(fd, MEMERASE, &mtdEraseInfo);
+
+ if (complete_write(fd, (char *)pTIM_h->pConsTIM, DTIM_MAX_SIZE) < 0)
+ goto out;
+
+ r = 0;
+out:
+ return r;
+}
+
+static int save_dtim(const char *dev, pTIM pTIM_h)
+{
+ int fd = -1;
+ int r = -1;
+ char _dev[32] = {0};
+ sprintf(_dev, "/dev/%s", dev);
+ fd = open(_dev, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ OTA_ERR("failed to open %s.\n", _dev);
+ goto out;
+ }
+
+ r = __save_dtim(fd, pTIM_h);
+ if (r)
+ OTA_ERR("failed to save dtim to %s.\n", _dev);
+out:
+ if (fd >= 0)
+ close(fd);
+ return r;
+}
+
+/* sync the new to old */
+static int __sync_dtim(pTIM pNew, pTIM pOld)
+{
+ int r = -1, i, j, found = 0, images;
+ int flag = 0;
+ pIMAGE_INFO_3_4_0 pImgSrc, pImgDst;
+
+ OTA_DEBUG("%s: new dtim mode: %d, old dtim mode: %d.\n", __func__,
+ pNew->pConsTIM->VersionBind.Trusted, pOld->pConsTIM->VersionBind.Trusted);
+ if (pNew->pConsTIM->VersionBind.Trusted != pOld->pConsTIM->VersionBind.Trusted) {
+ OTA_ERR("%s: Fatal Error. Can't sync two different trust mode dtim.\n", __func__);
+ return -1;
+ }
+
+ for (i = 0; i < pNew->pConsTIM->NumImages; i++) {
+ pImgSrc = (pIMAGE_INFO_3_4_0)(pNew->pImg + i);
+ for (j = 0; j < pOld->pConsTIM->NumImages; j++) {
+ pImgDst = (pIMAGE_INFO_3_4_0)(pOld->pImg + j);
+ if (pImgSrc->ImageID == pImgDst->ImageID &&
+ pImgSrc->ImageID != IMAGE_ID_DTIM_A &&
+ pImgSrc->ImageID != IMAGE_ID_DTIM_B) {
+ found++;
+ if (pImgSrc->ImageSize != pImgDst->ImageSize ||
+ pImgSrc->ImageSizeToHash != pImgDst->ImageSizeToHash ||
+ pImgSrc->LoadAddr != pImgDst->LoadAddr ||
+ pImgSrc->HashAlgorithmID != pImgDst->HashAlgorithmID ||
+ memcmp(pImgSrc->Hash, pImgDst->Hash, sizeof(pImgSrc->Hash)) != 0)
+ {
+ OTA_DEBUG("Image: %s has been changed.\n", id2str(pImgSrc->ImageID));
+ pImgDst->ImageID = pImgSrc->ImageID;
+ pImgDst->ImageSize = pImgSrc->ImageSize;
+ pImgDst->ImageSizeToHash = pImgSrc->ImageSizeToHash;
+ pImgDst->LoadAddr = pImgSrc->LoadAddr;
+ pImgDst->HashAlgorithmID = pImgSrc->HashAlgorithmID;
+ memcpy(pImgDst->Hash, pImgSrc->Hash, sizeof(pImgSrc->Hash));
+ flag = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ images = pNew->pConsTIM->NumImages - 1;
+ /* omit the first image(dtim it self) */
+ if (found != images) {
+ OTA_ERR("FATAL ERROR: NumImage: %d, found: %d, not exactly match.\n"
+ , pNew->pConsTIM->NumImages, found);
+ goto out;
+ }
+
+ r = flag;
+out:
+ return r;
+}
+
+static int update_dtim(const char *dev, void *bufNew)
+{
+ int r = -1;
+ TIM tNew, tOld;
+ char *buf = load_dtim(dev);
+
+ if (!buf) {
+ OTA_ERR("%s: failed to load dtim for %s.\n", __func__, dev);
+ goto out;
+ }
+
+ SetTIMPointers(buf, &tOld);
+ SetTIMPointers(bufNew, &tNew);
+
+ OTA_DEBUG("### Dump orignal dtim of %s. ###\n", dev);
+ dump_dtim(&tOld);
+ OTA_DEBUG("### Dump the new dtim. ###\n");
+ dump_dtim(&tNew);
+
+ r = __sync_dtim(&tNew, &tOld);
+ if (r < 0)
+ goto out;
+ if (r > 0) {
+ OTA_DEBUG("Images have been changed, update %s\n", dev);
+ r = save_dtim(dev, &tOld);
+ } else {
+ OTA_DEBUG("Images have NO change, DO NOT need to sync.\n");
+ r = 0;
+ }
+
+ OTA_DEBUG("%s: %s.\n", __func__, (r >= 0) ? "OK" : "FAILED");
+out:
+ if (buf)
+ free(buf);
+ return r;
+}
+
+static int sync_dtim(const char *src, const char *dst)
+{
+ int r = -1;//, i, j, found = 0;
+// int flag = 0;
+// pIMAGE_INFO_3_4_0 pImgSrc, pImgDst;
+ TIM tSrc;
+ TIM tDst;
+ char *bufSrc = load_dtim(src);
+ char *bufDst = load_dtim(dst);
+
+ OTA_DEBUG("Start to sync %s to %s.\n", src, dst);
+ if (!bufSrc || !bufDst) {
+ OTA_ERR("failed to sync %s to %s.\n", src, dst);
+ goto out;
+ }
+
+ SetTIMPointers(bufSrc, &tSrc);
+ SetTIMPointers(bufDst, &tDst);
+
+ OTA_DEBUG("Dump dtim info of %s.\n", src);
+ dump_dtim(&tSrc);
+ OTA_DEBUG("Dump dtim info of %s.\n", dst);
+ dump_dtim(&tDst);
+
+ if (tSrc.pConsTIM->NumImages != tDst.pConsTIM->NumImages) {
+ OTA_ERR("FATAL ERROR: NumImages(%s): %d, NumImages(%s): %d.\n",
+ src, tSrc.pConsTIM->NumImages, dst, tDst.pConsTIM->NumImages);
+ goto out;
+ }
+
+ r = __sync_dtim(&tSrc, &tDst);
+ if (r < 0)
+ goto out;
+ if (r > 0) {
+ OTA_DEBUG("Images have been changed, need to sync %s to %s.\n", src, dst);
+ r = save_dtim(dst, &tDst);
+ } else {
+ OTA_DEBUG("Images have NO change, DO NOT need to sync.\n");
+ r = 0;
+ }
+out:
+ if (bufSrc)
+ free(bufSrc);
+ if (bufDst)
+ free(bufDst);
+ return r;
+}
+
+/* dev is the mtd device of dtim */
+static int get_image_mode(const char *dev)
+{
+ char *buf = load_dtim(dev);
+ TIM tim;
+ int mode;
+
+ if (!buf) {
+ OTA_ERR("%s: failed to load dtim for %s.\n", __func__, dev);
+ return -1;
+ }
+
+ SetTIMPointers(buf, &tim);
+ mode = tim.pConsTIM->VersionBind.Trusted;
+ OTA_DEBUG("%s: it is %s mode(%s).\n", __func__, (mode == 1) ? "Trusted" : "NON-Trusted", dev);
+ free(buf);
+ return mode;
+}
+#endif
+
+static UINT_T CheckReserved (pTIM pTIM_h)
+{
+ pWTP_RESERVED_AREA pWRA = (pWTP_RESERVED_AREA) pTIM_h->pReserved;
+
+ // Make sure that the TIM has a credible size
+ if(pTIM_h->pConsTIM->SizeOfReserved == 0)
+ return NotFoundError;
+
+ // Older TIM's had old reserved fields definition
+ if (pTIM_h->pConsTIM->VersionBind.Version == (0x00030101))
+ return NotFoundError;
+
+ // Was this area in reserved field created by a WTP compliant tool so we can parse?
+ if (pWRA->WTPTP_Reserved_Area_ID != WTPRESERVEDAREAID)
+ return NotFoundError;
+
+ return NoError;
+}
+
+// Finds a Package of WTP recognized information in the reserved area based on identifier
+static pWTP_RESERVED_AREA_HEADER FindPackageInReserved (UINT_T * Retval, pTIM pTIM_h, UINT_T Identifier)
+{
+ UINT_T Count = 0;
+ pWTP_RESERVED_AREA_HEADER pWRAH = NULL;
+ pWTP_RESERVED_AREA pWRA = (pWTP_RESERVED_AREA) pTIM_h->pReserved;
+
+ *Retval = CheckReserved(pTIM_h);
+ if (*Retval != NoError)
+ return NULL;
+
+ // Start from the begining
+ pWRAH = (pWTP_RESERVED_AREA_HEADER) (pWRA + 1);
+
+ while ((pWRAH->Identifier != Identifier) && (pWRAH->Identifier != TERMINATORID) && (Count < pWRA->NumReservedPackages))
+ {
+ pWRAH = (pWTP_RESERVED_AREA_HEADER)((UINT_T)pWRAH + ((pWRAH->Size + 3) & ~3)); // Skip to the next one
+ Count++;
+ }
+ if (pWRAH->Identifier != Identifier)
+ {
+ *Retval = NotFoundError;
+ pWRAH = NULL;
+ }
+
+ return pWRAH;
+}
+
+// This function has been added to support to isolate backwards compatibility to tim.c
+// It will return a point to pIMAGE_INFO based on TIM version.
+static pIMAGE_INFO_3_4_0 ReturnPImgPtr(pTIM pTIM_h, UINT_T ImageNumber)
+{
+ pIMAGE_INFO_3_4_0 pIMG;
+ pIMG = (pIMAGE_INFO_3_4_0) &pTIM_h->pImg[ImageNumber];
+ return pIMG;
+}
+
+// This function is used to find an image information field in the TIM
+// of the image with the ID passed in
+
+static pIMAGE_INFO_3_4_0 FindImageInTIM(pTIM pTIM_h, UINT_T ImageID)
+{
+ pIMAGE_INFO_3_4_0 pImageInfo = NULL;
+ UINT8_T i;
+
+ if (pTIM_h)
+ {
+ for( i = 0; i < pTIM_h->pConsTIM->NumImages; i++)
+ {
+ pImageInfo = ReturnPImgPtr(pTIM_h, i);
+ if(pImageInfo->ImageID == ImageID)
+ return pImageInfo;
+ }
+ }
+ return NULL;
+}
+
+static int __retrive_timh_by_ddrid(pTIM pTIM_h, unsigned int *DDR_ID, int *imagesize)
+{
+ int i, DDRTimIndex = -1;
+ UINT_T /*LoadAddr, TimSize, */TimLoadAddr, Retval;
+ pIMAGE_INFO_3_4_0 pTimInfo = NULL;
+ pWTP_RESERVED_AREA_HEADER pWRAH = NULL;
+ pDDR_FLASH_MCP_PACKAGE pMCP = NULL;
+#if 0
+ if (DDR_ID == 0xFFFFFFFF || DDR_ID == 0) {
+ OTA_ERR("Warning: no valid DDR ID in ASR Flag\n");
+ return NoError;
+ }
+#endif
+ TimLoadAddr = (UINT_T)pTIM_h->pConsTIM;
+
+ pWRAH = FindPackageInReserved(&Retval, pTIM_h, DDR_FLASH_MCP_PACKAGE_ID);
+ if(pWRAH == NULL) {
+ OTA_ERR("No DFMP found, single DDR TIM\n\r");
+ return NoError;
+ } else {
+ pMCP = (DDR_FLASH_MCP_PACKAGE *) pWRAH;
+ for (i = 0; i < pMCP->NumberVendorDdrFlashSpec; i++) {
+ if(pMCP->ddrFlashSpec[i].VendorDdrPid == *DDR_ID) {
+ DDRTimIndex = i;
+ OTA_DEBUG("%s: [%d] got ddr id: 0x%x\n", __func__, i, *DDR_ID);
+ break;
+ }
+ }
+
+ pTimInfo = FindImageInTIM(pTIM_h, IMAGE_ID_TIMH);
+ if(pTimInfo == NULL) {
+ OTA_ERR("%s %d: No TIMH found, error\n", __func__, __LINE__);
+ return TIMNotFound;
+ }
+
+ if (DDRTimIndex < 0) {
+ OTA_ERR("NOT found ddr id: 0x%x, use the first TIM ddrid: 0x%x",
+ *DDR_ID, pMCP->ddrFlashSpec[0].VendorDdrPid);
+ *DDR_ID = pMCP->ddrFlashSpec[0].VendorDdrPid;
+ goto out;
+ }
+
+ /* go through all the TIMs to the right one */
+ for (i = 0; i < (DDRTimIndex + 1); i++) {
+ Retval = SetTIMPointers((void *)TimLoadAddr, pTIM_h);
+ if(Retval) {
+ OTA_ERR("%s %d: failed\n", __func__, __LINE__);
+ return TIMNotFound;
+ }
+
+ pTimInfo = FindImageInTIM(pTIM_h, IMAGE_ID_TIMH);
+ if(pTimInfo == NULL) {
+ OTA_ERR("%s %d: No TIMH found, error\n", __func__, __LINE__);
+ return TIMNotFound;
+ }
+ TimLoadAddr += pTimInfo->ImageSize;
+ }
+ }
+
+out:
+ *imagesize = pTimInfo->ImageSize;
+ OTA_DEBUG("%s: index: %d, size: 0x%x\n", __func__, DDRTimIndex, pTimInfo->ImageSize);
+ return NoError;
+}
+
diff --git a/mbtk/mbtk_otad/inc/tim.h b/mbtk/mbtk_otad/inc/tim.h
new file mode 100755
index 0000000..5cd20ec
--- /dev/null
+++ b/mbtk/mbtk_otad/inc/tim.h
@@ -0,0 +1,334 @@
+#ifndef __TIM_H__
+#define __TIM_H__
+
+enum {
+ IMAGE_ID_DTIM_A = 0x54494D31, /* dtim primary */
+ IMAGE_ID_DTIM_B = 0x54494d32, /* dtim recovery */
+ IMAGE_ID_UBOOT = 0x4F534C4F,
+ IMAGE_ID_KERNEL = 0x5A494D47,
+ IMAGE_ID_ROOTFS = 0x5359534A,
+ IMAGE_ID_ARBEL = 0x41524249,
+ IMAGE_ID_MSA = 0x47524249,
+ IMAGE_ID_RF = 0x52464249,
+ IMAGE_ID_OEMD = 0x4F454D44,
+ IMAGE_ID_OBM = 0x4f424d49,
+ IMAGE_ID_TIMH = 0x54494d48,
+
+ // Add by liubin
+ IMAGE_ID_DEVICE = 0x4F454D55,
+};
+
+#define TIMIDENTIFIER 0x54494D48 // "TIMH"
+// TIM Versions
+#define TIM_3_2_00 0x30200 // Support for Partitioning
+#define TIM_3_3_00 0x30300 // Support for ECDSA-256
+#define TIM_3_4_00 0x30400 // Support for ECDSA-521
+
+// Defined for DTIM support
+typedef enum
+{
+ TIMH_NOTINC = 0,
+ TIMH_INC = 1,
+ DTIM_PRIMARY_INC = 2,
+ DTIM_RECOVERY_INC = 3,
+ DTIM_CP_INC = 4,
+ TIMH_RECOVERY_INC = 5,
+ DTIM_PPSETTING_INC = 6,
+ // 7-9 reserved
+ DTIM_CUSTMOZIEDTYPE1 = 10,
+ DTIM_CUSTMOZIEDTYPE2 = 11,
+ DTIM_CUSTMOZIEDTYPE3 = 12,
+ DTIM_CUSTMOZIEDTYPE4 = 13,
+ DTIM_CUSTMOZIEDTYPE5 = 14,
+ DTIM_CUSTMOZIEDTYPE6 = 15,
+ DTIM_CUSTMOZIEDTYPE7 = 16,
+ DTIM_CUSTMOZIEDTYPE8 = 17,
+ DTIM_CUSTMOZIEDTYPE9 = 18,
+ DTIM_CUSTMOZIEDTYPE10 = 19,
+ DTIM_CUSTMOZIEDTYPE11 = 20,
+ DTIM_CUSTMOZIEDTYPE12 = 21,
+ DTIM_CUSTMOZIEDTYPE13 = 22,
+ DTIM_CUSTMOZIEDTYPE14 = 23,
+ DTIM_CUSTMOZIEDTYPE15 = 24,
+ DTIM_CUSTMOZIEDTYPE16 = 25,
+ DTIM_CUSTMOZIEDTYPE17 = 26,
+ DTIM_CUSTMOZIEDTYPE18 = 27,
+ DTIM_CUSTMOZIEDTYPE19 = 28,
+ DTIM_CUSTMOZIEDTYPE20 = 29,
+
+ DTIM_CUSTMOZIED_MAX = 50
+} TIMIncluded_Type;
+
+typedef unsigned int UINT_T, *PUINT;
+typedef unsigned char UINT8_T;
+
+typedef enum
+{
+ SHA160 = 0x00000014, //20
+ SHA256 = 0x00000020, //32
+ SHA512 = 0x00000040, //64
+ DUMMY_HASH = 0x7FFFFFFF
+}
+HASHALGORITHMID_T;
+
+typedef struct
+{
+ UINT_T Version;
+ UINT_T Identifier; // "TIMH"
+ UINT_T Trusted; // 1- Trusted, 0 Non
+ UINT_T IssueDate;
+ UINT_T OEMUniqueID;
+} VERSION_I, *pVERSION_I; // 0x10 bytes
+
+typedef struct
+{
+ UINT_T WTMFlashSign;
+ UINT_T WTMEntryAddr;
+ UINT_T WTMEntryAddrBack;
+ UINT_T WTMPatchSign;
+ UINT_T WTMPatchAddr;
+ UINT_T BootFlashSign;
+} FLASH_I, *pFLASH_I; // 0x10 bytes
+
+typedef struct
+{
+ UINT_T PartitionNumber : 4;
+ UINT_T ImageType : 8;
+ UINT_T Reserved : 20;
+}TIM_INT;
+
+typedef union{
+ TIM_INT bits;
+ UINT_T value;
+}PN, *pPN;
+
+typedef struct
+{
+ UINT_T ImageID; // Indicate which Image
+ UINT_T NextImageID; // Indicate next image in the chain
+ UINT_T FlashEntryAddr; // Block numbers for NAND
+ UINT_T LoadAddr;
+ UINT_T ImageSize;
+ UINT_T ImageSizeToHash;
+ HASHALGORITHMID_T HashAlgorithmID; // See HASHALGORITHMID_T
+ UINT_T Hash[16]; // Reserve 512 bits for the hash
+ PN PartitionNumber;
+} IMAGE_INFO_3_4_0, *pIMAGE_INFO_3_4_0; // 0x60 bytes
+
+typedef struct
+{
+ UINT_T ImageID; // Indicate which Image
+ UINT_T NextImageID; // Indicate next image in the chain
+ UINT_T FlashEntryAddr; // Block numbers for NAND
+ UINT_T LoadAddr;
+ UINT_T ImageSize;
+ UINT_T ImageSizeToHash;
+ HASHALGORITHMID_T HashAlgorithmID; // See HASHALGORITHMID_T
+ UINT_T Hash[8]; // Reserve 256 bits for the hash
+ UINT_T PartitionNumber; // This is new for V3.2.0
+} IMAGE_INFO_3_2_0, *pIMAGE_INFO_3_2_0; // 0x40 bytes
+
+// Constant part of the TIMs
+typedef struct
+{
+ VERSION_I VersionBind; // 0
+ FLASH_I FlashInfo; // 0x10
+ UINT_T NumImages; // 0x20
+ UINT_T NumKeys; // 0x24
+ UINT_T SizeOfReserved; // 0x28
+} CTIM, *pCTIM; // 0x2C
+
+// TIM structure for use by DKB/OBM/BootROM
+typedef struct
+{
+ pCTIM pConsTIM; // Constant part
+ pIMAGE_INFO_3_4_0 pImg; // Pointer to Images
+ void *pKey; // Pointer to Keys
+ PUINT pReserved; // Pointer to Reserved Area
+ void *pTBTIM_DS; // Pointer to Digital Signature
+} TIM, *pTIM;
+
+/**
+ * General error code definitions 0x0 - 0x1F
+ **/
+#define NoError 0x0
+#define NotFoundError 0x1
+#define TIMNotFound 0x6D
+
+// WTP Format Recognized Reserved Area Indicator
+#define WTPRESERVEDAREAID 0x4F505448 // "OPTH"
+
+// Reserved Area Package Headers
+#define TERMINATORID 0x5465726D // "Term"
+
+/********** WTP Recognized Reserved Area Layout ********************************
+*
+* WTPTP_Defined_Reserved_Format_ID \ This clues BR, OBM and DKB that the reserved area is in a known format
+* Number of Reserved Area Packages / For each package there is a header, payload size and payload
+*
+* Header \ Indicates what type of a Reserved Area Package
+* Size \ Size Comprises a single Reserved Area Package
+* Payload / There may be any number of Packages so long as TIM/NTIM < 4KB
+* /
+*
+* Header \ The Last one should be a Package with a Terminator Header
+* Size / The size should be 8 bytes (the size of this package)
+*
+**********************************************************************************/
+typedef struct
+{
+ UINT_T WTPTP_Reserved_Area_ID; // This clues BR, OBM and DKB that the reserved area is in a known format
+ UINT_T NumReservedPackages; // For each package there is a header, payload size and payload
+}WTP_RESERVED_AREA, *pWTP_RESERVED_AREA;
+
+typedef struct
+{
+ UINT_T Identifier; // Identification of this reserved area entry
+ UINT_T Size; // Size = Payload Size + 2 words (8 bytes).
+}WTP_RESERVED_AREA_HEADER, *pWTP_RESERVED_AREA_HEADER;
+
+#define DDR_FLASH_MCP_PACKAGE_ID 0X44464D50 // "DFMP"
+typedef struct
+{
+ unsigned int VendorDdrPid;
+ unsigned int FlashInfo; //for eMMC, FlashInfo is flash size, MB; for nand, FlashInfo is NandID
+} VendorDdrFlashSpec, *pVendorDdrFlashSpec;
+
+
+typedef struct
+{
+ WTP_RESERVED_AREA_HEADER WRAH;
+ unsigned int NumberVendorDdrFlashSpec;
+ VendorDdrFlashSpec ddrFlashSpec[2];
+} DDR_FLASH_MCP_PACKAGE, *pDDR_FLASH_MCP_PACKAGE;
+
+#define MAXRSAKEYSIZEWORDS 64 // 2048 bits
+#define MAXECCKEYSIZEWORDS 17 // 521 bits+
+
+typedef enum
+{
+ Marvell_DS = 0x00000000,
+ PKCS1_v1_5_Caddo = 0x00000001,
+ PKCS1_v2_1_Caddo = 0x00000002,
+ PKCS1_v1_5_Ippcp = 0x00000003,
+ PKCS1_v2_1_Ippcp = 0x00000004,
+ ECDSA_256 = 0x00000005,
+ ECDSA_521 = 0x00000006,
+ PKCS1_v2_2_Ippcp = 0x00000007,
+ DUMMY_ENALG = 0x7FFFFFFF // See _Cryptographic_Scheme for additional id's
+}
+ENCRYPTALGORITHMID_T;
+
+typedef struct
+{
+ UINT_T KeyID; // Associate an ID with this key
+ HASHALGORITHMID_T HashAlgorithmID; // See HASHALGORITHMID_T
+ UINT_T KeySize; // Specified in bits
+ UINT_T PublicKeySize; // Specified in bits
+ UINT_T RSAPublicExponent[MAXRSAKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T RSAModulus[MAXRSAKEYSIZEWORDS]; // Up to 2K bits
+ UINT_T KeyHash[8]; // Reserve 256 bits for the hash
+} KEY_MOD_3_2_0, *pKEY_MOD_3_2_0; // 0x22C bytes
+
+typedef struct
+{
+ UINT_T KeyID; // Associate an ID with this key
+ HASHALGORITHMID_T HashAlgorithmID; // See HASHALGORITHMID_T
+ UINT_T KeySize; // Specified in bits
+ UINT_T PublicKeySize; // Specified in bits
+ ENCRYPTALGORITHMID_T EncryptAlgorithmID; // See ENCRYPTALGORITHMID_T;
+ union
+ {
+ struct
+ {
+ UINT_T RSAPublicExponent[MAXRSAKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T RSAModulus[MAXRSAKEYSIZEWORDS]; // Up to 2K bits
+ }Rsa;
+
+ struct
+ {
+ UINT_T PublicKeyCompX[MAXECCKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T PublicKeyCompY[MAXECCKEYSIZEWORDS]; // Up to 521 bits
+ // Pad this struct so it remains consistent with RSA struct
+ UINT_T Reserved[(2*MAXRSAKEYSIZEWORDS)-(2*MAXECCKEYSIZEWORDS)];
+ }Ecdsa;
+ };
+
+ UINT_T KeyHash[8]; // Reserve 256 bits for the hash
+} KEY_MOD_3_3_0, *pKEY_MOD_3_3_0; //
+
+typedef struct
+{
+ UINT_T KeyID; // Associate an ID with this key
+ HASHALGORITHMID_T HashAlgorithmID; // See HASHALGORITHMID_T
+ UINT_T KeySize; // Specified in bits
+ UINT_T PublicKeySize; // Specified in bits
+ ENCRYPTALGORITHMID_T EncryptAlgorithmID; // See ENCRYPTALGORITHMID_T;
+ union
+ {
+ struct
+ {
+ UINT_T RSAPublicExponent[MAXRSAKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T RSAModulus[MAXRSAKEYSIZEWORDS]; // Up to 2K bits
+ }Rsa;
+
+ struct
+ {
+ UINT_T PublicKeyCompX[MAXECCKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T PublicKeyCompY[MAXECCKEYSIZEWORDS]; // Up to 521 bits
+ // Pad this struct so it remains consistent with RSA struct
+ UINT_T Reserved[(2*MAXRSAKEYSIZEWORDS)-(2*MAXECCKEYSIZEWORDS)];
+ }Ecdsa;
+
+ struct
+ {
+ UINT_T EncryptedHashRSAPublicExponent[MAXRSAKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T EncryptedHashRSAModulus[MAXRSAKEYSIZEWORDS]; // Up to 2K bits
+ }EncryptedRsa;
+
+ struct
+ {
+ UINT_T EncryptedHashPublicKeyCompX_R[MAXECCKEYSIZEWORDS]; // Contents depend on PublicKeySize
+ UINT_T EncryptedHashPublicKeyCompX_S[MAXECCKEYSIZEWORDS]; // Contents depend on PublicKeySize
+
+ UINT_T EncryptedHashPublicKeyCompY_R[MAXECCKEYSIZEWORDS]; // Up to 521 bits
+ UINT_T EncryptedHashPublicKeyCompY_S[MAXECCKEYSIZEWORDS]; // Up to 521 bits
+
+ // Pad this struct so it remains consistent with encrypted RSA struct
+ UINT_T Reserved[(2 * MAXRSAKEYSIZEWORDS)-(4 * MAXECCKEYSIZEWORDS)];
+ }EncryptedEcdsa;
+ };
+
+ UINT_T KeyHash[16]; // Reserve 512 bits for the hash
+} KEY_MOD_3_4_0, *pKEY_MOD_3_4_0; //
+
+
+typedef struct
+{
+ ENCRYPTALGORITHMID_T DSAlgorithmID; // See ENCRYPTALGORITHMID_T
+ HASHALGORITHMID_T HashAlgorithmID; // See HASHALGORITHMID_T
+ UINT_T KeySize; // Specified in bits
+ UINT_T Hash[8]; // Reserve 256 bits for optional key hash
+ union // Note that this union should not be included as part of the hash for TIM in the Digital Signature
+ {
+ struct
+ {
+ UINT_T RSAPublicExponent[MAXRSAKEYSIZEWORDS];
+ UINT_T RSAModulus[MAXRSAKEYSIZEWORDS]; // Up to 2K bits
+ UINT_T RSADigS[MAXRSAKEYSIZEWORDS]; // Contains TIM Hash
+ }Rsa;
+
+ struct
+ {
+ UINT_T ECDSAPublicKeyCompX[MAXECCKEYSIZEWORDS]; // Allow for 544 bits (17 words, 68 bytes for use with EC-521)
+ UINT_T ECDSAPublicKeyCompY[MAXECCKEYSIZEWORDS];
+ UINT_T ECDSADigS_R[MAXECCKEYSIZEWORDS];
+ UINT_T ECDSADigS_S[MAXECCKEYSIZEWORDS];
+ // Pad this struct so it remains consistent with RSA struct
+ UINT_T Reserved[(MAXRSAKEYSIZEWORDS*3)-(MAXECCKEYSIZEWORDS*4)];
+ } Ecdsa;
+ };
+} PLAT_DS, *pPLAT_DS;
+
+#endif
+
diff --git a/mbtk/mbtk_otad/src/mbtk_ota.c b/mbtk/mbtk_otad/src/mbtk_ota.c
new file mode 100755
index 0000000..9e49589
--- /dev/null
+++ b/mbtk/mbtk_otad/src/mbtk_ota.c
@@ -0,0 +1,235 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+
+#include "otad.h"
+#include "mbtk_type.h"
+#include "mbtk_device.h"
+
+typedef struct {
+ char name[32];
+ char dev[16];
+ uint32 partition_start;
+ uint32 partition_size;
+ uint32 erase_size;
+} partition_info_t;
+
+/*
+* revision_out start from 0x1000.
+*/
+#define REVISION_OUT_ADDR 0x1000
+
+char revision_out[48] = {0};
+static bool revision_out_found = FALSE;
+
+static int partition_get(char *partition_name, partition_info_t *info)
+{
+ FILE *fp = fopen("/proc/mtd", "r");
+ if(fp == NULL) {
+ OTA_ERR("fopen(/proc/mtd) fail:%d", errno);
+ return -1;
+ }
+
+ char buff[64];
+ char size_str[16];
+ char erase_size_str[16];
+ char name[32];
+ memset(buff, 0x0, sizeof(buff));
+ while(fgets(buff, sizeof(buff), fp)) {
+ if(strstr(buff, partition_name)) {
+ memset(size_str, 0x0, sizeof(size_str));
+ memset(erase_size_str, 0x0, sizeof(erase_size_str));
+ memset(name, 0x0, sizeof(name));
+ memcpy(info->dev, "/dev/", 5);
+ if(4 == sscanf(buff, "%s %s %s %s", info->dev + 5, size_str, erase_size_str, name)) {
+ if(name[0] == '\"' && name[strlen(name) - 1] == '\"') {
+ memcpy(info->name, name + 1, strlen(name) - 2); // No copy ""
+ } else {
+ OTA_ERR("partition(%s) name error.", buff);
+ return -1;
+ }
+
+ if(info->dev[strlen(info->dev) - 1] == ':') {
+ info->dev[strlen(info->dev) - 1] = '\0';
+ }
+
+ info->partition_size = (uint32)strtoul(size_str, NULL, 16);
+ info->erase_size = (uint32)strtoul(erase_size_str, NULL, 16);
+ //info->partition_start += info->partition_size;
+ break;
+ } else {
+ OTA_ERR("sscanf(%s) fail:%d", buff, errno);
+ return -1;
+ }
+ }
+ memset(buff, 0x0, sizeof(buff));
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+
+void revision_out_find(char *data, int len, unsigned int processed_cnt)
+{
+ if(!revision_out_found) {
+ if(processed_cnt + len > REVISION_OUT_ADDR) { // µ½´ï 0x1000
+ char *start = NULL;
+ if(strlen(revision_out) > 0) {
+ start = data;
+ } else {
+ start = data + REVISION_OUT_ADDR - processed_cnt;
+ }
+
+ if(data[len - 1] == '\0') { // Last char is '\0',get the complete version.
+ if(strlen(start) > 0) {
+ memcpy(revision_out + strlen(revision_out), start, strlen(start));
+ }
+ revision_out_found = TRUE;
+ OTA_DEBUG("Found complete version : %s", revision_out);
+ } else {
+ memcpy(revision_out + strlen(revision_out), start, data + len - start);
+ OTA_DEBUG("Found version : %s", revision_out);
+ }
+ }
+ }
+}
+
+int revision_out_update()
+{
+ if(strlen(revision_out) == 0) {
+ OTA_ERR("revision_out not set.");
+ revision_out_found = FALSE;
+ return -1;
+ }
+
+ partition_info_t info;
+ memset(&info, 0x0, sizeof(partition_info_t));
+ if(partition_get("device_info", &info)) {
+ OTA_ERR("partition_get() fail.");
+ return -1;
+ }
+
+ OTA_DEBUG("device_info name : %s, dev : %s, addr : %08x, size : %08x, erase_size : %08x", info.name,
+ info.dev, info.partition_start, info.partition_size, info.erase_size);
+
+ if(info.erase_size <= 0 || info.partition_size <= 0) {
+ OTA_ERR("partition info error.");
+ return -1;
+ }
+
+#if 0
+ int fd = open(dev, O_RDWR);
+ if (fd < 0) {
+ OTA_ERR("Fatal error: can't open device_info %s\n", dev);
+ return -1;
+ }
+
+ mbtk_device_info_header_t info_header;
+ memset(&info_header, 0x0, sizeof(mbtk_device_info_header_t));
+ int len = read(fd, &info_header, sizeof(mbtk_device_info_header_t));
+ if (len != sizeof(mbtk_device_info_header_t)) {
+ OTA_ERR("Fatal error: read %d bytes(expect %d)\n", len, sizeof(mbtk_device_info_header_t));
+ goto fail;
+ }
+
+ if(info_header.tag != MBTK_DEVICE_INFO_PARTITION_TAG) {
+ OTA_ERR("TAG error : %08x", info_header.tag);
+ goto fail;
+ }
+
+ if(info_header.version != MBTK_DEVICE_INFO_CURR_VERSION) {
+ OTA_ERR("Version error : %d", info_header.version);
+ goto fail;
+ }
+
+ if(info_header.item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr == 0) {
+ OTA_ERR("No found item : %d", MBTK_DEVICE_INFO_ITEM_BASIC);
+ goto fail;
+ }
+
+ lseek(fd, info_header.item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr, SEEK_SET);
+ mbtk_device_info_basic_t info_basic;
+ memset(&info_basic, 0, sizeof(mbtk_device_info_basic_t));
+ if (read(fd, &info_basic, sizeof(mbtk_device_info_basic_t)) != sizeof(mbtk_device_info_basic_t)) {
+ OTA_ERR("Read fail:%d", errno);
+ goto fail;
+ }
+
+ memset(info_basic.revision_out, 0, sizeof(info_basic.revision_out));
+ memcpy(info_basic.revision_out, revision_out, strlen(revision_out));
+
+ lseek(fd, info_header.item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr, SEEK_SET);
+ if (write(fd, &info_basic, sizeof(mbtk_device_info_basic_t)) != sizeof(mbtk_device_info_basic_t)) {
+ OTA_ERR("Write fail:%d", errno);
+ goto fail;
+ }
+#else
+ int fd = open(info.dev, O_RDWR);
+ if (fd < 0) {
+ OTA_ERR("Fatal error: can't open device_info %s\n", info.dev);
+ return -1;
+ }
+
+ char *mtd_buff = (char*)malloc(info.erase_size);
+ if(mtd_buff == NULL) {
+ OTA_ERR("malloc() failed\n");
+ return -1;
+ }
+ memset(mtd_buff, 0, info.erase_size);
+ int len = read(fd, mtd_buff, info.erase_size);
+ if (len != info.erase_size) {
+ OTA_ERR("Fatal error: read %d[%d] bytes(expect %d)\n", len, errno, info.erase_size);
+ goto fail;
+ }
+
+ struct erase_info_user mtdEraseInfo;
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ {
+ OTA_ERR("seek failed\n");
+ return -1;
+ }
+
+ mtdEraseInfo.length = info.partition_size;
+ mtdEraseInfo.start = 0;
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(fd, MEMERASE, &mtdEraseInfo);
+
+ mbtk_device_info_header_t *info_header = (mbtk_device_info_header_t*)mtd_buff;
+ mbtk_device_info_basic_t *info_basic = (mbtk_device_info_basic_t*)(mtd_buff + info_header->item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr);
+ OTA_DEBUG("Old version : %s", info_basic->revision_out);
+ memset(info_basic->revision_out, 0, sizeof(info_basic->revision_out));
+ memcpy(info_basic->revision_out, revision_out, strlen(revision_out));
+
+ lseek(fd, 0, SEEK_SET);
+ if (write(fd, mtd_buff, info.erase_size) != info.erase_size) {
+ OTA_ERR("Write fail:%d", errno);
+ goto fail;
+ }
+
+ if(mtd_buff) {
+ free(mtd_buff);
+ }
+
+#endif
+
+ close(fd);
+
+ OTA_DEBUG("Set revision_out : %s", revision_out);
+
+ memset(revision_out, 0x0, sizeof(revision_out));
+ revision_out_found = FALSE;
+
+ return 0;
+
+fail:
+ close(fd);
+ return -1;
+}
diff --git a/mbtk/mbtk_otad/src/otad.c b/mbtk/mbtk_otad/src/otad.c
new file mode 100755
index 0000000..400c2b9
--- /dev/null
+++ b/mbtk/mbtk_otad/src/otad.c
@@ -0,0 +1,3879 @@
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+
+#include <libubox/blob.h>
+#include <libubox/uloop.h>
+#include <libubox/usock.h>
+#include <libubox/list.h>
+#include <libubus.h>
+#if 0
+#include <curl/curl.h>
+#include <curl/easy.h>
+#endif
+#include <uci.h>
+
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+
+#include "libhttpclient/libhttpclient.h"
+#include "otad.h"
+
+#ifdef CONFIG_AB_SYSTEM
+#define MEMLOCKPRIV _IO('M', 25)
+#define MEMUNLOCKPRIV _IO('M', 26)
+
+static int complete_read(int fd, char *buf, int size);
+static int complete_write(int fd, char *buf, int size);
+#include "tim.h"
+#include "tim.c"
+#include "getfotav.c"
+
+#if 0
+/* support dfota upgrade */
+#define CONFIG_AB_SYSTEM_DFOTA
+#endif
+
+/* the main bootloader */
+const char *tmp_obm_main_file = "/tmp/obm_main.bin";
+const char *tmp_timh_main_file = "/tmp/timh_main.bin";
+/* the backup bootloader */
+const char *tmp_obm_bk_file = "/tmp/obm_bk.bin";
+const char *tmp_timh_bk_file = "/tmp/timh_bk.bin";
+/* the target timh for the specific ddr */
+const char *tmp_timh_main_target_file = "/tmp/timh_main_target.bin";
+const char *tmp_timh_bk_target_file = "/tmp/timh_bk_target.bin";
+
+static unsigned int obm_real_size = 0;
+#endif
+
+#define OTA_MAX_STRING_LEN 128
+#define OEMDDENTIFIER 0x4F454D44 /* "OEMD" */
+
+enum {
+ UPDATE_STATE_IDLE,
+ UPDATE_STATE_UPDATING,
+ UPDATE_STATE_UPDATED,
+ UPDATE_STATE_FAILED,
+};
+static int update_state = UPDATE_STATE_IDLE;
+static int update_oemd;
+
+struct version_info {
+ char version[OTA_MAX_STRING_LEN];
+ char url[OTA_MAX_STRING_LEN];
+ char * release_note;
+};
+
+#ifdef CONFIG_AB_SYSTEM
+#define MIN_RLS_VERSION 846
+
+static int upgrade_precheck(char *fotav)
+{
+ char *p;
+ int ver;
+
+ OTA_DEBUG("%s: %s\n", __func__, fotav);
+ p = strstr(fotav, "_rls");
+ if (!p) {
+ OTA_ERR("not found rls version.\n", __func__);
+ return -1;
+ }
+
+ p += 4;
+ ver = atoi(p);
+ if (ver < MIN_RLS_VERSION) {
+ OTA_DEBUG("%s: don't support upgrade to rls%d, min: rls%d\n", __func__, ver, MIN_RLS_VERSION);
+ return -1;
+ }
+
+ /* support upgrade */
+ return 0;
+}
+
+static int complete_read(int fd, char *buf, int size);
+static int complete_write(int fd, char *buf, int size);
+
+// Change by liubin
+#define MAX_MTD_PARTITION_CNT 35
+#define FBF_FILE_SECTOR_SIZE (4*1024)
+struct image_mtd_info {
+ char name[32];
+ char dev[16];
+ unsigned int flash_start_offset;
+ unsigned int size;
+ unsigned int erasesize;
+ unsigned int flag;
+};
+
+enum {
+ SYSTEM_SINGLE = 0,
+ SYSTEM_A = 'a',
+ SYSTEM_B = 'b'
+};
+
+static int gInActiveSystem = SYSTEM_SINGLE;
+static int gSystemHasRollbackFlag = 0;
+#endif
+
+struct ota_server {
+ char server_url[OTA_MAX_STRING_LEN];
+ int download_immediately;
+ int progress_notify;
+ int interval;
+ int first_interval;
+ unsigned int fbf_length;
+ unsigned int block_size;
+ unsigned int pagesize;
+ unsigned int emmc_block_size; /* 512B */
+ unsigned int fbf_addr;
+ char mtd_asrflag[64];
+#ifdef CONFIG_AB_SYSTEM
+ int mtd_cnt;
+ struct image_mtd_info image_mtd_info[MAX_MTD_PARTITION_CNT];
+ unsigned int cpuid;
+ unsigned int ddrid;
+ unsigned int max_timh_size;
+ unsigned int fotav_offset_in_fbf;
+ char fotav[128];
+#endif
+ char mtd_fbf[64];
+ struct version_info ver;
+};
+struct ota_server server_cfg;
+
+static struct ubus_context *ctx;
+static struct blob_buf b;
+static struct ubus_object ota_object;
+
+enum {
+ DOWNLOAD_TYPE,
+ DOWNLOAD_FILE_SIZE,
+ DOWNLOAD_URL,
+ DOWNLOAD_NAME,
+ DOWNLOAD_PSW,
+ DOWNLOAD_SYNC,
+ DOWNLOAD_SEGMENT_SIZE,
+ __DOWNLOAD_MAX
+};
+
+static const struct blobmsg_policy download_policy[] = {
+ [DOWNLOAD_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_INT32 },
+ [DOWNLOAD_FILE_SIZE] = { .name = "size", .type = BLOBMSG_TYPE_INT32 },
+ [DOWNLOAD_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
+ [DOWNLOAD_NAME] = { .name = "username", .type = BLOBMSG_TYPE_STRING },
+ [DOWNLOAD_PSW] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
+ [DOWNLOAD_SYNC] = { .name = "sync", .type = BLOBMSG_TYPE_INT32 },
+ [DOWNLOAD_SEGMENT_SIZE] = { .name = "segment_size", .type = BLOBMSG_TYPE_INT32 },
+};
+
+#if 0
+static size_t curl_cb(void *buffer, size_t size, size_t nmemb, void *stream)
+{
+ //OTA_ERR(" response: %s(%d:%d)\n", (char *)buffer, size, nmemb);
+ OTA_ERR(" response:%d:%d\n", size, nmemb);
+ return size * nmemb;
+}
+#endif
+// FBF file related definition
+static int _ota_download_progress = 0;
+static int ota_download_progress = 0;
+char * fbf_version_string = NULL;
+// Add by mbtk
+int Download_flag = 0;
+#define TR069_FBF_HEADER_SIZE 13
+#define DLCMD_IMAGE_TYPE_FIELD_BIT 4
+#define DLCMD_IMAGE_TYPE_FIELD_SIZE_BITS 4
+#define MAX_NUMBER_OF_FLASH_DEVICES_IN_MASTER_HEADER 4
+#define MAX_NUMBER_OF_FLASH_DEVICES_IN_DEVICE_HEADER 150
+#define BLOCK_DEVICE_SECTOR_SIZE (8*1024)
+#define MAX_RESEVERD_LEN 4
+#define MAX_NUM_SKIP_BLOCKS 32
+#define UNIQUE_SIZE 24
+#define NUM_OF_SUPPORTED_FLASH_DEVS 4
+#define RSA_IMAGE_ID 0x52534149
+#define MINI_SIZE (128)
+#define CHECKSUM_CACHE_SIZE (128)
+#define FILE_VERIFY_RAM_SIZE (server_cfg.block_size)
+
+struct version_check_context {
+ char * url;
+ int size;
+ int used;
+ char version[OTA_MAX_STRING_LEN];
+};
+
+typedef struct {
+ unsigned int Image_ID;
+ unsigned int Image_In_TIM;
+ unsigned int Flash_partition;
+ unsigned int Flash_erase_size;
+ unsigned int commands;
+ unsigned int First_Sector;
+ unsigned int length;
+ unsigned int Flash_Start_Address;
+ unsigned int reserve[MAX_RESEVERD_LEN];
+ unsigned int ChecksumFormatVersion2;
+} __attribute__((packed)) ImageStruct_11;
+
+typedef ImageStruct_11 * PImageStruct_11;
+
+typedef struct {
+ unsigned int Total_Number_Of_SkipBlocks;
+ unsigned int Size_of_Block[MAX_NUM_SKIP_BLOCKS];
+} SkipBlocksInfoStruct;
+
+typedef struct {
+ unsigned int EraseAll;
+ unsigned int ResetBBT;
+ unsigned int NandID;
+ unsigned int Reserved[MAX_RESEVERD_LEN - 1];
+ SkipBlocksInfoStruct SkipBlocksInfoStruct;
+} FlashOptStruct;
+
+typedef struct {
+ unsigned int DeviceFlags;
+ unsigned int DeviceParametes[16];
+ FlashOptStruct FlashOpt;
+ unsigned int ProductionMode; // production mode
+ unsigned char OptValue; // choice: 0 - Not reset after download, 1 - Reset after download
+ unsigned char ChipID;
+ unsigned char BBCS_EN;
+ unsigned char CRCS_EN;
+ unsigned int Reserved[MAX_RESEVERD_LEN-2];
+ unsigned int nOfImages;
+ ImageStruct_11 imageStruct_11[MAX_NUMBER_OF_FLASH_DEVICES_IN_MASTER_HEADER];
+} __attribute__((packed)) DeviceHeader_11;
+
+typedef DeviceHeader_11 * PDeviceHeader_11;
+
+typedef struct {
+ char Unique[UNIQUE_SIZE];
+ unsigned short int Flash_Device_Spare_Area_Size[NUM_OF_SUPPORTED_FLASH_DEVS];
+ unsigned short int Format_Version;
+ unsigned short int Size_of_Block;
+ unsigned int Bytes_To_Program;
+ unsigned int Bytes_To_Verify;
+ unsigned int Number_of_Bytes_To_Erase;
+ unsigned int Main_Commands;
+ unsigned int nOfDevices;
+ unsigned int DLerVeriosn;
+ unsigned int deviceHeaderOffset[MAX_NUMBER_OF_FLASH_DEVICES_IN_MASTER_HEADER];
+} __attribute__((packed)) MasterBlockHeader;
+
+typedef MasterBlockHeader * PMasterBlockHeader;
+
+struct imginfo_table {
+ unsigned int Img_Len;
+ unsigned int Img_Commands;
+ unsigned int Img_Start_Address;
+ unsigned int Img_Checksum;
+ unsigned int Flash_Start_Address;
+ unsigned int Flash_Erase_Size;
+ unsigned int Img_ID;
+ unsigned int Image_In_TIM;
+#ifdef CONFIG_AB_SYSTEM
+ int fd;
+ char name[32];
+ char dev[16];
+ unsigned int Img_Remain_Len;
+ unsigned int cs;
+ unsigned int Block_Start_Address;
+ unsigned int partition_size;
+ int erased;
+#endif
+ struct imginfo_table * next;
+};
+
+typedef struct imginfo_table ImginfoTable;
+
+enum {
+ HEADER,
+ CONTENT,
+};
+
+struct image_state {
+ struct imginfo_table * image_info;
+ struct image_state * next_image;
+ int result;
+};
+
+struct image_process_context {
+ ImginfoTable * image_info_table;
+ ImginfoTable * current_process;
+ unsigned int processed_cnt;
+ int state;
+ char * flash_cache;
+ int flash_cache_index;
+ int (*flash_cb)(struct image_process_context *, char *, int);
+ unsigned char * checksum_cache;
+ int checksum_cache_index;
+ unsigned int image_checksum;
+ int ota_download_notification_cnt;
+ struct image_state * image_state_list;
+ int download_result;
+ int fd;
+ int upgrade_method;
+ int dual_tim;
+ int same_tim;
+ int upgrade_bootloader;
+};
+
+typedef struct{
+ unsigned int CurImageID;
+ unsigned int ImageType;
+ unsigned int ImageState; /* 1: new image is backed up, 0: not backed up */
+ unsigned int ImageBkAddr;
+ unsigned int ImageBkLen;
+ unsigned int SegState;
+ unsigned int SegIndex;
+ unsigned int SegDestBkAddr;
+ unsigned int SegDestBkLen;
+ unsigned int PreTailAddr;
+ unsigned int PreTailLen;
+ unsigned int NextHeadAddr;
+ unsigned int NextHeadLen;
+ unsigned int NextSegWriteOffset;
+ unsigned int NextSegReadOffset;
+ unsigned int NextSegEraseOffset;
+}SDfotaState, *pSDfotaState;
+
+struct DeviceHeader_11_tr069 {
+ unsigned int DeviceFlags;
+ unsigned int DeviceParameters[16]; /* Device Parameters, reserve 16 U32 here, will be defined depending on different devices */
+ FlashOptStruct FlashOpt;
+ unsigned int ProductionMode; // production mode
+ unsigned char OptValue; // choice: 0 - Not reset after download, 1 - Reset after download
+ unsigned char ChipID;
+ unsigned char BBCS_EN;
+ unsigned char CRCS_EN;
+ unsigned int Reserved[MAX_RESEVERD_LEN-2];
+ unsigned int nOfImages; /* number of images */
+ ImageStruct_11 imageStruct_11[0]; /* array of image structs */
+} __attribute__((packed)); // Same as struct 'DeviceHeader_11' but the ImageStruct cnt is zero
+
+struct DDRT_STATE{
+ unsigned int test_proc :1; //1: start, 0: done
+ unsigned int last_res :1; //1: fail, 0: pass
+ unsigned int total_times :15;
+ unsigned int fail_times :15;
+};
+
+typedef union{
+ unsigned int value;
+ struct DDRT_STATE bits;
+}DDRTestState, *pDDRTestState;
+
+struct tr069_firmware_flag {
+ unsigned int header;
+ unsigned int upgrade_flag; //1,upgrade; 2, backup boot
+ unsigned int fbf_flash_address;
+ unsigned int fbf_file_size;
+ unsigned int erase_psm;
+ unsigned int erase_psm_address;
+ unsigned int erase_psm_size;
+ unsigned int erase_fs;
+ unsigned int fs_erase_address;
+ unsigned int fs_erase_size;
+ unsigned int upgrade_method; //1,TR069; 2, SD; 3,WebUI
+ unsigned int UnlockKeyFlag;
+ unsigned int production_mode_flag; //for production mode
+ unsigned int eehP[2];
+ unsigned int cpsr[2];
+ unsigned int hawk[2];
+ unsigned int imsd[2];
+ unsigned int pipe[2];
+ unsigned int fast[2];
+ unsigned int apmf[2];
+ unsigned int pid[2];
+ unsigned int vid[2];
+ unsigned int obmdl[2];
+ unsigned int dlflag[2];
+ unsigned int ramdump[2];
+ unsigned int dfota_n_of_images;
+ unsigned int dfota_need_copy_only;
+ unsigned int dfota_conpy_len;
+#ifdef CONFIG_AB_SYSTEM
+ unsigned int active_slot; /* prev active slot */
+ unsigned int temp_active_slot; /* current active slot */
+ unsigned int reboot_cnt;
+ unsigned int synced;
+ unsigned int rsvd[16];
+#endif
+ unsigned int nocp[2];
+ unsigned int TrustBootStatus;
+ char mversion[128];
+ SDfotaState SDfotaInfo;
+ unsigned int ref_count;
+ unsigned int flag_len;
+ unsigned int version;
+ unsigned int DDR_ID;
+ unsigned int Flash_ID;
+ unsigned int cplog[2];
+ DDRTestState ddrt_state;
+ unsigned int svc_state;
+ char MVersion_B[128]; /* only use for AB system */
+ unsigned int Reserved[68]; /* reserved for asr */
+ unsigned int ReservedForCustomer[35]; /* reserved for customer */
+ /* reserve to make the ASR_Flag length as 1KB */
+
+ unsigned int crc;
+ /* NOTICE !!!
+ * If you change this structure, you must also sync the change to OBM/Uboot/OTA/Telephony
+ * OBM: obm/Common/Misc/asr_flag.h
+ * Uboot: uboot/board/Marvell/common/asr_flag.h
+ * OTA: services/ota/otad.c
+ * Telephony: lte_telephony/apps/cp_load/cploader.h
+ * If add a new member to this structure, must decrease the size of Reserved[]
+ */
+};
+
+#define ASRFLAG_HEADER 0x464F5441
+
+/* ASR Flag version history
+* 1.0.0.1: support dual asr flag
+* 1.0.0.2: support asr flag crc
+*/
+#define ASRFLAG_VERSION_LEGACY 0xFFFFFFFF
+#define ASRFLAG_VERSION_DAF 0x31303031
+#define ASRFLAG_VERSION_CRC 0x31303032
+#define ASRFLAG_VERSION ASRFLAG_VERSION_CRC
+
+struct download_timer_context {
+ int type;
+ int size;
+ int segment_size;
+ char * url;
+ char * username;
+ char * pwd;
+ int file_size;
+ int received_size;
+};
+
+struct download_timer_context download_method_ctx = {0};
+static struct tr069_firmware_flag gAsrFlag;
+
+static int asrflag_daf_enabled(struct tr069_firmware_flag * p_asrflag)
+{
+ if(p_asrflag->version != ASRFLAG_VERSION_LEGACY &&
+ p_asrflag->version >= ASRFLAG_VERSION_DAF)
+ return 1;
+
+ return 0;
+}
+
+static int asrflag_crc_enabled(struct tr069_firmware_flag * p_asrflag)
+{
+ if(p_asrflag->version != ASRFLAG_VERSION_LEGACY &&
+ p_asrflag->version >= ASRFLAG_VERSION_CRC)
+ return 1;
+
+ return 0;
+}
+
+static unsigned int malbrain_crc32(unsigned int crcu32, const unsigned char *ptr, unsigned int buf_len)
+{
+ static const unsigned int s_crc32[16] = {
+ 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+ };
+ if (!ptr)
+ return 0;
+ crcu32 = ~crcu32;
+ while (buf_len--)
+ {
+ unsigned char b = *ptr++;
+ crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
+ crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
+ }
+ return ~crcu32;
+}
+
+static void asrflag_update_crc(struct tr069_firmware_flag * p_asrflag)
+{
+ unsigned int crc_len, crc_val;
+ crc_len = sizeof(struct tr069_firmware_flag) - 4; /* 4 bytes is CRC itself */
+
+ crc_val = malbrain_crc32(0, (unsigned char *)p_asrflag, crc_len);
+
+ p_asrflag->crc = crc_val;
+
+ return;
+}
+
+static int asrflag_is_invalid(struct tr069_firmware_flag * p_asrflag)
+{
+ unsigned int crc_len, crc_val;
+
+ if(p_asrflag->header != ASRFLAG_HEADER)
+ return 1;
+
+ if(!asrflag_crc_enabled(p_asrflag))
+ return 0;
+
+ crc_len = sizeof(struct tr069_firmware_flag) - 4; /* 4 bytes is CRC itself */
+ crc_val = malbrain_crc32(0, (unsigned char *)p_asrflag, crc_len);
+
+ if(p_asrflag->crc != crc_val) {
+ OTA_ERR("asr flag mismatch: 0x%x 0x%x\n", crc_val, p_asrflag->crc);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int get_asr_flag(struct tr069_firmware_flag *p_asrflag)
+{
+ int fd = 0, ret = 0;
+ unsigned int step = 0, offset = 0, flaglen = 0;
+ struct tr069_firmware_flag *main_asrflag = NULL;
+ struct tr069_firmware_flag *backup_asrflag = NULL;
+ flaglen = sizeof(struct tr069_firmware_flag);
+
+ main_asrflag = malloc(flaglen);
+ if(main_asrflag == NULL) {
+ OTA_ERR("Fail to malloc\n");
+ return -1;
+ }
+
+ fd = open(server_cfg.mtd_asrflag, O_RDONLY);
+ if (fd < 0) {
+ free(main_asrflag);
+ OTA_ERR("Fatal error: can't open asr flag %s\n", server_cfg.mtd_asrflag);
+ return -1;
+ }
+
+ if (read(fd, main_asrflag, flaglen) < 0)
+ goto error;
+ if ( asrflag_is_invalid(main_asrflag) ) {
+ backup_asrflag = main_asrflag;
+ main_asrflag = NULL;
+
+ step = (server_cfg.block_size)?server_cfg.block_size:0x1000;
+ offset = step;
+
+ while (1) {
+ if(lseek(fd, offset, SEEK_SET) < 0 )
+ goto error;
+ ret = read(fd, backup_asrflag, flaglen);
+ if(ret < 0)
+ goto error;
+
+ if(ret == 0 || !asrflag_is_invalid(backup_asrflag) )
+ break;
+
+ offset += step;
+ }
+
+ /* can't find valid backup ASR Flag */
+ if ( asrflag_is_invalid(backup_asrflag) ) {
+ free(backup_asrflag); backup_asrflag = NULL;
+ }
+ } else {
+ if( asrflag_daf_enabled(main_asrflag) ) {
+ backup_asrflag = malloc(flaglen);
+ if(backup_asrflag != NULL)
+ {
+ if(lseek(fd, main_asrflag->flag_len, SEEK_SET) < 0)
+ goto error;
+
+ if (read(fd, backup_asrflag, flaglen) < 0)
+ goto error;
+
+ if( asrflag_is_invalid(backup_asrflag) )
+ {
+ free(backup_asrflag);
+ backup_asrflag = NULL;
+ }
+ }
+ } else {
+ /* old way which doesn't support backup */
+ memcpy(p_asrflag, main_asrflag, flaglen);
+ close(fd);
+ free(main_asrflag);
+ return 0;
+ }
+ }
+
+ if(main_asrflag == NULL && backup_asrflag == NULL) {
+ goto error;
+ } else if(main_asrflag == NULL) {
+ memcpy(p_asrflag, backup_asrflag, flaglen);
+ } else if (backup_asrflag == NULL) {
+ memcpy(p_asrflag, main_asrflag, flaglen);
+ } else {
+ if(memcmp(main_asrflag, backup_asrflag, flaglen))
+ OTA_ERR("Main asr flag mismatch with backup\n");
+ if(backup_asrflag->ref_count > main_asrflag->ref_count)
+ memcpy(p_asrflag, backup_asrflag, flaglen);
+ else
+ memcpy(p_asrflag, main_asrflag, flaglen);
+ }
+
+ close(fd);
+ if(main_asrflag) free(main_asrflag);
+ if(backup_asrflag) free(backup_asrflag);
+ return 0;
+
+error:
+ close(fd);
+ if(main_asrflag) free(main_asrflag);
+ if(backup_asrflag) free(backup_asrflag);
+ return -1;
+}
+
+static int write_asr_flag(struct tr069_firmware_flag *p_asrflag)
+{
+ unsigned int flaglen = 0;
+ int n = 0;
+ int fd = open(server_cfg.mtd_asrflag, O_RDWR);
+ if (fd < 0) {
+ OTA_ERR("Fatal error: can't open asr flag %s\n", server_cfg.mtd_asrflag);
+ return -1;
+ }
+
+ flaglen = sizeof(struct tr069_firmware_flag);
+ if (p_asrflag->ref_count ++ == 0xFFFFFFFF)
+ p_asrflag->ref_count = 0;
+
+ asrflag_update_crc(p_asrflag);
+
+ n = write(fd, p_asrflag, flaglen);
+ if (n != flaglen) {
+ OTA_ERR("Fatal error: write %d bytes(expect %d) to asr flag\n", n, sizeof(gAsrFlag));
+ close(fd);
+ return -1;
+ }
+
+ if( asrflag_daf_enabled(p_asrflag) ) {
+ lseek(fd, p_asrflag->flag_len, SEEK_SET);
+
+ n = write(fd, p_asrflag, flaglen);
+ if (n != flaglen) {
+ OTA_ERR("Fatal error: write %d bytes(expect %d) to asr flag\n", n, sizeof(gAsrFlag));
+ close(fd);
+ return -1;
+ }
+ }
+
+ close(fd);
+ return 0;
+}
+
+#ifdef CONFIG_AB_SYSTEM
+static int get_inactive_system()
+{
+ if (get_asr_flag(&gAsrFlag)) {
+ OTA_ERR("Fatal error: can't read asr flag %s\n", server_cfg.mtd_asrflag);
+ return -1;
+ }
+
+ OTA_DEBUG("Asr Flag: active_slot: %c(0x%x), temp_active_slot: %c(0x%x), reboot_cnt: %d, synced: %d\n",
+ gAsrFlag.active_slot, gAsrFlag.active_slot,
+ gAsrFlag.temp_active_slot, gAsrFlag.temp_active_slot,
+ gAsrFlag.reboot_cnt, gAsrFlag.synced);
+
+ if (gAsrFlag.active_slot != gAsrFlag.temp_active_slot) {
+ OTA_DEBUG("System %c is valid, now update the active slot...\n", gAsrFlag.temp_active_slot);
+ gAsrFlag.active_slot = gAsrFlag.temp_active_slot;
+ gAsrFlag.reboot_cnt = 0;
+ gAsrFlag.synced = 0;
+ if (write_asr_flag(&gAsrFlag)) {
+ OTA_ERR("Fatal error: fail to write asr flag\n");
+ return -1;
+ }
+ } else {
+ if (gAsrFlag.synced == 0) {
+ /* if active_slot == temp_active_slot & synced = 0, the system rollback must happened */
+ gSystemHasRollbackFlag = 1;
+ }
+ }
+ if (gAsrFlag.temp_active_slot == SYSTEM_B)
+ return SYSTEM_A;
+ return SYSTEM_B;
+}
+
+static int complete_read(int fd, char *buf, int size)
+{
+ int pos = 0;
+ while (pos != size) {
+ int n = read(fd, buf + pos, size - pos);
+ if (n < 0) {
+ OTA_ERR("Fatal error: read failed: %d...\n", n);
+ return -1;
+ }
+ pos += n;
+ }
+
+ return pos;
+}
+
+static int complete_write(int fd, char *buf, int size)
+{
+ int pos = 0;
+ while (pos != size) {
+ int n = write(fd, buf + pos, size - pos);
+ if (n < 0) {
+ OTA_ERR("Fatal error: write failed: %d...\n", n);
+ return -1;
+ }
+ pos += n;
+ }
+
+ return pos;
+}
+
+static int __system_compare(char *src, char *dst, int size, int erasesize)
+{
+ char sdev[32] = {0}, ddev[32] = {0};
+ sprintf(sdev, "/dev/%s", src);
+ sprintf(ddev, "/dev/%s", dst);
+ int fdSrc = open(sdev, O_RDWR | O_SYNC);
+ int fdDst = open(ddev, O_RDWR | O_SYNC);
+
+ int ret = -1;
+ char *sbuf = NULL, *dbuf = NULL;
+ if (fdSrc < 0 || fdDst < 0) {
+ OTA_ERR("Fatal error: can't open dev, src: %s, fdSrc: %d, dst: %s, fdDst: %d\n",
+ src, fdSrc, dst, fdDst);
+ goto err;
+ }
+
+ sbuf = malloc(erasesize);
+ if (!sbuf) {
+ OTA_ERR("Fatal error: can't malloc 0x%x for src buf\n", erasesize);
+ goto err;
+ }
+
+ dbuf = malloc(erasesize);
+ if (!dbuf) {
+ OTA_ERR("Fatal error: can't malloc 0x%x for dst buf\n", erasesize);
+ goto err;
+ }
+
+ OTA_DEBUG("Src: %s, Dst: %s, Size: 0x%x...\n", sdev, ddev, size);
+ while (size) {
+ int n = erasesize;
+ if (size < erasesize)
+ n = size;
+ memset(sbuf, 0, erasesize);
+ memset(dbuf, 0, erasesize);
+
+ if (complete_read(fdSrc, sbuf, n) < 0)
+ goto err;
+ if (complete_read(fdDst, dbuf, n) < 0)
+ goto err;
+
+ if (memcmp(sbuf, dbuf, n) != 0) {
+ OTA_ERR("Src: %s, Dst: %s, are not same, NEED to sync\n", sdev, ddev);
+ goto err;
+ }
+ size -= n;
+ }
+
+ ret = 0;
+ OTA_DEBUG("Src: %s, Dst: %s, are same, NO NEED to sync\n", sdev, ddev);
+err:
+ if (fdSrc >= 0)
+ close(fdSrc);
+ if (fdDst >= 0)
+ close(fdDst);
+ if (sbuf)
+ free(sbuf);
+ if (dbuf)
+ free(dbuf);
+ return ret;
+}
+
+static int __system_sync(char *src, char *dst, int size, int erasesize)
+{
+ if (__system_compare(src, dst, size, erasesize) == 0)
+ return 0;
+
+ int ret = -1;
+ char *buf = NULL;
+ char sdev[32] = {0}, ddev[32] = {0};
+ sprintf(sdev, "/dev/%s", src);
+ sprintf(ddev, "/dev/%s", dst);
+ int fdSrc = open(sdev, O_RDWR | O_SYNC);
+ int fdDst = open(ddev, O_RDWR | O_SYNC);
+#ifndef CONFIG_PARTITION_EMMC
+ struct erase_info_user mtdEraseInfo;
+ struct mtd_info_user mtdInfo;
+ if (ioctl(fdDst, MEMGETINFO, &mtdInfo)) {
+ OTA_ERR("Could not get MTD device info from %s\n", ddev);
+ goto err;
+ }
+ mtdEraseInfo.start = 0;
+ mtdEraseInfo.length = mtdInfo.erasesize;
+#endif
+ if (fdSrc < 0 || fdDst < 0) {
+ OTA_ERR("Fatal error: can't open dev, src: %s, fdSrc: %d, dst: %s, fdDst: %d\n",
+ src, fdSrc, dst, fdDst);
+ goto err;
+ }
+
+ buf = malloc(erasesize);
+ if (!buf) {
+ OTA_ERR("Fatal error: can't malloc 0x%x\n", erasesize);
+ goto err;
+ }
+
+ OTA_DEBUG("Sync Src: %s to Dst: %s, Size: 0x%x...\n", sdev, ddev, size);
+ while (size) {
+ int n = erasesize;
+ if (size < erasesize)
+ n = size;
+ memset(buf, 0, erasesize);
+
+ if (complete_read(fdSrc, buf, n) < 0)
+ goto err;
+#ifndef CONFIG_PARTITION_EMMC
+ ioctl(fdDst, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(fdDst, MEMERASE, &mtdEraseInfo);
+#endif
+ if (complete_write(fdDst, buf, n) < 0)
+ goto err;
+ size -= n;
+#ifndef CONFIG_PARTITION_EMMC
+ mtdEraseInfo.start += mtdInfo.erasesize;
+#endif
+ }
+
+ ret = 0;
+err:
+ if (fdSrc >= 0)
+ close(fdSrc);
+ if (fdDst >= 0)
+ close(fdDst);
+ if (buf)
+ free(buf);
+ return ret;
+}
+
+static int get_file_size(const char *path)
+{
+ int filesize = -1;
+ struct stat statbuff;
+ if(stat(path, &statbuff) < 0)
+ return filesize;
+ else
+ filesize = statbuff.st_size;
+ return filesize;
+}
+
+static int system_sync()
+{
+ int changed = 0;
+
+ OTA_DEBUG("Start to sync system %c to %c...\n", gAsrFlag.temp_active_slot, gInActiveSystem);
+ for (int i = 0; i < server_cfg.mtd_cnt; i++) {
+ struct image_mtd_info *pSrc = &server_cfg.image_mtd_info[i];
+ if (pSrc->flag == gAsrFlag.active_slot) {
+ for (int j = 0; j < server_cfg.mtd_cnt; j++) {
+ struct image_mtd_info *pDst = &server_cfg.image_mtd_info[j];
+ if (pDst->flag == gInActiveSystem) {
+ if (strlen(pSrc->name) == strlen(pDst->name)) {
+ int len = strlen(pSrc->name);
+ if (strncmp(pSrc->name, pDst->name, len - 3) == 0) {
+ /* remove the suffix "-a\n" or "-b\n", 3 bytes */
+ OTA_DEBUG("Start to sync %s to %s...\n", pSrc->name, pDst->name);
+ if (__system_sync(pSrc->dev, pDst->dev, pDst->size, pDst->erasesize) < 0) {
+ OTA_ERR("Fatal error: sync failed...\n");
+ return -1;
+ }
+ OTA_DEBUG("Sync %s to %s OK...\n", pSrc->name, pDst->name);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (strncmp(gAsrFlag.mversion, gAsrFlag.MVersion_B, 128) != 0) {
+ changed = 1;
+ OTA_DEBUG("diff mversion a: %s, mversion b: %s\n", gAsrFlag.mversion, gAsrFlag.MVersion_B);
+ if (gInActiveSystem == SYSTEM_A) {
+ OTA_DEBUG("mversion b -> a\n");
+ memset(gAsrFlag.mversion, 0, 128);
+ strncpy(gAsrFlag.mversion, gAsrFlag.MVersion_B, 128);
+ } else {
+ OTA_DEBUG("mversion a -> b\n");
+ memset(gAsrFlag.MVersion_B, 0, 128);
+ strncpy(gAsrFlag.MVersion_B, gAsrFlag.mversion, 128);
+ }
+ }
+
+ OTA_DEBUG("System sync done, update the synced flag...\n");
+ if (!changed && gAsrFlag.synced == 1) {
+ /* no need to save flag to flash if synced flag is 1
+ * directly return to decrease write flash */
+ OTA_DEBUG("The synced flag was set already, no need to update.\n");
+ return 0;
+ }
+
+ gAsrFlag.synced = 1;
+ gAsrFlag.reboot_cnt = 0;
+
+ OTA_DEBUG("Save Asr Flag: active_slot: %c(0x%x), temp_active_slot: %c(0x%x), reboot_cnt: %d, synced: %d\n",
+ gAsrFlag.active_slot, gAsrFlag.active_slot,
+ gAsrFlag.temp_active_slot, gAsrFlag.temp_active_slot,
+ gAsrFlag.reboot_cnt, gAsrFlag.synced);
+ return write_asr_flag(&gAsrFlag);
+}
+
+#endif
+
+
+static int tr069_fbf_parse(void * img_addr, int len, struct image_process_context * context)
+{
+ MasterBlockHeader* pMasterHeader = NULL;
+ PDeviceHeader_11 pDevHeader_11=NULL;
+ PImageStruct_11 pImage_11=NULL;
+ ImginfoTable * image_table = NULL, * temp_table = NULL;
+
+ unsigned int * temp_p = NULL;
+ unsigned int img_num,img_start;
+
+ pMasterHeader = (MasterBlockHeader*)img_addr;
+ if ((pMasterHeader->Format_Version != 11)) {
+ OTA_ERR("Bad version\n");
+ return -1;
+ }
+
+ if (pMasterHeader->nOfDevices != 1) {
+ OTA_ERR("Bad content\n");
+ return -1;
+ }
+
+ if ((len + context->processed_cnt) < sizeof(MasterBlockHeader)) {
+ return len;
+ }
+
+ if ((len + context->processed_cnt) <
+ (pMasterHeader->deviceHeaderOffset[0] + sizeof(struct DeviceHeader_11_tr069))) {
+ OTA_ERR("length less than device offset[%d:%d]\n",
+ pMasterHeader->deviceHeaderOffset[0], sizeof(struct DeviceHeader_11_tr069));
+ return len;
+ }
+
+ {
+ // Checking FBF vesion string, if present
+ const char * version = (const char *)&pMasterHeader->Unique[12];
+ if (strlen(version)) OTA_DEBUG("Handle FBF version: %s\n", version);
+ if (fbf_version_string) {
+ if (strcmp(fbf_version_string, version)) {
+ OTA_ERR("Version not match: %s\n", fbf_version_string);
+ return -1;
+ }
+ }
+ }
+
+ temp_p = (unsigned int *)(pMasterHeader->deviceHeaderOffset[0] + (unsigned int)img_addr);
+ pDevHeader_11 = (PDeviceHeader_11)temp_p;
+ OTA_DEBUG("parsed image number is :%d\n", pDevHeader_11->nOfImages);
+ if ((len + context->processed_cnt) <
+ (pMasterHeader->deviceHeaderOffset[0] + sizeof(struct DeviceHeader_11_tr069) +
+ sizeof(ImageStruct_11) * pDevHeader_11->nOfImages)) {
+ return len;
+ }
+
+ update_oemd = 0;
+ for(img_num = 0; img_num < pDevHeader_11->nOfImages; img_num ++) {
+ temp_p = (unsigned int*)&pDevHeader_11->imageStruct_11[img_num];
+ pImage_11 = (PImageStruct_11)temp_p;
+ img_start = pImage_11->First_Sector<<TR069_FBF_HEADER_SIZE;
+
+ temp_table = image_table;
+#ifdef CONFIG_AB_SYSTEM
+ if (pImage_11->Image_ID == FOTA_FBFVERSION_IMAGEID) {
+ server_cfg.fotav_offset_in_fbf = img_start;
+ OTA_DEBUG("%s: fotav_offset_in_fbf = 0x%x\n", __func__, server_cfg.fotav_offset_in_fbf);
+ }
+
+ if (pImage_11->reserve[0] != 0) {
+ OTA_DEBUG("Found A/B Image, ID: 0x%x, InTim: %d, "
+ "Partition: 0x%x, EraseSize: 0x%x, "
+ "CMD: 0x%x, FirstSector: 0x%x, Len: 0x%x, "
+ "FlashStartAddress(A): 0x%x, FlashStartAddress(B): 0x%x, "
+ "CheckSum: 0x%x\n",
+ pImage_11->Image_ID, pImage_11->Image_In_TIM,
+ pImage_11->Flash_partition, pImage_11->Flash_erase_size,
+ pImage_11->commands, pImage_11->First_Sector, pImage_11->length,
+ pImage_11->Flash_Start_Address, pImage_11->reserve[0],
+ pImage_11->ChecksumFormatVersion2);
+
+ if (gInActiveSystem == SYSTEM_B) {
+ /* there are no flash address B for obm & timh */
+ if (pImage_11->Image_ID != IMAGE_ID_TIMH && pImage_11->Image_ID != IMAGE_ID_OBM)
+ pImage_11->Flash_Start_Address = pImage_11->reserve[0];
+ }
+ }
+
+ if (pImage_11->Image_ID == IMAGE_ID_OBM)
+ obm_real_size = pImage_11->length;
+
+#ifdef CONFIG_PARTITION_EMMC
+ /* the unit of address in fbf was: block */
+ pImage_11->Flash_Start_Address *= server_cfg.emmc_block_size;
+#endif
+
+ int i;
+ struct image_mtd_info *pImageMtdInfo = NULL;
+ for (i = 0; i < server_cfg.mtd_cnt; i++) {
+ pImageMtdInfo = &server_cfg.image_mtd_info[i];
+ if (pImage_11->Image_ID == IMAGE_ID_TIMH || pImage_11->Image_ID == IMAGE_ID_OBM) {
+ context->upgrade_bootloader = 1;
+ #ifdef CONFIG_PARTITION_EMMC
+ if (pImage_11->Image_In_TIM == TIMH_INC) {
+ if (strstr(pImageMtdInfo->name, "bootloader0"))
+ goto found_bootloader;
+ } else if (pImage_11->Image_In_TIM == TIMH_RECOVERY_INC) {
+ if (strstr(pImageMtdInfo->name, "bootloader1"))
+ goto found_bootloader;
+ } else {
+ exit(-1);
+ }
+ #else
+ if (strstr(pImageMtdInfo->name, "bootloader"))
+ goto found_bootloader;
+ #endif
+ }
+
+ if (gInActiveSystem != pImageMtdInfo->flag)
+ /* skip the active system mtd */
+ continue;
+ if ((pImageMtdInfo->flash_start_offset == pImage_11->Flash_Start_Address) ||
+ (
+ /* handle cpimage */
+ (pImage_11->Flash_Start_Address > pImageMtdInfo->flash_start_offset) &&
+ (pImage_11->Flash_Start_Address < (pImageMtdInfo->flash_start_offset + pImageMtdInfo->size))
+ )) {
+ break;
+ }
+ }
+
+ if (i == server_cfg.mtd_cnt) {
+ OTA_ERR("FBF is not match the current system...(0x%x)\n", pImage_11->Flash_Start_Address);
+ continue;
+ }
+found_bootloader:
+#endif
+ image_table = (ImginfoTable *)malloc(sizeof(ImginfoTable));
+ if (!image_table) {
+ OTA_ERR("Failed! cannot malloc memory for image infor table\n");
+ return -1;
+ }
+
+ image_table->Img_Len= pImage_11->length;
+ image_table->Img_Commands = pImage_11->commands;
+ image_table->Img_Checksum = pImage_11->ChecksumFormatVersion2;
+ image_table->Flash_Erase_Size = pImage_11->Flash_erase_size;
+ image_table->Img_Start_Address = img_start;
+ image_table->Flash_Start_Address = pImage_11->Flash_Start_Address;
+ image_table->Img_ID = pImage_11->Image_ID;
+ image_table->Image_In_TIM = pImage_11->Image_In_TIM;
+ if (pImage_11->Image_ID == OEMDDENTIFIER)
+ update_oemd = 1;
+ image_table->next = temp_table;
+#ifdef CONFIG_AB_SYSTEM
+ char dev[32] = {0};
+ sprintf(dev, "/dev/%s", pImageMtdInfo->dev);
+ if (image_table->Img_ID == IMAGE_ID_OBM) {
+ if (image_table->Image_In_TIM == TIMH_INC)
+ image_table->fd = open(tmp_obm_main_file, O_CREAT | O_RDWR | O_SYNC, 777);
+ else if (image_table->Image_In_TIM == TIMH_RECOVERY_INC) {
+ image_table->fd = open(tmp_obm_bk_file, O_CREAT | O_RDWR | O_SYNC, 777);
+ context->dual_tim = 1;
+ } else {
+ OTA_ERR("%s %d: fatal error, unkown Image_In_TIM: %d\n",
+ __func__, __LINE__, image_table->Image_In_TIM);
+ exit(-1);
+ }
+ } else if (image_table->Img_ID == IMAGE_ID_TIMH) {
+ if (image_table->Image_In_TIM == TIMH_INC)
+ image_table->fd = open(tmp_timh_main_file, O_CREAT | O_RDWR | O_SYNC, 777);
+ else if (image_table->Image_In_TIM == TIMH_RECOVERY_INC) {
+ image_table->fd = open(tmp_timh_bk_file, O_CREAT | O_RDWR | O_SYNC, 777);
+ context->dual_tim = 1;
+ } else {
+ OTA_ERR("%s %d: fatal error, unkown Image_In_TIM: %d\n",
+ __func__, __LINE__, image_table->Image_In_TIM);
+ exit(-1);
+ }
+ } else {
+ image_table->fd = open(dev, O_RDWR | O_SYNC);
+ }
+ image_table->partition_size = pImageMtdInfo->size;
+ image_table->erased = 0;
+ memset(image_table->dev, 0, sizeof(image_table->dev));
+ memset(image_table->name, 0, sizeof(image_table->name));
+ sprintf(image_table->dev, "%s", pImageMtdInfo->dev);
+ sprintf(image_table->name, "%s", pImageMtdInfo->name);
+ /* 4K align */
+ image_table->Img_Remain_Len = ((image_table->Img_Len + FBF_FILE_SECTOR_SIZE - 1) & (~ (FBF_FILE_SECTOR_SIZE - 1)));
+ image_table->Block_Start_Address = pImageMtdInfo->flash_start_offset;
+ OTA_DEBUG("Parse new image: start: 0x%08x, len: 0x%08x(flash offset: 0x%08x, %s)\n", img_start, image_table->Img_Len,
+ image_table->Flash_Start_Address, pImageMtdInfo->name);
+#else
+ OTA_DEBUG("Parse new image: 0x%08x~0x%08x\n", img_start, img_start + image_table->Img_Len);
+#endif
+ }
+
+ context->image_info_table = image_table;
+ if(pDevHeader_11->Reserved[0] == 1){ //DFota
+ context->upgrade_method = 4;
+ }
+ else{
+ context->upgrade_method = 0;
+ }
+
+ OTA_DEBUG(" first offset: %d\n", pMasterHeader->deviceHeaderOffset[0]);
+ OTA_DEBUG(" all header size: %d\n", (pMasterHeader->deviceHeaderOffset[0] + sizeof(struct DeviceHeader_11_tr069) +
+ sizeof(ImageStruct_11) * pDevHeader_11->nOfImages));
+ OTA_DEBUG(" already processed: %d\n", context->processed_cnt);
+#ifdef CONFIG_AB_SYSTEM
+#ifndef CONFIG_AB_SYSTEM_DFOTA
+ /* once parse image ok, clear the synced flag immediately */
+ gAsrFlag.synced = 0;
+ write_asr_flag(&gAsrFlag);
+#endif
+#endif
+ return (pMasterHeader->deviceHeaderOffset[0] + sizeof(struct DeviceHeader_11_tr069) +
+ sizeof(ImageStruct_11) * pDevHeader_11->nOfImages) - context->processed_cnt;
+}
+
+static void dump_table(struct image_process_context * context)
+{
+ ImginfoTable * temp = context->image_info_table;
+ while (temp) {
+#ifdef CONFIG_AB_SYSTEM
+ OTA_DEBUG("Get Image from start: 0x%08x, len: 0x%08x, flashoffset: 0x%08x(%s)\n",
+ temp->Img_Start_Address, temp->Img_Len, temp->Flash_Start_Address, temp->name);
+#else
+ OTA_DEBUG("Get Image from 0x%08x to 0x%08x\n", temp->Img_Start_Address, temp->Img_Start_Address + temp->Img_Len);
+#endif
+ temp = temp->next;
+ }
+}
+
+static int build_image_list(struct image_process_context * context)
+{
+ struct imginfo_table * table = context->image_info_table;
+
+ while (table) {
+ struct image_state * temp = malloc(sizeof(struct image_state));
+ struct image_state * backup = context->image_state_list;
+ if (!temp) {
+ OTA_ERR("Cannot malloc memory..\n");
+ return -1;
+ }
+ temp->result = 0; // Mask this image is not download
+ temp->next_image = backup;
+ temp->image_info = table;
+ context->image_state_list = temp;
+ table = table->next;
+ }
+ return 0;
+}
+
+static int free_image_list(struct image_process_context * context)
+{
+ struct image_state * temp = context->image_state_list;
+ while (temp) {
+ struct image_state * backup = temp->next_image;
+#if defined(CONFIG_AB_SYSTEM) && !defined(CONFIG_AB_SYSTEM_DFOTA)
+ close(temp->image_info->fd);
+ temp->image_info->fd = -1;
+#endif
+ free(temp);
+ temp = backup;
+ }
+ return 0;
+}
+
+static unsigned int fbf_checksum(unsigned char * src, unsigned int len, unsigned int checksum)
+{
+ unsigned int * start = (unsigned int *)src;
+ unsigned int * end = (unsigned int *)(src + len);
+ while (start < end) {
+ checksum ^= (*start++);
+ }
+ return checksum;
+}
+
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+static int mark_current_image_processed(struct image_process_context * context)
+{
+ struct image_state * temp = context->image_state_list;
+ while (temp) {
+ if (temp->image_info == context->current_process) {
+ temp->result = 1; // Mark it be processed
+ return 0;
+ }
+ temp = temp->next_image;
+ }
+ OTA_ERR("Why cannot find the processed image?\n");
+ return -1;
+}
+
+static int image_check(struct image_process_context * context, char * data, int len)
+{
+ int size, cnt;
+ // First check the data belong to same image
+ size = (context->processed_cnt + len - context->current_process->Img_Start_Address) >= context->current_process->Img_Len ?
+ context->current_process->Img_Start_Address + context->current_process->Img_Len - context->processed_cnt : len;
+ cnt = size;
+
+ while (cnt) {
+ if ((context->checksum_cache_index + cnt) >= CHECKSUM_CACHE_SIZE) {
+ int space = CHECKSUM_CACHE_SIZE - context->checksum_cache_index;
+ memcpy(context->checksum_cache + context->checksum_cache_index, data, space);
+ context->image_checksum = fbf_checksum(context->checksum_cache, CHECKSUM_CACHE_SIZE, context->image_checksum);
+ data += space;
+ cnt -= space;
+ context->checksum_cache_index = 0;
+ } else {
+ memcpy(context->checksum_cache + context->checksum_cache_index, data, cnt);
+ context->checksum_cache_index += cnt;
+ cnt -= cnt;
+ }
+ }
+
+ if ((context->processed_cnt + len - context->current_process->Img_Start_Address) >= context->current_process->Img_Len) {
+ OTA_DEBUG("Handle image end...\n");
+ if (context->checksum_cache_index != 0) {
+ context->image_checksum = fbf_checksum(context->checksum_cache, context->checksum_cache_index, context->image_checksum);
+ }
+ OTA_DEBUG(" Image[%08x] checksum 0x%08x:0x%08x\n", context->current_process->Img_ID, context->current_process->Img_Checksum, context->image_checksum);
+ if (context->current_process->Img_Checksum == context->image_checksum) {
+ mark_current_image_processed(context);
+ } else if (context->current_process->Img_ID == RSA_IMAGE_ID) {
+ OTA_DEBUG(" RSA image, always mark to pass\n");
+ mark_current_image_processed(context);
+ } if (context->current_process->Img_Checksum == 0) {
+ OTA_DEBUG(" RAW checksum is zero, always mark to pass\n");
+ mark_current_image_processed(context);
+ }
+ context->checksum_cache_index = 0;
+ context->current_process = 0;
+ context->image_checksum = 0;
+ }
+ context->processed_cnt += size;
+ return size;
+}
+#endif
+static void notify_progress(int progress)
+{
+ char buf[128] = {0};
+ snprintf(buf, 128, "progress[%d]", progress);
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "notification", buf);
+ ubus_notify(ctx, &ota_object, "notification", b.head, -1);
+}
+
+static void notify_download_start(void)
+{
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "notification", "start");
+ ubus_notify(ctx, &ota_object, "notification", b.head, -1);
+}
+
+static void notify_download_end(int success)
+{
+ char buf[128] = {0};
+ snprintf(buf, 128, "end[%d]", !!success);
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "notification", buf);
+ ubus_notify(ctx, &ota_object, "notification", b.head, -1);
+}
+
+static int firmware_download_cb(char * data, int len, int num, void *cbdata)
+{
+ struct image_process_context * context = (struct image_process_context *)cbdata;
+ int ret = 0;
+ unsigned int temp = 0;
+ int total=0;
+ if(download_method_ctx.type == OTA_TYPE_UDP){
+ download_method_ctx.received_size +=len;
+ _ota_download_progress = download_method_ctx.received_size;
+ total = download_method_ctx.file_size;
+ }else{
+ _ota_download_progress += len;
+ total = num;
+ }
+ temp = (_ota_download_progress * 100);
+ ota_download_progress = (temp / total);
+ if (ota_download_progress >= 100) {
+ ota_download_progress = 99;
+ }
+ if ((ota_download_progress - context->ota_download_notification_cnt) >= server_cfg.progress_notify) {
+ OTA_DEBUG("OTA download progress %d\n", context->ota_download_notification_cnt);
+ context->ota_download_notification_cnt = ota_download_progress;
+ notify_progress(context->ota_download_notification_cnt);
+ }
+#if defined(CONFIG_AB_SYSTEM) && !defined(CONFIG_AB_SYSTEM_DFOTA)
+ /* len = 4096 for every packet except for the last one */
+ if (total <= FBF_FILE_SECTOR_SIZE) {
+ OTA_ERR("Error file total size %d...\n", total);
+ return -1;
+ }
+
+ /* 1. FBF Head sit one the first sector of the FBF file, check it */
+ if (context->state == HEADER) {
+ ret = tr069_fbf_parse(data, len, context);
+ if (ret < 0) {
+ OTA_ERR("Failed, fbf parse failed...\n");
+ return -1;
+ }
+
+ if (context->image_info_table) {
+ context->state = CONTENT;
+ dump_table(context);
+ // Build image list for trace all image download result
+ build_image_list(context);
+ }
+ context->processed_cnt = len;
+ } else if (context->state == CONTENT) {
+ if (context->processed_cnt < 0x2000) {
+ OTA_DEBUG("skip 2nd 4K...\n");
+ // Add by liubin
+ revision_out_find(data, len, context->processed_cnt);
+ // End by liubin
+
+ context->processed_cnt += len;
+ return 0;
+ }
+
+ if (context->flash_cache_index < server_cfg.block_size) {
+ /* flash_cache_index increase by 4096 */
+ char *pos = context->flash_cache + context->flash_cache_index;
+ memcpy(pos, data, len); // len = 4096 here
+ context->flash_cache_index += len;
+ context->processed_cnt += len;
+ }
+
+ if (server_cfg.fotav_offset_in_fbf &&
+ context->processed_cnt == (server_cfg.fotav_offset_in_fbf + 0x1000))
+ {
+ memcpy(server_cfg.fotav, context->flash_cache, 128);
+ temp = strlen(server_cfg.fotav);
+ if (server_cfg.fotav[temp - 1] == ';')
+ server_cfg.fotav[temp - 1] = 0; /* remove last ; */
+ OTA_DEBUG("%s: got fota version: %s\n", __func__, server_cfg.fotav);
+ if (upgrade_precheck(server_cfg.fotav))
+ exit(-1);
+ }
+
+ //if (context->flash_cache_index == server_cfg.block_size) {
+ /* flush the cache to flash */
+ ImginfoTable *p;
+ p = context->image_info_table;
+ while (p)
+ {
+ int image_len = p->Img_Len;
+// bool flush_cache = false;
+ /* FBF_FILE_SECTOR_SIZE alignment */
+ image_len = ((image_len + FBF_FILE_SECTOR_SIZE - 1) & (~ (FBF_FILE_SECTOR_SIZE - 1)));
+ int total_block = ((image_len + server_cfg.block_size - 1) & (~ (server_cfg.block_size - 1))) / server_cfg.block_size;
+ if (context->processed_cnt > p->Img_Start_Address) {
+ if (context->processed_cnt < (p->Img_Start_Address + image_len)) {
+ if (context->flash_cache_index < server_cfg.block_size) {
+ break;
+ }
+ }
+ if (context->processed_cnt == (p->Img_Start_Address + image_len) ||
+ context->flash_cache_index == server_cfg.block_size) {
+ p->cs = fbf_checksum((unsigned char *)context->flash_cache, context->flash_cache_index, p->cs);
+ int offset = context->processed_cnt - p->Img_Start_Address;
+ struct erase_info_user mtdEraseInfo;
+ offset += p->Flash_Start_Address - p->Block_Start_Address;
+ int block = ((offset + server_cfg.block_size - 1) & (~ (server_cfg.block_size - 1))) / server_cfg.block_size;
+ int start = server_cfg.block_size * (block - 1);
+ OTA_DEBUG("@ context->processed_cnt: 0x%x, p->Img_Start_Address: 0x%x, len: 0x%x, start: 0x%x\n",
+ context->processed_cnt, p->Img_Start_Address, image_len, start);
+ OTA_DEBUG("@ found, dev: %s, name: %s, block: %d(total: %d), cs: 0x%x(expect: 0x%x), index: 0x%x\n",
+ p->dev, p->name, block - 1,total_block,p->cs, p->Img_Checksum, context->flash_cache_index);
+
+ if (p->fd < 0) {
+ OTA_ERR("mtd device open failed...\n");
+ return -1;
+ }
+
+ if (p->erased == 0 && strstr(p->name, "oem_data")) {
+ OTA_DEBUG("Need to Erase all of %s(%s)\n", p->dev, p->name);
+ mtdEraseInfo.length = p->partition_size;
+ mtdEraseInfo.start = 0;
+ #ifndef CONFIG_PARTITION_EMMC
+ ioctl(p->fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(p->fd, MEMERASE, &mtdEraseInfo);
+ #endif
+ p->erased = 1;
+ }
+
+ if (p->Img_ID != IMAGE_ID_OBM && p->Img_ID != IMAGE_ID_TIMH) {
+ ret = lseek(p->fd, start, SEEK_SET);
+ if (ret < 0)
+ {
+ OTA_ERR("seek failed\n");
+ return -1;
+ }
+
+ mtdEraseInfo.length = server_cfg.block_size;
+ mtdEraseInfo.start = start;
+ #ifndef CONFIG_PARTITION_EMMC
+ ioctl(p->fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(p->fd, MEMERASE, &mtdEraseInfo);
+ #endif
+ }
+
+ ret = write(p->fd, context->flash_cache, context->flash_cache_index);
+ if (ret != context->flash_cache_index) {
+ OTA_ERR("error: write incomplete! %d/%d\n", ret, context->flash_cache_index);
+ return -1;
+ }
+
+ memset(context->flash_cache, 0, server_cfg.block_size);
+ context->flash_cache_index = 0;
+ break;
+ }
+ }
+ p = p->next;
+ }
+
+ if (!p) {
+ //OTA_ERR("not found image, ignore, %d...\n", context->processed_cnt);
+ memset(context->flash_cache, 0, server_cfg.block_size);
+ context->flash_cache_index = 0;
+ }
+ //}
+ }
+#else
+ if (context->flash_cb) context->flash_cb(context, data, len);
+ while (len > 0) {
+ switch (context->state) {
+ case HEADER: {
+ OTA_DEBUG("Header cosume %d, len %d\n", context->processed_cnt,len);
+ if ((context->processed_cnt + len) < MINI_SIZE) {
+ OTA_DEBUG("FBF header not complete, continue recv\n");
+ context->processed_cnt += len;
+ return 0;
+ }
+ ret = tr069_fbf_parse(context->flash_cache, len, context);
+ if (ret < 0) {
+ OTA_ERR("Failed, fbf parse failed...\n");
+ context->processed_cnt += len;
+ len -= len;
+ return -1;
+ }
+ len -= ret;
+ data += ret;
+ context->processed_cnt += ret;
+ if (context->image_info_table) {
+ context->state = CONTENT;
+ dump_table(context);
+ // Build image list for trace all image download result
+ build_image_list(context);
+ }
+ break;
+ }
+ case CONTENT:
+ default: {
+ ImginfoTable * temp;
+ if (!context->current_process) {
+ int discard;
+ temp = context->image_info_table;
+ while (temp) {
+ if (temp->Img_Start_Address <= (context->processed_cnt + len) &&
+ temp->Img_Start_Address >= context->processed_cnt) {
+ OTA_DEBUG("Find new image: start_address 0x%08x, image length %d, write to 0x%08x\n",
+ temp->Img_Start_Address, temp->Img_Len, temp->Flash_Start_Address);
+ if(temp->Img_Len!=0){
+ break;
+ }
+ }
+ temp = temp->next;
+ }
+ if (!temp) {
+ OTA_DEBUG("Current data[0x%08x~0x%08x] not contain any content\n",
+ context->processed_cnt, context->processed_cnt + len);
+ context->processed_cnt += len;
+ return 0;
+ }
+ discard = temp->Img_Start_Address - context->processed_cnt;
+ if (discard) OTA_DEBUG("Have discard %d...\n", discard);
+ len -= discard;
+ data += discard;
+ context->processed_cnt += discard;
+ context->current_process = temp;
+ }
+ ret = image_check(context, data, len);
+ len -= ret;
+ data += ret;
+ }
+ }
+ };
+#endif
+ return 0;
+}
+
+#if defined(CONFIG_AB_SYSTEM) && !defined(CONFIG_AB_SYSTEM_DFOTA)
+static char *gTempbuf = NULL;
+static int gTempbufPos = 0;
+static int gTotalBytes = 0;
+/* this wrapper function is to guarantee 4K size each package */
+static int firmware_download_cb_ab(char * data, int len, int num, void *cbdata)
+{
+ int bytes = 0, pos = 0, ret = 0;
+ if (!gTempbuf)
+ gTempbuf = malloc(4096);
+
+ while (len) {
+ bytes = len;
+ if ((gTempbufPos + len) > 4096)
+ bytes = 4096 - gTempbufPos;
+ memcpy(gTempbuf + gTempbufPos, data + pos, bytes);
+ len -= bytes;
+ pos += bytes;
+ gTempbufPos += bytes;
+ gTotalBytes += bytes;
+ if (gTempbufPos == 4096 || gTotalBytes == num) {
+ ret = firmware_download_cb(gTempbuf, gTempbufPos, num, cbdata);
+ gTempbufPos = 0;
+ if (ret) {
+ OTA_ERR("%s: failed, ret = %d\n", __func__, ret);
+ return ret;
+ }
+ }
+ }
+
+ if(gTotalBytes == num) {
+ struct image_process_context * context = (struct image_process_context *)cbdata;
+ context->download_result = 1;
+ free(gTempbuf);
+ gTempbuf = NULL;
+ }
+ return 0;
+}
+#endif
+
+static int push2flash(struct image_process_context * context, char * data, int len)
+{
+ int ret;
+ int block_cnt = 0;
+ struct erase_info_user mtdEraseInfo;
+
+ while (len && context->flash_cache) {
+ if ((context->flash_cache_index + len) >= server_cfg.block_size) {
+ int space = server_cfg.block_size - context->flash_cache_index;
+ memcpy(context->flash_cache + context->flash_cache_index, data, space);
+ data += space;
+ len -= space;
+ context->flash_cache_index = 0;
+ block_cnt = ((context->processed_cnt + space) / server_cfg.block_size);
+ OTA_DEBUG(" write to block %d\n", block_cnt);
+ // Write to flash
+ ret = lseek(context->fd, server_cfg.block_size * block_cnt, SEEK_SET);
+ if (ret < 0) {
+ OTA_ERR("seek failed\n");
+ return -1;
+ }
+ if (context->processed_cnt + space >= server_cfg.fbf_length) {
+ OTA_ERR("!!! FILE TOO LARGE !!!\n");
+ return 0;
+ }
+ mtdEraseInfo.length = server_cfg.block_size;
+ mtdEraseInfo.start = server_cfg.block_size * ((context->processed_cnt + space) / server_cfg.block_size);
+ ioctl(context->fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(context->fd, MEMERASE, &mtdEraseInfo);
+ ret = write(context->fd, context->flash_cache, server_cfg.block_size);
+ if (ret != server_cfg.block_size) {
+ OTA_ERR("error: write incomplete!\n");
+ }
+ //memset(context->flash_cache, 0, server_cfg.block_size);
+ } else {
+ memcpy(context->flash_cache + context->flash_cache_index, data, len);
+ context->flash_cache_index += len;
+ len -= len;
+ }
+ };
+
+ return 0;
+}
+
+static int flush_flash(struct image_process_context * context)
+{
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+ int ret;
+ int block_cnt;
+ if (context->flash_cache_index && context->flash_cache) {
+ block_cnt = ((context->processed_cnt) / server_cfg.block_size);
+ if (((context->processed_cnt) % server_cfg.block_size) != 0) {
+ block_cnt++;;
+ }
+ OTA_DEBUG("flush at block %d\n", block_cnt);
+ ret = lseek(context->fd, server_cfg.block_size * block_cnt, SEEK_SET);
+ if (ret < 0) {
+ OTA_ERR("seek failed!\n");
+ return -1;
+ }
+ write(context->fd, context->flash_cache, server_cfg.block_size);
+ }
+#endif
+ sync();
+ return 0;
+}
+
+static void __download_throgh_sd(const char * url, struct image_process_context * context)
+{
+ int fd = -1;
+ int total = 0, all = 0;
+ char * buf = NULL;
+
+ if (url == NULL || context == NULL) {
+ OTA_ERR("Bad parameters!\n");
+ // Add by mbtk
+ Download_flag = -1;
+ return;
+ }
+ fd = open(url, O_RDONLY);
+ if (fd < 0) {
+ OTA_ERR("open for SD download failed!\n");
+ // Add by mbtk
+ Download_flag = -1;
+ goto done;
+ }
+ total = lseek(fd, 0, SEEK_END);
+ if (total < 0) {
+ OTA_ERR("seek failed!\n");
+ // Add by mbtk
+ Download_flag = -1;
+ goto done;
+ }
+
+ buf = malloc(4096);
+ if (buf == NULL) {
+ OTA_ERR("malloc failed!\n");
+ // Add by mbtk
+ Download_flag = -1;
+ goto done;
+ }
+
+ all = total;
+ lseek(fd, 0, SEEK_SET);
+ while (total) {
+ int remain = total > 4096 ? 4096 : total;
+ int size = 0;
+ //OTA_ERR("SD download size: %d:%d\n", total, remain);
+ memset(buf, 0, 4096);
+ size = read(fd, buf, remain);
+ if (size != remain) {
+ OTA_ERR("read firmware failed!\n");
+ // Add by mbtk
+ Download_flag = -1;
+ goto done;
+ }
+ firmware_download_cb(buf, remain, all, context);
+ total -= remain;
+ }
+ flush_flash(context);
+ context->download_result = 1;
+done:
+ if (fd >= 0) {
+ close(fd);
+ fd = -1;
+ }
+ if (buf) {
+ free(buf);
+ buf = NULL;
+ }
+ return;
+}
+
+
+static void __download_throgh_http(const char * url, struct image_process_context * context)
+{
+#if 0
+ CURL *curl = curl_easy_init();
+ unsigned int response_code;
+ double firmware_size;
+ char * temp = NULL;
+ *temp = 2;
+
+ OTA_ERR("Try access %s through curl\n", url);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_cb);
+
+ curl_easy_perform(curl);
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
+ curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &firmware_size);
+ OTA_ERR("Get response code: %d and firmware size: %d\n", response_code, firmware_size);
+
+ curl_easy_cleanup(curl);
+#else
+ struct http_client * client = NULL;
+ int http_response_code = 0;
+ client = http_client_init();
+ if (client == NULL) {
+ OTA_ERR("HTTP client init failed!\n");
+ return;
+ }
+
+ OTA_DEBUG("Try access %s through http\n", url);
+ http_client_setopt(client, HTTPCLIENT_OPT_URL, url);
+#if defined(CONFIG_AB_SYSTEM) && !defined(CONFIG_AB_SYSTEM_DFOTA)
+ http_client_setopt(client, HTTPCLIENT_OPT_RESPONSECB, firmware_download_cb_ab);
+#else
+ http_client_setopt(client, HTTPCLIENT_OPT_RESPONSECB, firmware_download_cb);
+#endif
+ http_client_setopt(client, HTTPCLIENT_OPT_METHOD, HTTPCLIENT_REQUEST_GET);
+ http_client_setopt(client, HTTPCLIENT_OPT_RESPONSECB_DATA, context);
+ http_client_perform(client);
+ flush_flash(context);
+ http_client_getinfo(client, HTTPCLIENT_GETINFO_RESPONSE_CODE, &http_response_code);
+ OTA_DEBUG("HTTP result: %d\n", http_response_code);
+ if (http_response_code == 200) {
+ context->download_result = 1;
+ }
+ if (client) http_client_shutdown(client);
+#endif
+}
+
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+static int push2ram(struct image_process_context * context, char * data, int len)
+{
+ while (len && context->flash_cache) {
+ if ((context->flash_cache_index + len) >= FILE_VERIFY_RAM_SIZE) {
+ int space = FILE_VERIFY_RAM_SIZE - context->flash_cache_index;
+ memcpy(context->flash_cache + context->flash_cache_index, data, space);
+ data += space;
+ len -= space;
+ context->flash_cache_index = 0;
+ } else {
+ memcpy(context->flash_cache + context->flash_cache_index, data, len);
+ context->flash_cache_index += len;
+ len -= len;
+ }
+ };
+ return 0;
+}
+
+static int verify_flash_image(struct image_process_context * context, int * file_size)
+{
+ // Handle all data, try read it from flash, and verify again
+ int error = 0;
+ unsigned int i;
+ int total = context->processed_cnt;
+ struct image_process_context new_context = {0};
+ char * temp = malloc(server_cfg.block_size);
+ struct image_state * temp_list;
+ int fd = -1;
+ struct mtd_info_user mtdInfo;
+ unsigned int ofs;
+
+ new_context.ota_download_notification_cnt = context->ota_download_notification_cnt;
+ fd = open(server_cfg.mtd_fbf, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ OTA_ERR("Open MTD device failed!\n");
+ return -1;
+ }
+ if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ OTA_ERR("Could not get MTD device info from %s\n", server_cfg.mtd_fbf);
+ } else {
+ struct erase_info_user mtdEraseInfo;
+ OTA_DEBUG(" MTD size: %d\n", mtdInfo.size);
+ OTA_DEBUG(" MTD erase size: %d\n", mtdInfo.erasesize);
+ OTA_DEBUG(" MTD type: %d\n", mtdInfo.type);
+ mtdEraseInfo.length = mtdInfo.erasesize;;
+ if (mtdInfo.type == MTD_NANDFLASH) {
+ for (mtdEraseInfo.start = 0; mtdEraseInfo.start < mtdInfo.size; mtdEraseInfo.start += mtdInfo.erasesize) {
+ ofs = mtdEraseInfo.start;
+ if (ioctl(fd, MEMGETBADBLOCK, &ofs)) {
+ OTA_ERR("Has bad block at %08x\n", (unsigned int)ofs);
+ }
+ }
+ }
+ }
+ sync();
+ lseek(fd, server_cfg.block_size, SEEK_SET);
+
+ if (!temp) {
+ OTA_ERR("Cannot malloc memory for image verify");
+ return -1;
+ }
+
+ new_context.checksum_cache = malloc(CHECKSUM_CACHE_SIZE);
+ if (!new_context.checksum_cache) goto done;
+ new_context.flash_cache = malloc(FILE_VERIFY_RAM_SIZE);
+ if (!new_context.flash_cache) goto done;
+ new_context.flash_cb = push2ram;
+ i = 1;
+ *file_size = context->processed_cnt;
+ while (total) {
+ int remain_size = total > server_cfg.block_size ? server_cfg.block_size : total;
+ int sub_total = remain_size;
+ int ret = 0;
+ OTA_DEBUG("Verify block %d\n", i);
+ ret = read(fd, temp, server_cfg.block_size);
+ if (ret != server_cfg.block_size) {
+ OTA_ERR("error: data incomplete!\n");
+ }
+ while (remain_size) {
+ int space = remain_size > 4096 ? 4096 : remain_size;
+ firmware_download_cb(temp + (sub_total - remain_size), space, context->processed_cnt, &new_context);
+ remain_size -= space;
+ }
+ total -= sub_total;
+ i++;
+ }
+ free(temp);
+ temp = NULL;
+ temp_list = new_context.image_state_list;
+ while (temp_list) {
+ OTA_DEBUG("The verify image(0x%08x) process result %d\n",
+ temp_list->image_info->Img_Checksum, temp_list->result);
+ if (!temp_list->result) error = 1;
+ temp_list = temp_list->next_image;
+ }
+done:
+ if (temp) free(temp);
+ temp = NULL;
+ if (new_context.flash_cache) free(new_context.flash_cache);
+ new_context.flash_cache = NULL;
+ if (new_context.checksum_cache) free(new_context.checksum_cache);
+ new_context.checksum_cache = NULL;
+ temp = NULL;
+ free_image_list(&new_context);
+ close(fd);
+ return error;
+}
+#endif
+
+
+#ifdef CONFIG_AB_SYSTEM
+
+#ifdef CONFIG_PARTITION_EMMC
+static int emmc_boot_lock_unlock(int no, int lock)
+{
+ char cmd[64] = {0};
+ sprintf(cmd, "echo %d > /sys/block/mmcblk1boot%d/force_ro", lock, no);
+ system(cmd);
+ return 0;
+}
+#endif
+
+static int mtd_erase(int fd, unsigned int offset, unsigned int length)
+{
+#ifndef CONFIG_PARTITION_EMMC
+ struct erase_info_user erase;
+ OTA_DEBUG("%s: offset: 0x%x, length: 0x%x\n", __func__, offset, length);
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ OTA_ERR("%s: seek failed. err: %d\n", __func__, errno);
+ return -1;
+ }
+
+ erase.length = length;
+ erase.start = offset;
+
+ ioctl(fd, MEMUNLOCK, &erase);
+ if (ioctl(fd, MEMERASE, &erase) < 0) {
+ OTA_ERR("%s: erase failed. err: %d\n", __func__, errno);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+#ifndef CONFIG_PARTITION_EMMC
+static int is_all_ff(char *buf, int size)
+{
+ for (int i = 0; i < size; i++) {
+ if (0xff != (unsigned char)buf[i])
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+static int __upgrade_timh(int fd, unsigned int offset, const char *file,
+ unsigned int size, char *dst_buf, unsigned int dst_buf_size, unsigned int pagesize)
+{
+ int srcfd = -1, r = -1;
+ char *buf = NULL, *dst = NULL;
+ int dstsize, off;
+
+ OTA_DEBUG("%s: offset: 0x%x, file: %s, size: 0x%x, dst_buf_size: %d, "
+ "pagesize: %d, max_timh_size: %d\n",
+ __func__, offset, file, size, dst_buf_size, pagesize, server_cfg.max_timh_size);
+ if ((srcfd = open(file, O_RDONLY)) < 0) {
+ OTA_ERR("%s: failed to open file: %s\n", __func__, file);
+ goto err;
+ }
+
+ buf = malloc(size);
+ if (!buf) {
+ OTA_ERR("%s: no mem\n", __func__);
+ goto err;
+ }
+
+ if (complete_read(srcfd, buf, size) < 0) {
+ OTA_ERR("%s: read failed\n", __func__);
+ goto err;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ OTA_ERR("%s: seek failed. err: %d\n", __func__, errno);
+ goto err;
+ }
+
+ if (dst_buf) {
+ dst = dst_buf;
+ dstsize = dst_buf_size;
+ memcpy(dst, buf, size);
+ } else {
+ dst = buf;
+ dstsize = size;
+ }
+
+#ifndef CONFIG_PARTITION_EMMC
+ if (dstsize > server_cfg.max_timh_size) {
+ /* 1. write all timh */
+ if (complete_write(fd, dst, server_cfg.max_timh_size) < 0) {
+ OTA_ERR("%s: write all timh failed\n", __func__);
+ goto err;
+ }
+
+ /* 2. write bbt */
+ for (off = server_cfg.max_timh_size; off < dstsize; off += pagesize) {
+ if (!is_all_ff(dst + off, pagesize)) {
+ if (complete_write(fd, dst + off, pagesize) < 0) {
+ OTA_ERR("%s: write bbt page failed\n", __func__);
+ goto err;
+ }
+ } else {
+ OTA_DEBUG("0x%x + 0x%x is all FF, skip write.\n", offset, off);
+ }
+ }
+ } else {
+#endif
+ if (complete_write(fd, dst, dstsize) < 0) {
+ OTA_ERR("%s: write failed\n", __func__);
+ goto err;
+ }
+#ifndef CONFIG_PARTITION_EMMC
+ }
+#endif
+
+ r = 0;
+err:
+ if (srcfd >= 0)
+ close(srcfd);
+ if (buf)
+ free(buf);
+ return r;
+}
+
+static int write_to_file(void *buf, int size, const char *file)
+{
+ int fd;
+ int r = -1;
+ fd = open(file, O_CREAT | O_RDWR | O_SYNC | O_TRUNC, 777);
+ if (fd < 0) {
+ OTA_ERR("%s: failed to open %s\n", __func__, file);
+ return r;
+ }
+
+ if (complete_write(fd, buf, size) < 0) {
+ OTA_ERR("%s: write failed\n", __func__);
+ goto err;
+ }
+
+ r = 0;
+err:
+ if (fd >= 0)
+ close(fd);
+ return r;
+}
+
+static int retrive_timh_by_ddrid(const char *file, unsigned int *ddr_id, const char *target_file)
+{
+ int size, fd = -1, r = -1;
+ char *buf = NULL;
+ TIM tim;
+
+ OTA_DEBUG("%s: ddr id: 0x%x\n", __func__, *ddr_id);
+ size = get_file_size(file);
+ if (size <= 0) {
+ OTA_ERR("failed to get size of file: %s\n", file);
+ return r;
+ }
+
+ buf = malloc(size);
+ if (!buf) {
+ OTA_ERR("%s: failed to malloc for file: %s, size: %d\n",
+ __func__, file, size);
+ return r;
+ }
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ OTA_ERR("%s: failed to open file: %s\n",
+ __func__, file);
+ r = -1;
+ goto err;
+ }
+
+ if (complete_read(fd, buf, size) < 0)
+ goto err;
+
+ SetTIMPointers(buf, &tim);
+ if (__retrive_timh_by_ddrid(&tim, ddr_id, &size) != NoError) {
+ OTA_ERR("%s: failed to retrive timh\n", __func__);
+ goto err;
+ }
+
+ if (write_to_file(tim.pConsTIM, size, target_file) < 0)
+ goto err;
+ OTA_DEBUG("%s: OK.\n", __func__);
+ r = 0;
+err:
+ if (buf)
+ free(buf);
+ if (fd >= 0)
+ close(fd);
+ return r;
+}
+
+static int __upgrade_obm(int fd, unsigned int offset, const char *obm_file, const char *timh_file)
+{
+ int obm_fd = -1, timh_fd = -1, r = -1;
+ char *buf = NULL;
+ int obm_size = 0, timh_size = 0;
+
+ if (obm_file)
+ obm_size = get_file_size(obm_file);
+ if (timh_file)
+ timh_size = get_file_size(timh_file);
+
+ OTA_DEBUG("%s: offset: 0x%x, obm file: %s, obm_size: %d(%d), timh file: %s, timh_size: %d\n",
+ __func__, offset, obm_file, obm_size, obm_real_size, timh_file, timh_size);
+ obm_size = obm_real_size;
+
+ if ((obm_fd = open(obm_file, O_RDONLY)) < 0) {
+ OTA_ERR("%s: failed to open obm file: %s\n", __func__, obm_file);
+ goto err;
+ }
+
+ if (timh_file) {
+ if ((timh_fd = open(timh_file, O_RDONLY)) < 0) {
+ OTA_ERR("%s: failed to open timh file: %s\n", __func__, timh_file);
+ goto err;
+ }
+ }
+
+ buf = malloc(obm_size + timh_size);
+ if (!buf) {
+ OTA_ERR("%s: no mem\n", __func__);
+ goto err;
+ }
+
+ if (complete_read(obm_fd, buf, obm_size) < 0) {
+ OTA_ERR("%s: read obm failed\n", __func__);
+ goto err;
+ }
+
+ if (timh_file) {
+ if (complete_read(timh_fd, buf + obm_size, timh_size) < 0) {
+ OTA_ERR("%s: read timh failed\n", __func__);
+ goto err;
+ }
+ }
+
+ /* write obm + timh backup */
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ OTA_ERR("%s: seek failed. err: %d\n", __func__, errno);
+ goto err;
+ }
+
+ if (complete_write(fd, buf, obm_size + timh_size) < 0) {
+ OTA_ERR("%s: write failed\n", __func__);
+ goto err;
+ }
+
+ r = 0;
+err:
+ if (obm_fd >= 0) close(obm_fd);
+ if (timh_fd >= 0) close(timh_fd);
+ if (buf) free(buf);
+ return r;
+}
+
+static int __upgrade_bootloader(struct image_process_context * context, int Image_In_Tim)
+{
+ ImginfoTable *obm = NULL, *timh = NULL, *p;
+ int fd = -1, r = -1;
+ char *bootdev = NULL;
+ char *block0 = NULL;
+ char *obm_file = NULL, *timh_file = NULL;
+ /* put this file right after the obm */
+ char *timh_bk_file = NULL;
+
+#ifdef CONFIG_PARTITION_EMMC
+ int emmc_boot_part = 0;
+ if (Image_In_Tim == TIMH_INC) {
+ bootdev = "/dev/mmcblk1boot0";
+ emmc_boot_part = 0;
+ } else if (Image_In_Tim == TIMH_RECOVERY_INC) {
+ bootdev = "/dev/mmcblk1boot1";
+ emmc_boot_part = 1;
+ }
+#else
+ bootdev = "/dev/mtd0";
+#endif
+
+ if (Image_In_Tim == TIMH_INC) {
+ obm_file = (char *)tmp_obm_main_file;
+ timh_file = (char *)tmp_timh_main_target_file;
+ if (context->dual_tim)
+ timh_bk_file = (char *)tmp_timh_bk_target_file;
+ } else if (Image_In_Tim == TIMH_RECOVERY_INC) {
+ obm_file = (char *)tmp_obm_bk_file;
+ timh_file = (char *)tmp_timh_bk_target_file;
+ timh_bk_file = (char *)tmp_timh_main_target_file;
+ } else {
+ OTA_ERR("%s: unsupport %d\n", __func__, Image_In_Tim);
+ exit(-1);
+ }
+
+ if (context->same_tim) {
+ timh_file = (char *)tmp_timh_main_target_file; /* always use the main tim */
+ timh_bk_file = NULL; /* no need to append tim to obm */
+ }
+
+ p = context->image_info_table;
+ while (p) {
+ if (p->Img_ID == IMAGE_ID_OBM && p->Image_In_TIM == Image_In_Tim)
+ obm = p;
+ else if (p->Img_ID == IMAGE_ID_TIMH && p->Image_In_TIM == Image_In_Tim)
+ timh = p;
+ p = p->next;
+ }
+
+ if (!obm || !timh) {
+ OTA_ERR("no obm or timh.\n");
+ goto err;
+ }
+
+ OTA_DEBUG("%s: start %d...\n", __func__, Image_In_Tim);
+ fd = open(bootdev, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ OTA_ERR("failed to open %s.\n", bootdev);
+ goto err;
+ }
+
+#ifdef CONFIG_PARTITION_EMMC
+ // no bbm for emmc
+#else
+ ioctl(fd, MEMUNLOCKPRIV, NULL);
+
+ // bbm related things were in block 0, so we need to backup them
+ // 1. load block 0
+ block0 = malloc(server_cfg.block_size);
+ if (!block0) {
+ OTA_ERR("%s: no mem\n", __func__);
+ goto err;
+ }
+
+ if (lseek(fd, timh->Flash_Start_Address, SEEK_SET) < 0) {
+ OTA_ERR("%s: seek failed. err: %d\n", __func__, errno);
+ goto err;
+ }
+
+ if (complete_read(fd, block0, server_cfg.block_size) < 0) {
+ OTA_ERR("%s: load block0 failed\n", __func__);
+ goto err;
+ }
+#endif
+
+ // 2. erase timh
+ if (mtd_erase(fd, timh->Flash_Start_Address, server_cfg.block_size) < 0) {
+ OTA_ERR("erase timh failed\n");
+ goto err;
+ }
+
+ // 3. erase obm
+ if (mtd_erase(fd, obm->Flash_Start_Address, server_cfg.block_size) < 0) {
+ OTA_ERR("erase obm failed\n");
+ goto err;
+ }
+
+#ifdef CONFIG_PARTITION_EMMC
+ /* unlock */
+ emmc_boot_lock_unlock(emmc_boot_part, 0);
+#endif
+
+ // 4. write obm
+ if (__upgrade_obm(fd, obm->Flash_Start_Address, obm_file, timh_bk_file) < 0) {
+ OTA_ERR("update obm failed\n");
+ goto err;
+ }
+
+ // 5. write timh
+ if (__upgrade_timh(fd, timh->Flash_Start_Address, timh_file,
+ get_file_size(timh_file), block0, server_cfg.block_size, server_cfg.pagesize) < 0) {
+ OTA_ERR("update timh failed\n");
+ goto err;
+ }
+
+#ifdef CONFIG_PARTITION_EMMC
+ /* unlock */
+ emmc_boot_lock_unlock(emmc_boot_part, 1);
+#endif
+ OTA_DEBUG("%s: successfully...\n", __func__);
+
+ r = 0;
+err:
+ if (fd >= 0) {
+#ifndef CONFIG_PARTITION_EMMC
+ ioctl(fd, MEMLOCKPRIV, NULL);
+#endif
+ close(fd);
+ }
+
+ if (block0) free(block0);
+ return r;
+}
+
+static int get_soc_id(unsigned int *ddrid, unsigned int *cpuid)
+{
+#define CPUID_STR "chip_id: "
+#define DDRID_STR "ddr_id: "
+ const char *file = "/dev/soc_id";
+ int fd = -1, ret = -1;
+ char buf[64], *p;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ OTA_ERR("%s: open %s failed.\n", __func__, file);
+ goto err;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (read(fd, buf, 64) < 0) {
+ OTA_ERR("%s: read failed.\n", __func__);
+ goto err;
+ }
+
+ OTA_DEBUG("%s: soc: %s\n", __func__, buf);
+ p = strstr(buf, CPUID_STR);
+ if (!p) {
+ OTA_ERR("%s: not found chip id.\n", __func__);
+ goto err;
+ }
+ *cpuid = strtoul(p + strlen(CPUID_STR), NULL, 16);
+
+ p = strstr(buf, DDRID_STR);
+ if (!p) {
+ OTA_ERR("%s: not found ddr id.\n", __func__);
+ goto err;
+ }
+ *ddrid = strtoul(p + strlen(DDRID_STR), NULL, 16);
+
+ OTA_DEBUG("%s: got cpudid: 0x%x, ddrid: 0x%x\n", __func__, *cpuid, *ddrid);
+err:
+ if (fd >= 0) close(fd);
+ return ret;
+}
+
+/*
+ block0 = main timh + bbt
+ block1 = backup timh + bbt
+ block2 = main obm + backup timh
+ block3 = backup obm + main timh
+*/
+static int upgrade_bootloader(struct image_process_context * context)
+{
+ int r = -1;
+ int cpuid, revision;
+ if (context->upgrade_bootloader != 1)
+ /* no bootloader */
+ return 0;
+
+ get_soc_id(&server_cfg.ddrid, &server_cfg.cpuid);
+ cpuid = server_cfg.cpuid & 0xffff;
+ revision = (server_cfg.cpuid >> 16) & 0xff;
+ context->same_tim = 0;
+
+#ifndef CONFIG_PARTITION_EMMC
+ switch (cpuid) {
+ case 0x1802:
+ case 0x1826:
+ server_cfg.max_timh_size = 4 * 1024;
+ break;
+ case 0x1803:
+ case 0x1828:
+ server_cfg.max_timh_size = 8 * 1024;
+ break;
+ case 0x1903:
+ if (context->dual_tim && (revision == 0xA0 || revision == 0xB0))
+ context->same_tim = 1;
+ case 0x1901:
+ case 0x1906:
+ case 0x1806:
+ server_cfg.max_timh_size = 16 * 1024;
+ break;
+ default:
+ OTA_DEBUG("%s: default cpuid: 0x%x\n", __func__, server_cfg.cpuid);
+ server_cfg.max_timh_size = 16 * 1024;
+ break;
+ }
+#endif
+
+ OTA_DEBUG("%s: dual tim: %d, same tim: %d\n", __func__, context->dual_tim, context->same_tim);
+ if (access(tmp_obm_main_file, F_OK) || access(tmp_timh_main_file, F_OK)) {
+ OTA_ERR("%s: missing main.\n", __func__);
+ goto err;
+ }
+
+ if (context->dual_tim) {
+ if (access(tmp_obm_bk_file, F_OK) || access(tmp_timh_bk_file, F_OK)) {
+ OTA_ERR("%s: missing backup.\n", __func__);
+ goto err;
+ }
+ }
+
+ if (gAsrFlag.DDR_ID == 0 || gAsrFlag.DDR_ID == 0xFFFFFFFF) {
+ gAsrFlag.DDR_ID = server_cfg.ddrid;
+ OTA_DEBUG("%s: invalid ddrid in asrflag, use current ddrid.\n", __func__);
+ }
+
+ if (gAsrFlag.DDR_ID != server_cfg.ddrid)
+ OTA_DEBUG("%s: Warning: mismatch ddrid, in asrflag: 0x%x, current ddrid: 0x%x\n",
+ __func__, gAsrFlag.DDR_ID, server_cfg.ddrid);
+
+ if (retrive_timh_by_ddrid(tmp_timh_main_file, &gAsrFlag.DDR_ID, tmp_timh_main_target_file) < 0) {
+ OTA_ERR("failed to retrive timh for ddr: 0x%x to %s.\n", gAsrFlag.DDR_ID, tmp_timh_main_target_file);
+ goto err;
+ }
+
+ if (context->dual_tim) {
+ if (retrive_timh_by_ddrid(tmp_timh_bk_file, &gAsrFlag.DDR_ID, tmp_timh_bk_target_file) < 0) {
+ OTA_ERR("failed to retrive timh for ddr: 0x%x to %s.\n", gAsrFlag.DDR_ID, tmp_timh_bk_target_file);
+ goto err;
+ }
+ }
+
+ if (context->dual_tim) {
+ /* upgrade the backup bootloader */
+ if (__upgrade_bootloader(context, TIMH_RECOVERY_INC) < 0)
+ goto err;
+ }
+
+ /* then upgrade the main bootloader */
+ if (__upgrade_bootloader(context, TIMH_INC) < 0)
+ goto err;
+
+ r = 0;
+err:
+ remove(tmp_obm_main_file);
+ remove(tmp_timh_main_file);
+ remove(tmp_timh_main_target_file);
+ if (context->dual_tim) {
+ remove(tmp_obm_bk_file);
+ remove(tmp_timh_bk_file);
+ remove(tmp_timh_bk_target_file);
+ }
+ return r;
+}
+#endif
+
+static int image_recheck(struct image_process_context * context)
+{
+#if defined(CONFIG_AB_SYSTEM) && !defined(CONFIG_AB_SYSTEM_DFOTA)
+ ImginfoTable *p = context->image_info_table;
+ char *cache = malloc(FBF_FILE_SECTOR_SIZE);
+ int flag = 0;
+ if (!cache) {
+ OTA_ERR("no memory\n");
+ return -1;
+ }
+
+ ImginfoTable *tmp = p;
+ while (tmp) {
+ lseek(tmp->fd, 0, SEEK_SET);
+ tmp = tmp->next;
+ }
+
+ while (p) {
+ p->cs = 0;
+ OTA_DEBUG("recheck %s, %s, %d\n", p->dev, p->name, p->Flash_Start_Address - p->Block_Start_Address);
+ if (p->Img_ID == IMAGE_ID_OBM || p->Img_ID == IMAGE_ID_TIMH)
+ lseek(p->fd, 0, SEEK_SET);
+ else
+ lseek(p->fd, p->Flash_Start_Address - p->Block_Start_Address, SEEK_SET);
+/*
+ int ret = lseek(p->fd, 0, SEEK_SET);
+ if (ret < 0)
+ {
+ OTA_ERR("seek failed, %s\n", p->name);
+ flag = -1;
+ goto next;
+ }
+*/
+ int remain = p->Img_Len;
+ while (remain > 0) {
+ int size = remain > FBF_FILE_SECTOR_SIZE ? FBF_FILE_SECTOR_SIZE : remain;
+ memset(cache, 0, FBF_FILE_SECTOR_SIZE);
+ int n = read(p->fd, cache, size);
+ if (n != size) {
+ OTA_ERR("read failed, read %d(expect %d), %s\n", n, size, p->name);
+ flag = -1;
+ goto next;
+ }
+ p->cs = fbf_checksum((unsigned char *)cache, FBF_FILE_SECTOR_SIZE, p->cs);
+ remain -= n;
+ }
+
+ if (p->cs != p->Img_Checksum) {
+ OTA_ERR("%s, cs: 0x%x(expect 0x%x)\n", p->name, p->cs, p->Img_Checksum);
+ flag = -1;
+ goto next;
+ } else {
+ OTA_DEBUG("recheck %s, %s OK, cs: 0x%x(expect 0x%x)...\n", p->dev, p->name, p->cs, p->Img_Checksum);
+ }
+next:
+ p = p->next;
+ }
+
+ if (flag == 0) {
+ if (upgrade_bootloader(context) < 0) {
+ flag = -1;
+ OTA_ERR("%s: upgrade bootloader failed, don't reboot or powerdown...\n",
+ __func__);
+ return flag;
+ }
+
+ /* all image write ok, update the active system slot */
+ //#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+ int slot = gInActiveSystem == SYSTEM_A ? 'a' : 'b';
+ /* tell boot to update NVM files from oemd */
+ if (update_oemd)
+ system("touch /NVM/oemd && sync");
+ gAsrFlag.temp_active_slot = slot;
+ gAsrFlag.reboot_cnt = 0;
+ gAsrFlag.synced = 0;
+
+ if (gInActiveSystem == SYSTEM_A) {
+ OTA_DEBUG("prev mversion a: %s updated to %s\n", gAsrFlag.mversion, server_cfg.fotav);
+ memset(gAsrFlag.mversion, 0, 128);
+ strncpy(gAsrFlag.mversion, server_cfg.fotav, 128);
+ } else {
+ OTA_DEBUG("prev mversion b: %s updated to %s\n", gAsrFlag.mversion, server_cfg.fotav);
+ memset(gAsrFlag.MVersion_B, 0, 128);
+ strncpy(gAsrFlag.MVersion_B, server_cfg.fotav, 128);
+ }
+
+ write_asr_flag(&gAsrFlag);
+ }
+ return flag;
+#else
+ struct image_state * image_state_list, * image_state_list_org;
+ int file_size = 0;
+ image_state_list_org = image_state_list = context->image_state_list;
+ if ((context->image_state_list == NULL) || (context->download_result != 1)) {
+ return -1;
+ }
+
+ while (image_state_list) {
+ OTA_DEBUG("The image(0x%08x) process result %d\n",
+ image_state_list->image_info->Img_Checksum, image_state_list->result);
+ if (!image_state_list->result) return -1;;
+ image_state_list = image_state_list->next_image;
+ }
+
+ if (!image_state_list && image_state_list_org) {
+ if (verify_flash_image(context, &file_size)) {
+ return -1;
+ }
+ }
+ /* set dlflag for non-AB */
+ /* tell boot to update NVM files from oemd */
+ if (update_oemd)
+ system("touch /NVM/oemd && sync");
+
+ if(get_asr_flag(&gAsrFlag)) {
+ OTA_ERR("Fail to get asr flag\n");
+ return -1;
+ }
+ gAsrFlag.upgrade_flag = 1;
+ gAsrFlag.fbf_flash_address = server_cfg.fbf_addr + server_cfg.block_size;
+ gAsrFlag.fbf_file_size = context->processed_cnt;
+ gAsrFlag.upgrade_method = context->upgrade_method;
+ gAsrFlag.dfota_n_of_images = 0xFFFFFFFF;
+
+ if(write_asr_flag(&gAsrFlag)) {
+ OTA_ERR("Fail to write asr flag\n");
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static int build_udp_server(const char * path)
+{
+ int fd = -1;
+ struct timeval timeout = {10, 0};
+ struct sockaddr_un un = {0};
+ int size;
+
+ unlink(path);
+ un.sun_family = AF_UNIX;
+ sprintf(un.sun_path, "%s", path);
+ OTA_DEBUG("Will create socket at %s\n", un.sun_path);
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ OTA_ERR("Build socket failed!\n");
+ return -1;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout))) {
+ OTA_ERR("Set timeout failed!\n");
+ goto failed;
+ }
+
+ size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
+ if (bind(fd, (struct sockaddr*)&un, size)) {
+ OTA_ERR("Bind failed!\n");
+ goto failed;
+ }
+ //(void)chmod(un.sun_path, 0777);
+ OTA_DEBUG("will listen on %d\n", fd);
+ if (listen(fd, 5) < 0) {
+ OTA_ERR("Listen failed!\n");
+ goto failed;
+ }
+ return fd;
+
+failed:
+ if (fd > 0) {
+ close(fd);
+ }
+ return -1;
+}
+
+static int accept_udp(int fd)
+{
+ struct timeval timeout = {10, 0};
+ int client;
+
+ client = accept(fd, NULL, 0);
+ if (client < 0) {
+ OTA_ERR("Accept failed!\n");
+ } else {
+ setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
+ }
+ return client;
+}
+
+static void __download_throgh_udp(int fd, int size, struct image_process_context * context)
+{
+ int total = size;
+ char * buf = malloc(4096);
+ int res=0;
+
+ if (buf == NULL) {
+ OTA_ERR("memory issue at __download_through_udp!\n");
+ return;
+ }
+
+ // for debug
+ OTA_DEBUG("size: %d.\n", size);
+
+ while (total) {
+ int recved = 0;
+ memset(buf, 0, 4096);
+
+ int n = total > 4096 ? 4096 : total;
+ int ret;
+repeat:
+ ret = recv(fd, buf + recved, n, 0);
+ if (ret <= 0) {
+ OTA_ERR("recv failed! errno: %d, %s\n", errno, strerror(errno));
+ if (errno == EAGAIN) {
+ sleep(1);
+ OTA_DEBUG("try again.\n");
+ goto repeat;
+ }
+ goto done;
+ }
+ recved += ret;
+ n -= ret;
+ if (n != 0) {
+ //OTA_DEBUG("recved: %d, n: %d, ret: %d\n", recved, n, ret);
+ goto repeat;
+ }
+
+ res=firmware_download_cb(buf, recved, size, context);
+ if(res<0){
+ goto done;
+ }
+ total -= recved;
+ };
+ OTA_DEBUG("__download_throgh_udp received_size[%d],file_size[%d]\n", download_method_ctx.received_size,download_method_ctx.file_size);
+ if(download_method_ctx.received_size == download_method_ctx.file_size){
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+ flush_flash(context);
+#endif
+ context->download_result = 1;
+ }
+done:
+ if (buf) {
+ free(buf);
+ buf = NULL;
+ }
+ return;
+}
+
+
+
+
+static int erase_ota_fbf_area(void)
+{
+#if defined(CONFIG_AB_SYSTEM) && !defined(CONFIG_AB_SYSTEM_DFOTA)
+ return 0;
+#else
+ struct erase_info_user mtdEraseInfo;
+ struct mtd_info_user mtdInfo;
+ int fd = open(server_cfg.mtd_fbf, O_RDWR | O_SYNC);
+ if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ OTA_ERR("Could not get MTD FBF device info from %s\n", server_cfg.mtd_fbf);
+ close(fd);
+ update_state = UPDATE_STATE_FAILED;
+ return -1;
+ }
+ mtdEraseInfo.length = mtdInfo.erasesize;
+ for (mtdEraseInfo.start = 0; mtdEraseInfo.start < mtdInfo.size; mtdEraseInfo.start += mtdInfo.erasesize) {
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(fd, MEMERASE, &mtdEraseInfo);
+ }
+ close(fd);
+ fd = -1;
+ sync();
+#endif
+ return 0;
+
+}
+
+static struct image_process_context *udp_context=NULL;
+static int udp_download_cb(struct uloop_timeout *timeout)
+{
+ //int type = download_method_ctx.type;
+ int size = download_method_ctx.size;
+ int segment_size = download_method_ctx.segment_size;
+ char * url = download_method_ctx.url;
+ char * username = download_method_ctx.username;
+ char * psw = download_method_ctx.pwd;
+ int ret = -1;
+ struct image_process_context *context=NULL;
+
+ if(size==0 && udp_context==NULL){
+ OTA_ERR("ubus call donwload paramer abnormal!\n");//rm60362
+ notify_download_end(0);
+ update_state = UPDATE_STATE_FAILED;
+ goto exit;
+ }
+
+ if(size!=0){
+ if(udp_context){
+ if (udp_context->flash_cache) free(udp_context->flash_cache);
+ udp_context->flash_cache = NULL;
+ if (udp_context->checksum_cache) free(udp_context->checksum_cache);
+ udp_context->checksum_cache = NULL;
+ if(udp_context->fd!=-1){
+ close(udp_context->fd);
+ udp_context->fd = -1;
+ }
+
+ if (udp_context->image_state_list) {
+ free_image_list(udp_context);
+ udp_context->image_state_list=NULL;
+ }
+ if(udp_context){
+ free(udp_context);
+ udp_context = NULL;
+ }
+
+ }
+
+ udp_context = (struct image_process_context *)malloc(sizeof(struct image_process_context));
+ memset(udp_context,0,sizeof(struct image_process_context));
+ }
+ context = udp_context;
+
+ if(size!=0){
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+ context->fd = open(server_cfg.mtd_fbf, O_RDWR | O_SYNC);
+ if (context->fd < 0) {
+ OTA_ERR("Cannot open MTD device!\n");
+ notify_download_end(0);
+ update_state = UPDATE_STATE_FAILED;
+ return ret;
+ }
+#endif
+ notify_download_start();
+ _ota_download_progress = ota_download_progress = 0;
+
+ download_method_ctx.file_size = size;
+ download_method_ctx.received_size = 0;
+ // Init firmware download context
+ context->flash_cache = malloc(server_cfg.block_size);
+ if (!context->flash_cache) {
+ OTA_ERR("Cannot malloc memory for download cache\n");
+ goto done;
+ }
+#ifdef CONFIG_AB_SYSTEM
+ memset(context->flash_cache, 0, server_cfg.block_size);
+#endif
+ context->checksum_cache = malloc(CHECKSUM_CACHE_SIZE);
+ if (!context->checksum_cache) {
+ OTA_ERR("Cannot malloc memory for download cache\n");
+ goto done;
+ }
+ context->flash_cb = push2flash;
+ }
+
+ // download from UDP
+ int s = -1, c = -1;
+ OTA_DEBUG("Download through UDP\n");
+ s = build_udp_server(url);
+ if (s >= 0) {
+ c = accept_udp(s);
+ if (c >= 0) {
+
+ if(size!=0){
+ if(erase_ota_fbf_area())
+ goto done;
+ }
+
+ __download_throgh_udp(c, segment_size, context);
+
+ }else{
+ OTA_ERR("accept_udp failed\n");
+ }
+ }else{
+ OTA_ERR("build_udp_server failed\n");
+ return 0;
+ }
+ if (s >= 0) close(s);
+ if (c >= 0) close(c);
+ ret = 0;
+
+done:
+ if(download_method_ctx.file_size == download_method_ctx.received_size){
+ // Clear context
+ if (context->flash_cache) free(context->flash_cache);
+ context->flash_cache = NULL;
+ if (context->checksum_cache) free(context->checksum_cache);
+ context->checksum_cache = NULL;
+ close(context->fd);
+ context->fd = -1;
+ if (image_recheck(context) == 0) {
+ update_state = UPDATE_STATE_UPDATED;
+ OTA_ERR("%s: Image download succssful.\n", __func__);
+ notify_download_end(1);
+ ret = 0;
+ } else {
+ update_state = UPDATE_STATE_FAILED;
+ OTA_ERR("Image download failed\n");
+ notify_download_end(0);
+ ret = -1;
+ }
+ if (context->image_state_list) {
+ free_image_list(context);
+ context->image_state_list=NULL;
+ }
+ if(udp_context){
+ free(udp_context);
+ udp_context = NULL;
+ }
+
+
+ }
+ else{
+ //update_state = UPDATE_STATE_IDLE;
+ //notify_download_end(1);
+ }
+exit:
+
+ if (url) free(url);
+ url = NULL;
+ if (username) free(username);
+ username = NULL;
+ if (psw) free(psw);
+ psw = NULL;
+ return ret;
+}
+
+
+static int download_cb(struct uloop_timeout *timeout)
+{
+ int type = download_method_ctx.type;
+ int size = download_method_ctx.size;
+ char * url = download_method_ctx.url;
+ char * username = download_method_ctx.username;
+ char * psw = download_method_ctx.pwd;
+ struct image_process_context context = {0};
+ int ret = -1;
+
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+ context.fd = open(server_cfg.mtd_fbf, O_RDWR | O_SYNC);
+ if (context.fd < 0) {
+ OTA_ERR("Cannot open MTD device!\n");
+ notify_download_end(0);
+ update_state = UPDATE_STATE_FAILED;
+ return ret;
+ }
+#endif
+ notify_download_start();
+
+ _ota_download_progress = ota_download_progress = 0;
+ // Init firmware download context
+ context.flash_cache = malloc(server_cfg.block_size);
+ if (!context.flash_cache) {
+ OTA_ERR("Cannot malloc memory for download cache\n");
+ goto done;
+ }
+#ifdef CONFIG_AB_SYSTEM
+ memset(context.flash_cache, 0, server_cfg.block_size);
+#endif
+ context.checksum_cache = malloc(CHECKSUM_CACHE_SIZE);
+ if (!context.checksum_cache) {
+ OTA_ERR("Cannot malloc memory for download cache\n");
+ goto done;
+ }
+ context.flash_cb = push2flash;
+
+ if (type == OTA_TYPE_HTTP) {
+ // download from http
+ if(erase_ota_fbf_area())
+ goto done;
+ __download_throgh_http(url, &context);
+ } else if (type == OTA_TYPE_UDP) {
+ // download from UDP
+ int s = -1, c = -1;
+ OTA_DEBUG("Download through UDP\n");
+ s = build_udp_server(url);
+ if (s >= 0) {
+ c = accept_udp(s);
+ if (c >= 0) {
+ if(erase_ota_fbf_area())
+ goto done;
+ __download_throgh_udp(c, size, &context);
+ }
+ }
+ if (s >= 0) close(s);
+ if (c >= 0) close(c);
+ } else if (type == OTA_TYPE_SD) {
+ // download from SD
+ if(erase_ota_fbf_area())
+ goto done;
+ __download_throgh_sd(url, &context);
+ } else {
+ // assert?
+ OTA_ERR("Unknow download type\n");
+ }
+
+done:
+ // Clear context
+ if (context.flash_cache) free(context.flash_cache);
+ context.flash_cache = NULL;
+ if (context.checksum_cache) free(context.checksum_cache);
+ context.checksum_cache = NULL;
+ if (url) free(url);
+ url = NULL;
+ if (username) free(username);
+ username = NULL;
+ if (psw) free(psw);
+ psw = NULL;
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+ close(context.fd);
+ context.fd = -1;
+#endif
+ // Change by mbtk
+ if ((image_recheck(&context) == 0) && !Download_flag) {
+ update_state = UPDATE_STATE_UPDATED;
+ OTA_DEBUG("Image download succssful\n");
+
+ // Add by liubin
+ revision_out_update();
+ // End by liubin
+
+ notify_download_end(1);
+ ret = 0;
+ } else {
+ update_state = UPDATE_STATE_FAILED;
+ OTA_ERR("Image download failed\n");
+ notify_download_end(0);
+ ret = -1;
+ }
+
+ if (context.image_state_list) {
+ free_image_list(&context);
+ }
+ return ret;
+}
+
+static struct uloop_timeout download_timer = { .cb = (void*)download_cb };
+static struct uloop_timeout udp_download_timer = { .cb = (void*)udp_download_cb };
+
+
+static int download_func(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__DOWNLOAD_MAX];
+ int ret = -1;
+ int sync = 0; /* default is no sync */
+ int type=-1;
+ blob_buf_init(&b, 0);
+
+ blobmsg_parse(download_policy, ARRAY_SIZE(download_policy), tb, blob_data(msg), blob_len(msg));
+ if (tb[DOWNLOAD_TYPE]) type = blobmsg_get_u32(tb[DOWNLOAD_TYPE]);
+
+
+ if ((update_state == UPDATE_STATE_IDLE ||update_state == UPDATE_STATE_FAILED) ||
+ (type == OTA_TYPE_UDP && update_state == UPDATE_STATE_UPDATING)) {
+ update_state = UPDATE_STATE_UPDATING;
+
+ OTA_DEBUG("Method call: %s\n", method);
+ //memset(&download_method_ctx, 0, sizeof(download_method_ctx));
+ download_method_ctx.url = download_method_ctx.username = download_method_ctx.pwd =NULL;
+ download_method_ctx.type = download_method_ctx.size = download_method_ctx.segment_size= 0;
+ if (tb[DOWNLOAD_URL]) download_method_ctx.url = strdup(blobmsg_data(tb[DOWNLOAD_URL]));
+ if (tb[DOWNLOAD_NAME]) download_method_ctx.username = strdup(blobmsg_data(tb[DOWNLOAD_NAME]));
+ if (tb[DOWNLOAD_PSW]) download_method_ctx.pwd = strdup(blobmsg_data(tb[DOWNLOAD_PSW]));
+ if (tb[DOWNLOAD_TYPE]) download_method_ctx.type = blobmsg_get_u32(tb[DOWNLOAD_TYPE]);
+ if (tb[DOWNLOAD_FILE_SIZE]) download_method_ctx.size = blobmsg_get_u32(tb[DOWNLOAD_FILE_SIZE]);
+ if (tb[DOWNLOAD_SYNC]) sync = blobmsg_get_u32(tb[DOWNLOAD_SYNC]);
+ if (tb[DOWNLOAD_SEGMENT_SIZE]) download_method_ctx.segment_size = blobmsg_get_u32(tb[DOWNLOAD_SEGMENT_SIZE]);
+
+ if (download_method_ctx.url) OTA_DEBUG(" url: %s\n", download_method_ctx.url);
+ if (download_method_ctx.username) OTA_DEBUG(" username: %s\n", download_method_ctx.username);
+ if (download_method_ctx.pwd) OTA_DEBUG(" password: %s\n", download_method_ctx.pwd);
+ OTA_DEBUG(" type: %d, size: %d ,segment size: %d\n", download_method_ctx.type, download_method_ctx.size,download_method_ctx.segment_size);
+
+ if (sync != 1) {
+ if(download_method_ctx.type == OTA_TYPE_UDP){
+ uloop_timeout_set(&udp_download_timer, 1);
+ }else{
+ uloop_timeout_set(&download_timer, 1);
+ }
+ blobmsg_add_string(&b, "response", "download ready");
+ ret = 0;
+ } else {
+ if(download_method_ctx.type == OTA_TYPE_UDP){
+ ret = udp_download_cb(&udp_download_timer);
+ }else{
+ ret = download_cb(&download_timer);
+ }
+ if (ret == 0) {
+ blobmsg_add_string(&b, "response", "image download succssful");
+ } else {
+ blobmsg_add_string(&b, "response", "image download failed");
+ }
+ }
+ } else {
+ OTA_ERR("Error! update already in processing or be processed\n");
+ blobmsg_add_string(&b, "response", "download failed (update already in processing or be processed)");
+ ret = -1;
+ }
+
+ ubus_send_reply(ctx, req, b.head);
+ return ret;
+}
+
+// Version check
+struct xml_parse_context {
+ const char * file;
+ int i;
+ char tag[OTA_MAX_STRING_LEN];
+ char * value;
+ int value_size;
+ int state;
+};
+enum {
+ XML_STATE_NULL,
+ XML_STATE_TAG,
+ XML_STATE_VALUE,
+};
+static int get_next_tag(struct xml_parse_context * context)
+{
+ int len = 0;
+ int i = context->i;
+ int start = 0;
+ if (context->file[i++] != '<') {
+ return -1;
+ }
+ if (context->file[i] == '/') {
+ return -1;
+ }
+ start = i;
+ while (context->file[i] != '\0') {
+ if (context->file[i] == '>') {
+ memset(context->tag, 0, OTA_MAX_STRING_LEN);
+ if (len > OTA_MAX_STRING_LEN) {
+ OTA_ERR("Memory issue in get_next_tag(%d)!\n", len);
+ return -1;
+ }
+ memcpy(context->tag, &context->file[start], len);
+ context->i += (len + 2);
+ OTA_DEBUG("Tag: %s\n", context->tag);
+ return 0;
+ }
+ len++;
+ i++;
+ }
+ return -1;
+}
+static int get_next_value(struct xml_parse_context * context)
+{
+ int len = 0;
+ int i = context->i;
+ int start = 0;
+ if (context->file[i] == '<') {
+ return -1;
+ }
+ while (context->file[i] == '\r' || context->file[i] == '\t' || context->file[i] == '\n') {
+ i++;
+ }
+ start = i;
+ while (context->file[i] != '\0') {
+ if (context->file[i] == '<') {
+ if (context->file[i + 1] != '/') {
+ OTA_ERR("Bad file!\n");
+ return -1;
+ }
+ if (strncmp(&context->file[i + 2], context->tag, strlen(context->tag))) {
+ OTA_ERR("tag not match!\n");
+ return -1;
+ }
+ memset(context->value, 0, context->value_size);
+ if (len > context->value_size) {
+ OTA_ERR("Memory issue in get_next_vale(%d:%d)!\n", len, context->value_size);
+ return -1;
+ }
+ memcpy(context->value, &context->file[start], len);
+ context->i += (len + 3 + strlen(context->tag));
+ OTA_DEBUG("Value: %s\n", context->value);
+ return 0;
+ }
+ len++;
+ i++;
+ }
+ return -1;
+}
+
+static int version_parse(const char * string, struct version_info * ver)
+{
+ #define OTA_MARVELL_VERSION_TAG "Marvell"
+ #define OTA_MARVELL_VERSION_TAG_VER "Version"
+ #define OTA_MARVELL_VERSION_TAG_URL "URL"
+ #define OTA_MARVELL_VERSION_TAG_NOTE "ReleaseNote"
+ struct xml_parse_context context = {0};
+ #define MAX_XML_VALUE_SIZE 4096
+ int ret = 0;
+
+ if (string == NULL || ver == NULL) {
+ OTA_ERR("Invalid parameters!\n");
+ return -1;
+ }
+
+ context.file = string;
+ context.value = malloc(MAX_XML_VALUE_SIZE);
+ if (context.value == NULL) {
+ OTA_ERR("Malloc for context buffer failed!\n");
+ return -1;
+ }
+ context.value_size = MAX_XML_VALUE_SIZE;
+
+ if (get_next_tag(&context) < 0) {
+ OTA_ERR("Parse first tag failed!\n");
+ ret = -1;
+ goto done;
+ }
+ if (strcmp(context.tag, OTA_MARVELL_VERSION_TAG)) {
+ OTA_ERR("First tag is not %s\n", OTA_MARVELL_VERSION_TAG);
+ ret = -1;
+ goto done;
+ }
+ while (get_next_tag(&context) == 0) {
+ if (get_next_value(&context) == 0) {
+ if (!strcmp(context.tag, OTA_MARVELL_VERSION_TAG_VER)) {
+ OTA_DEBUG("Handle version: %s\n", context.value);
+ snprintf(ver->version, OTA_MAX_STRING_LEN, "%s", context.value);
+ } else if (!strcmp(context.tag, OTA_MARVELL_VERSION_TAG_URL)) {
+ OTA_DEBUG("Handle URL: %s\n", context.value);
+ snprintf(ver->url, OTA_MAX_STRING_LEN, "%s", context.value);
+ } else if (!strcmp(context.tag, OTA_MARVELL_VERSION_TAG_NOTE)) {
+ OTA_DEBUG("Handle release note: %s\n", context.value);
+ if (ver->release_note) {
+ free(ver->release_note);
+ ver->release_note = NULL;
+ }
+ ver->release_note = strdup(context.value);
+ }
+ }
+ }
+done:
+ if (context.value) {
+ free(context.value);
+ }
+ return ret;
+}
+
+static int version_check_cb(char * data, int len, int num, void *cbdata)
+{
+ struct version_check_context * context = (struct version_check_context *)cbdata;
+ if ((context->size - context->used) < len) {
+ char * buf = realloc(context->url, context->size + num);
+ if (buf == NULL) {
+ OTA_ERR("Memory issue at version_check_cb\n");
+ return -1;
+ }
+ context->size += num;
+ context->url = buf;
+ memcpy(context->url + context->used, data, len);
+ context->used += len;
+ } else {
+ memcpy(context->url + context->used, data, len);
+ context->used += len;
+ }
+ return 0;
+}
+struct version_check_context version_check_context = {0};
+static int detect_new_version(struct ota_server * server, char ** firmwar_url)
+{
+ struct http_client * client = NULL;
+ struct http_client_list * header = NULL;
+ int http_response_code = 0;
+ int ret = -1;
+ char buf[OTA_MAX_STRING_LEN + 30] = {0};
+
+ OTA_DEBUG("Try access %s for version check\n", server->server_url);
+
+ client = http_client_init();
+ if (client == NULL) {
+ OTA_ERR("HTTP client init failed!\n");
+ return -1;
+ }
+
+ version_check_context.url = malloc(OTA_MAX_STRING_LEN);
+ if (version_check_context.url == NULL) {
+ OTA_ERR("Malloc failed!\n");
+ goto done;
+ }
+ memset(version_check_context.url, 0, OTA_MAX_STRING_LEN);
+ version_check_context.size = OTA_MAX_STRING_LEN;
+ version_check_context.used = 0;
+
+ http_client_setopt(client, HTTPCLIENT_OPT_URL, server->server_url);
+ http_client_setopt(client, HTTPCLIENT_OPT_RESPONSECB, version_check_cb);
+ http_client_setopt(client, HTTPCLIENT_OPT_METHOD, HTTPCLIENT_REQUEST_POST);
+ http_client_setopt(client, HTTPCLIENT_OPT_RESPONSECB_DATA, &version_check_context);
+ snprintf(buf, sizeof(buf), "MarvellOTA: version=%s\r\n", version_check_context.version);
+ header = http_client_list_append(header, buf);
+ http_client_setopt(client, HTTPCLIENT_OPT_HTTPHEADER, header);
+ http_client_perform(client);
+ http_client_getinfo(client, HTTPCLIENT_GETINFO_RESPONSE_CODE, &http_response_code);
+
+ OTA_DEBUG("Version check result: %d\n", http_response_code);
+ if (http_response_code == 200) {
+ version_parse(version_check_context.url, &server_cfg.ver);
+ OTA_DEBUG("Detected new version at: %s\n", server_cfg.ver.url);
+ *firmwar_url = strdup(server_cfg.ver.url);
+ } else {
+ // Free memory
+ // If http response is HTTP 200 OK, version checking caller should free this memory
+ free(version_check_context.url);
+ version_check_context.url = NULL;
+ version_check_context.size = 0;
+ version_check_context.used = 0;
+ }
+ ret = 0;
+done:
+ if (client) http_client_shutdown(client);
+ return ret;
+}
+
+enum {
+ QUERY_TYPE,
+ __QUERY_MAX
+};
+
+static const struct blobmsg_policy query_policy[] = {
+ [QUERY_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
+};
+
+static int query_func(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__QUERY_MAX];
+ char * type = NULL;
+ const char * string = NULL;
+
+ OTA_DEBUG("enter: %s\n", __func__);
+ blobmsg_parse(query_policy, ARRAY_SIZE(query_policy), tb, blob_data(msg), blob_len(msg));
+
+ if (tb[QUERY_TYPE]) type = blobmsg_data(tb[QUERY_TYPE]);
+ if (type == NULL) {
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "response", "failed");
+ ubus_send_reply(ctx, req, b.head);
+ OTA_ERR("Failed query type\n");
+ return 0;
+ }
+ if (*type == '1') {
+ // Download states
+ switch (update_state) {
+ case UPDATE_STATE_UPDATING:
+ string = "updating";
+ break;
+ case UPDATE_STATE_UPDATED:
+ string = "success";
+ break;
+ case UPDATE_STATE_FAILED:
+ string = "failed";
+ break;
+ case UPDATE_STATE_IDLE:
+ default:
+ string = "not start";
+ break;
+ }
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "response", string);
+ ubus_send_reply(ctx, req, b.head);
+ return 0;
+ } else if (*type == '0' ) {
+ // Query new version
+ int len = strlen(server_cfg.ver.version);
+ if (len != 0) {
+ char * buf = malloc(len + 50);
+ if (buf == NULL) {
+ OTA_ERR("Malloc failed!\n");
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "response", "failed:memory issue");
+ ubus_send_reply(ctx, req, b.head);
+ return 0;
+ }
+ memset(buf, 0, len + 30);
+ sprintf(buf, "has new version:[%s]", server_cfg.ver.version);
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "response", buf);
+ ubus_send_reply(ctx, req, b.head);
+ free(buf);
+ buf = NULL;
+ return 0;
+ } else {
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "response", "no new version");
+ ubus_send_reply(ctx, req, b.head);
+ return 0;
+ }
+ } else {
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "response", "unkonw");
+ ubus_send_reply(ctx, req, b.head);
+ OTA_ERR("unkonw query type %s\n", type);
+ return 0;
+ }
+}
+
+static const struct ubus_method otad_method[] = {
+ UBUS_METHOD("download", download_func, download_policy),
+ UBUS_METHOD("query", query_func, query_policy),
+};
+
+static struct ubus_object_type otad_object_type = UBUS_OBJECT_TYPE("ota", otad_method);
+
+static struct ubus_object ota_object = {
+ .name = "ota",
+ .type = &otad_object_type,
+ .methods = otad_method,
+ .n_methods = ARRAY_SIZE(otad_method),
+};
+
+static void version_check(struct uloop_timeout *timeout);
+static struct uloop_timeout version_check_timer = { .cb = version_check };
+
+
+static void version_check(struct uloop_timeout *timeout)
+{
+ char * firmware = NULL;
+ OTA_DEBUG("Try checking new version\n");
+
+ if (update_state == UPDATE_STATE_UPDATING) {
+ OTA_ERR("Firmware updating... Reset timer.\n");
+ goto reset_timer;
+ } else if (update_state == UPDATE_STATE_UPDATED) {
+ OTA_ERR("Firmware already be updated, not need detect again\n");
+ return;
+ }
+
+ detect_new_version(&server_cfg, &firmware);
+ if (firmware && strlen(firmware) && server_cfg.download_immediately != 0) {
+ OTA_DEBUG("New firmware at: %s\n", firmware);
+ do {
+ unsigned int id;
+ static struct ubus_request req;
+ char firmare_url[OTA_MAX_STRING_LEN + 1] = {0};
+ snprintf(firmare_url, sizeof(firmare_url), "%s/%s", server_cfg.server_url, firmware);
+ if (ubus_lookup_id(ctx, "ota", &id)) {
+ OTA_ERR("Cannot found object...\n");
+ break;
+ }
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "url", firmare_url);
+ blobmsg_add_string(&b, "username", "user name");
+ blobmsg_add_u32(&b, "type", 0);
+ ubus_invoke_async(ctx, id, "download", b.head, &req);
+ ubus_complete_request_async(ctx, &req);
+ } while (0);
+ free(firmware);
+ firmware = NULL;
+ if (update_state == UPDATE_STATE_UPDATED) {
+ //1TODO: Post system reset for new image install
+ OTA_DEBUG("Firmware download success, will post system reboot\n");
+ return;
+ } else {
+ uloop_timeout_set(&version_check_timer, server_cfg.interval * 2);
+ }
+ }
+reset_timer:
+ uloop_timeout_set(&version_check_timer, server_cfg.interval * 1000);
+}
+
+static unsigned int get_mtd_offset(int mtd)
+{
+ char file[64] = {0};
+ char content[32] = {0};
+ int fd;
+ sprintf(file, "/sys/class/mtd/mtd%d/offset", mtd);
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ OTA_ERR("%s: failed to open %s\n", __func__, file);
+ return -1;
+ }
+
+ read(fd, content, 32);
+ close(fd);
+ return atoi(content);
+}
+
+#ifdef CONFIG_AB_SYSTEM
+#ifndef CONFIG_PARTITION_EMMC
+static int get_mtd_pagesize(int mtd, unsigned int *pagesize)
+{
+ struct mtd_info_user mtdinfo;
+ char dev[32];
+ int fd;
+
+ memset(dev, 0, sizeof(dev));
+ sprintf(dev, "/dev/mtd%d", mtd);
+ fd = open(dev, O_RDONLY);
+ if (fd < 0) {
+ OTA_ERR("%s: failed to open %s.\n", __func__, dev);
+ return -1;
+ }
+
+ if (ioctl(fd, MEMGETINFO, &mtdinfo)) {
+ OTA_ERR("%s: Could not get MTD device info from %s\n", __func__, dev);
+ close(fd);
+ return -1;
+ }
+
+ *pagesize = mtdinfo.writesize;
+ OTA_DEBUG("%s: %s, pagesize: %d\n", __func__, dev, *pagesize);
+
+ return 0;
+}
+#endif
+#endif
+
+static int init_cfg(const char * uci_path)
+{
+ FILE * fp = NULL;
+ #define MAX_LINE_SIZE 128
+ char buf[MAX_LINE_SIZE] = {0};
+
+#if 1
+ server_cfg.interval = 5;
+ server_cfg.first_interval = 1;
+ server_cfg.progress_notify = 10;
+#else
+ /*
+ ota.@ota[0]=ota
+ ota.@ota[0].fbf_address='0x2A60000'
+ ota.@ota[0].progress_notify='10'
+ ota.@ota[0].interval='5'
+ ota.@ota[0].first_interval='1'
+ */
+ if (uci_path) { /* If UCI file exist parse it */
+ struct uci_context *uci_ctx = NULL;
+ struct uci_package *p = NULL;
+ struct uci_section *s = NULL;
+ struct uci_element *e1 = NULL, *e2 = NULL;
+ uci_ctx = uci_alloc_context();
+ if (uci_load(uci_ctx, uci_path, &p)) {
+ OTA_ERR("uci load failed\n");
+ uci_free_context(uci_ctx);
+ return -1;
+ }
+
+ uci_foreach_element(&p->sections, e1) {
+ s = uci_to_section(e1);
+ if (strcmp(s->type, "ota")) {
+ continue;
+ }
+
+ uci_foreach_element(&s->options, e2) {
+ if (!strcmp((uci_to_option(e2))->e.name, "server_url")) {
+ OTA_DEBUG("OTA server URL: %s\n", (uci_to_option(e2))->v.string);
+ snprintf(server_cfg.server_url, OTA_MAX_STRING_LEN, "%s", (uci_to_option(e2))->v.string);
+ } else if (!strcmp((uci_to_option(e2))->e.name, "progress_nofity")) {
+ OTA_DEBUG("Download notify interval: %s\n", (uci_to_option(e2))->v.string);
+ sscanf((uci_to_option(e2))->v.string, "%d", &server_cfg.progress_notify);
+ } else if (!strcmp((uci_to_option(e2))->e.name, "interval")) {
+ OTA_DEBUG("Download version detect interval: %s\n", (uci_to_option(e2))->v.string);
+ sscanf((uci_to_option(e2))->v.string, "%d", &server_cfg.interval);
+ } else if (!strcmp((uci_to_option(e2))->e.name, "first_interval")) {
+ OTA_DEBUG("Download first version detect interval: %s\n", (uci_to_option(e2))->v.string);
+ sscanf((uci_to_option(e2))->v.string, "%d", &server_cfg.first_interval);
+ } else if (!strcmp((uci_to_option(e2))->e.name, "download_immediately")) {
+ OTA_DEBUG("Download firmware immediately: %s\n", (uci_to_option(e2))->v.string);
+ sscanf((uci_to_option(e2))->v.string, "%d", &server_cfg.download_immediately);
+ }
+ }
+ }
+
+ uci_free_context(uci_ctx);
+ uci_ctx = NULL;
+ }
+#endif
+
+#ifdef CONFIG_PARTITION_EMMC
+ fp = fopen("/proc/emmc", "r");
+#else
+ fp = fopen("/proc/mtd", "r");
+#endif
+ if (fp == NULL) {
+ OTA_ERR("Open MTD failed!\n");
+ return -1;
+ }
+
+#ifdef CONFIG_AB_SYSTEM
+ server_cfg.mtd_cnt = 0;
+ OTA_DEBUG("Start to retrive the mtd partition info...\n");
+ #ifdef CONFIG_PARTITION_EMMC
+ server_cfg.emmc_block_size = 512; /* emmc */
+ server_cfg.block_size = 0x20000; /* only used for buffer cache size */
+
+ struct image_mtd_info *bootdev;
+ /* the main bootloader */
+ bootdev = &server_cfg.image_mtd_info[0];
+ sprintf(bootdev->dev, "%s", "mmcblk1boot0");
+ sprintf(bootdev->name, "%s", "bootloader0");
+ bootdev->flag = SYSTEM_SINGLE;
+ bootdev->flash_start_offset = 0;
+
+ /* the backup bootloader */
+ bootdev = &server_cfg.image_mtd_info[1];
+ sprintf(bootdev->dev, "%s", "mmcblk1boot1");
+ sprintf(bootdev->name, "%s", "bootloader1");
+ bootdev->flag = SYSTEM_SINGLE;
+ bootdev->flash_start_offset = 0;
+
+ server_cfg.mtd_cnt = 2;
+ #else
+ server_cfg.block_size = 0x20000; /* nand flash */
+ if (get_mtd_pagesize(0, &server_cfg.pagesize) < 0) {
+ fclose(fp);
+ return -1;
+ }
+ #endif
+#endif
+
+ /*
+ root@OpenWrt:~# cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 000a0000 00020000 "bootloader"
+ mtd1: 00020000 00020000 "cp_reliabledata"
+ mtd2: 00020000 00020000 "ap_reliabledata"
+ mtd3: 00020000 00020000 "cp_reliabledata_backup"
+ mtd4: 00020000 00020000 "ap_reliabledata_backup"
+ mtd5: 00020000 00020000 "mep-ota"
+ mtd6: 00020000 00020000 "mep-ota_backup"
+ mtd7: 00100000 00020000 "asr_flag"
+ mtd8: 00040000 00020000 "dtim-a"
+ mtd9: 00040000 00020000 "dtim-b"
+ mtd10: 00de0000 00020000 "cpimage-a"
+ mtd11: 00de0000 00020000 "cpimage-b"
+ mtd12: 000c0000 00020000 "u-boot-a"
+ mtd13: 000c0000 00020000 "u-boot-b"
+ mtd14: 00500000 00020000 "kernel-a"
+ mtd15: 00500000 00020000 "kernel-b"
+ mtd16: 00040000 00020000 "device_info"
+ mtd17: 02800000 00020000 "OTA"
+ mtd18: 00040000 00020000 "cust_info"
+ mtd19: 00020000 00020000 "rootfs-a-sdtim"
+ mtd20: 013e0000 00020000 "rootfs-a-mount"
+ mtd21: 01400000 00020000 "rootfs-a"
+ mtd22: 00020000 00020000 "rootfs-b-sdtim"
+ mtd23: 013e0000 00020000 "rootfs-b-mount"
+ mtd24: 01400000 00020000 "rootfs-b"
+ mtd25: 00020000 00020000 "oem_data-a-sdtim"
+ mtd26: 006e0000 00020000 "oem_data-a-mount"
+ mtd27: 00700000 00020000 "oem_data-a"
+ mtd28: 00020000 00020000 "oem_data-b-sdtim"
+ mtd29: 006e0000 00020000 "oem_data-b-mount"
+ mtd30: 00700000 00020000 "oem_data-b"
+ mtd31: 01400000 00020000 "rootfs_data"
+ mtd32: 05640000 00020000 "user_data"
+ mtd33: 00d20000 00020000 "MRVL_BBM"
+ */
+ while (fgets(buf, MAX_LINE_SIZE, fp) != NULL) {
+ char name[200] = {0};
+ char size[200] = {0};
+ char erasesize[200] = {0};
+ char tag[64] = {0};
+ int cnt = 0;
+ int index = 0;
+ char * p = buf;
+#ifdef CONFIG_PARTITION_EMMC
+ /* skip prev ' ' */
+ while ((index < (MAX_LINE_SIZE-1)) && (buf[index] == ' '))
+ index++;
+ p = &buf[index];
+#endif
+ while ((index < (MAX_LINE_SIZE-1)) && (buf[index] != '\0')) {
+ if (buf[index] == ' ') {
+ buf[index] = '\0';
+ if (cnt == 0) {
+ snprintf(name, sizeof(name), "%s", p);
+ } else if (cnt == 1) {
+ snprintf(size, sizeof(size), "%s", p);
+ } else if (cnt == 2) {
+ snprintf(erasesize, sizeof(erasesize), "%s", p);
+ snprintf(tag, 64, "%s", &buf[index + 1]);
+ break;
+ }
+ cnt++;
+ p = &buf[index + 1];
+ }
+ index++;
+ }
+#ifdef CONFIG_AB_SYSTEM
+ if (strncmp(name, "dev", 3) == 0)
+ continue;
+ /* retrive the mtd partition info */
+ struct image_mtd_info *pCurrentMtdInfo = &server_cfg.image_mtd_info[server_cfg.mtd_cnt];
+ int j = strlen(name);
+ if (name[j - 1] == ':')
+ name[j - 1] = '\0';
+ sprintf(pCurrentMtdInfo->dev, "%s", name);
+ sprintf(pCurrentMtdInfo->name, "%s", tag);
+
+ pCurrentMtdInfo->flag = SYSTEM_SINGLE;
+ j = strlen(tag);
+ /* the last tow chars for tag are "\n */
+ if (tag[j - 4] == '-') {
+ if (tag[j - 3] == 'a')
+ pCurrentMtdInfo->flag = SYSTEM_A;
+ else if (tag[j - 3] == 'b')
+ pCurrentMtdInfo->flag = SYSTEM_B;
+ }
+
+ /* remove the last \n */
+ pCurrentMtdInfo->name[strlen(pCurrentMtdInfo->name) - 1] = 0;
+
+ sscanf(size, "%x", &pCurrentMtdInfo->size);
+ sscanf(erasesize, "%x", &pCurrentMtdInfo->erasesize);
+
+#ifdef CONFIG_PARTITION_EMMC
+ /* dev: size start name */
+ /* the "erasesize" field represent "start" block in emmc */
+ pCurrentMtdInfo->flash_start_offset = pCurrentMtdInfo->erasesize * server_cfg.emmc_block_size;
+ pCurrentMtdInfo->size *= server_cfg.emmc_block_size;
+#else
+ pCurrentMtdInfo->flash_start_offset = get_mtd_offset(server_cfg.mtd_cnt);
+#endif
+ OTA_DEBUG(" Dev: %s, FlashOffset: 0x%x, Size: 0x%x, EraseSize: 0x%x, Name: %s\n",
+ pCurrentMtdInfo->dev, pCurrentMtdInfo->flash_start_offset, pCurrentMtdInfo->size,
+ pCurrentMtdInfo->erasesize, pCurrentMtdInfo->name);
+ if (strstr(pCurrentMtdInfo->name, "asr_flag")) {
+ int bln=0;
+ #ifdef CONFIG_PARTITION_EMMC
+ sscanf(name, "mmcblk1p%d", &bln);
+ snprintf(server_cfg.mtd_asrflag, 64, "/dev/mmcblk1p%d", bln);
+ #else
+ sscanf(name, "mtd%d", &bln);
+ snprintf(server_cfg.mtd_asrflag, 64, "/dev/mtdblock%d", bln);
+ #endif
+ }
+#ifdef CONFIG_AB_SYSTEM_DFOTA
+ else if (strstr(pCurrentMtdInfo->name, "OTA")) {
+ sscanf(size, "%x", &server_cfg.fbf_length);
+ #ifndef CONFIG_PARTITION_EMMC
+ sscanf(erasesize, "%x", &server_cfg.block_size);
+ #endif
+ snprintf(server_cfg.mtd_fbf, 64, "/dev/%s", name);
+ server_cfg.fbf_addr = pCurrentMtdInfo->flash_start_offset;
+ OTA_DEBUG("Get MTD info: 0x%x\n", server_cfg.fbf_addr);
+ OTA_DEBUG(" name: %s\n", server_cfg.mtd_fbf);
+ OTA_DEBUG(" size: %08x\n", server_cfg.fbf_length);
+ OTA_DEBUG(" erasesize: %08x\n", server_cfg.block_size);
+ OTA_DEBUG(" tag: %s\n", tag);
+ }
+#endif
+ server_cfg.mtd_cnt++;
+#else
+ if (strncmp(tag, "\"asr_flag\"", 10) == 0) {
+ int j = strlen(name);
+ unsigned int asr_size;
+ unsigned int asr_erasesize;
+ sscanf(size, "%x", &asr_size);
+ sscanf(erasesize, "%x", &asr_erasesize);
+ if (name[j - 1] == ':') {
+ name[j - 1] = '\0';
+ }
+ int bln=0;
+ sscanf(name, "mtd%d", &bln);
+ //sprintf(asr_flag_path, "/dev/mtdblock%d", bln);
+
+ snprintf(server_cfg.mtd_asrflag, 64, "/dev/mtdblock%d", bln);
+ OTA_DEBUG("Get MTD info:\n");
+ OTA_DEBUG(" name: %s\n", name);
+ OTA_DEBUG(" mtd_asrflag: %s\n", server_cfg.mtd_asrflag);
+ OTA_DEBUG(" size: %08x\n", asr_size);
+ OTA_DEBUG(" erasesize: %08x\n", asr_erasesize);
+ OTA_DEBUG(" tag: %s\n", tag);
+ }else if (strncmp(tag, "\"OTA\"", 5) == 0) {
+ int j = strlen(name);
+ sscanf(size, "%x", &server_cfg.fbf_length);
+ sscanf(erasesize, "%x", &server_cfg.block_size);
+ if (name[j - 1] == ':') {
+ name[j - 1] = '\0';
+ }
+
+ int bln=0;
+ sscanf(name, "mtd%d", &bln);
+ server_cfg.fbf_addr = get_mtd_offset(bln);
+ snprintf(server_cfg.mtd_fbf, 64, "/dev/%s", name);
+ OTA_DEBUG("Get MTD info:\n");
+ OTA_DEBUG(" name: %s\n", server_cfg.mtd_fbf);
+ OTA_DEBUG(" size: %08x\n", server_cfg.fbf_length);
+ OTA_DEBUG(" erasesize: %08x\n", server_cfg.block_size);
+ OTA_DEBUG(" tag: %s\n", tag);
+ OTA_DEBUG(" fbf_addr: 0x%08x\n", server_cfg.fbf_addr);
+ }
+#endif
+ memset(buf, 0, MAX_LINE_SIZE);
+ }
+ fclose(fp);
+#ifdef CONFIG_AB_SYSTEM
+ gInActiveSystem = get_inactive_system();
+ if (gInActiveSystem != SYSTEM_B && gInActiveSystem != SYSTEM_A) {
+ OTA_ERR("FATAL ERROR, no legal inactive system flag exist...");
+ return -1;
+ }
+ OTA_DEBUG("Inactive System is %c...\n", gInActiveSystem);
+ system_sync();
+#endif
+ return 0;
+}
+
+static int sync_mversion(void)
+{
+ int ret = 0, i;
+ int fd_asrflag, fd_mversion;
+ int len_asrflag, len_mversion, len;
+ char mversion[128];
+ struct tr069_firmware_flag AsrFlag;
+ char *p_mversion;
+ p_mversion = AsrFlag.mversion;
+
+#ifdef CONFIG_AB_SYSTEM
+ if (gInActiveSystem == SYSTEM_A)
+ p_mversion = AsrFlag.MVersion_B;
+#endif
+
+ memset(mversion, 0, 128);
+
+ fd_asrflag = open(server_cfg.mtd_asrflag, O_RDWR);
+ if (fd_asrflag < 0) {
+ OTA_ERR("Fatal error: can't open asr flag %s\n", server_cfg.mtd_asrflag);
+ return -1;
+ }
+
+ len_asrflag = read(fd_asrflag, &AsrFlag, sizeof(AsrFlag));
+ if (len_asrflag != sizeof(AsrFlag)) {
+ OTA_ERR("Fatal error: read %d bytes(expect %d)\n", len_asrflag, sizeof(AsrFlag));
+ close(fd_asrflag);
+ return -1;
+ }
+
+ fd_mversion = open("/etc/mversion", O_RDWR);
+ if (fd_mversion < 0) {
+ OTA_ERR("Fatal error: can't open /etc/mversion\n");
+ close(fd_asrflag);
+ return -1;
+ }
+ len_mversion = read(fd_mversion, mversion, 128);
+ if(len_mversion <= 0)
+ {
+ OTA_ERR("Fatal error: read mversion\n");
+ ret = -1;
+ goto sync_done;
+ }
+
+ for (i = len_mversion - 1; i >= 0; i--)
+ {
+ if(mversion[i] == '\n' || mversion[i] == '\r'){
+ len_mversion -- ;
+ mversion[i] = 0;
+ }
+ else
+ break;
+ }
+
+ if(p_mversion[0] == 0xFF || p_mversion[0] == 0x0)
+ {
+ OTA_ERR("There is no mversion in asr flag\n");
+ goto sync_done;
+ }
+
+ if(memcmp(mversion, p_mversion, len_mversion) != 0)
+ {
+ memset(mversion, 0, 128);
+ strncpy(mversion, p_mversion, 128);
+ mversion[127]=0;
+ lseek(fd_mversion, 0, SEEK_SET);
+ len = write(fd_mversion, mversion, 128);
+ if (len != 128) {
+ OTA_ERR("Fail to write mversion: write %d bytes(expected %d)\n", len, 128);
+ ret = -1;
+ }
+ write(fd_mversion, "\n", 1);
+ goto sync_done;
+ }
+
+sync_done:
+ close(fd_asrflag);
+ close(fd_mversion);
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+// char * uci_path = NULL;
+
+ mbtk_log_init("radio", "MBTK_OTAD");
+ //set_service_log_tag("OTAD");
+ prctl(PR_SET_NAME, "otad");
+
+#if 0
+ if (argc > 1) { /* UCI file exist */
+#ifdef CONFIG_AB_SYSTEM
+ if (strncmp(argv[1], "-f", 2) == 0) {
+ switch (argc) {
+ case 2:
+ OTA_ERR("miss fota path.\n");
+ return -1;
+ case 4:
+ default:
+ /* go through */
+ uci_path = argv[3];
+ OTA_DEBUG("OTA service start(%s)\n", uci_path);
+ case 3:
+ ret = get_fota_version(argv[2], server_cfg.fotav, 128);
+ if (ret > 0) {
+ OTA_ERR("get_fota_version failed, ret: %d\n", ret);
+ return -1;
+ }
+ OTA_DEBUG("got fotav: %s\n", server_cfg.fotav);
+ if (upgrade_precheck(server_cfg.fotav) < 0)
+ return -1;
+ break;
+ }
+ } else
+#endif
+ {
+ uci_path = argv[1];
+ OTA_DEBUG("OTA service start(%s)\n", uci_path);
+ }
+ } else { /* No UCI file - use default values */
+ OTA_DEBUG("OTA service start\n");
+ }
+#endif
+
+ uloop_init();
+ ctx = ubus_connect(UBUS_UNIX_SOCKET);
+ if (ctx == NULL) {
+ OTA_ERR("Connect to UBUSD failed!\n");
+ ret = -1;
+ goto done;
+ }
+ ubus_add_uloop(ctx);
+ ret = ubus_add_object(ctx, &ota_object);
+
+ memset(&server_cfg, 0, sizeof(server_cfg));
+ // ota
+ init_cfg(NULL);
+#if !defined(CONFIG_AB_SYSTEM) || defined(CONFIG_AB_SYSTEM_DFOTA)
+ if (server_cfg.fbf_length == 0 || server_cfg.block_size == 0) {
+ OTA_ERR("Config file incorrect!\n");
+ return -1;
+ }
+#endif
+ if (server_cfg.progress_notify == 0) {
+ server_cfg.progress_notify = 10;
+ }
+ if (server_cfg.interval == 0) {
+ server_cfg.interval = 5;
+ }
+ if (server_cfg.first_interval == 0) {
+ server_cfg.first_interval = 1;
+ }
+ if (server_cfg.fbf_addr == 0) {
+ server_cfg.fbf_addr = 0x2a60000;
+ }
+
+ if (strlen(server_cfg.server_url) != 0) {
+ int fd = open("/etc/mversion", O_RDONLY);
+ if (fd < 0) {
+ OTA_ERR("Read version failed!\n");
+ return -1;
+ }
+ read(fd, version_check_context.version, OTA_MAX_STRING_LEN);
+ close(fd);
+ uloop_timeout_set(&version_check_timer, 1000 * server_cfg.first_interval);
+ }
+
+ if(sync_mversion() != 0)
+ OTA_ERR("Sync mversion error\n");
+
+ uloop_run();
+done:
+
+ return ret;
+}
+