Add mbtk_otad

Change-Id: I472a8f3acdc6207a17800352bf7ce5e6fff167a9
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;
+}
+