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;
+}
+