blob: cb0c9761ff51bb13f3dca460e384da299128ee89 [file] [log] [blame]
b.liua76c9612025-03-28 13:58:09 +08001#include "tim.h"
2
3#define DTIM_MAX_SIZE (128 * 1024)
4
5#if 0
6
7static const char *id2str(unsigned int id)
8{
9 switch (id) {
10 case IMAGE_ID_ARBEL:
11 return "ARBEL";
12 case IMAGE_ID_DTIM_A:
13 return "DTIM_A";
14 case IMAGE_ID_DTIM_B:
15 return "DTIM_B";
16 case IMAGE_ID_KERNEL:
17 return "KERNEL";
18 case IMAGE_ID_MSA:
19 return "MSA";
20 case IMAGE_ID_OEMD:
21 return "OEMD";
22 case IMAGE_ID_RF:
23 return "RF";
24 case IMAGE_ID_ROOTFS:
25 return "ROOTFS";
26 case IMAGE_ID_UBOOT:
27 return "UBOOT";
28 default:
29 OTA_ERR("Unkown id: 0x%x\n", id);
30 return "NULL";
31 }
32}
33#endif
34
35static int SetTIMPointers( void *pStartAddr, TIM *pTIM_h)
36{
37 pTIM_h->pConsTIM = (pCTIM) pStartAddr; // Overlap Contant Part of TIM with actual TIM...
38
39 if ((pTIM_h->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER) ||
40 (pTIM_h->pConsTIM->VersionBind.Version < TIM_3_2_00)) {
41 /* incorrect tim */
42 pTIM_h->pConsTIM = NULL;
43 return -1;
44 }
45
46 // Assign a pointer to start of Images Area
47 pTIM_h->pImg = (pIMAGE_INFO_3_4_0) (pStartAddr + sizeof (CTIM));
48
49 // Assign a pointer to start of Key Area
50 if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00)
51 pTIM_h->pKey = (pKEY_MOD_3_4_0) ((UINT_T)pTIM_h->pImg + ((pTIM_h->pConsTIM->NumImages) * sizeof (IMAGE_INFO_3_4_0)));
52 else
53 pTIM_h->pKey = (pKEY_MOD_3_4_0) ((UINT_T)pTIM_h->pImg + ((pTIM_h->pConsTIM->NumImages) * sizeof (IMAGE_INFO_3_2_0)));
54
55 // Assign a pointer to start of reserved area
56 if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00)
57 pTIM_h->pReserved = (PUINT) ((UINT_T)pTIM_h->pKey + ((pTIM_h->pConsTIM->NumKeys) * sizeof (KEY_MOD_3_4_0)));
58 else if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_3_00)
59 pTIM_h->pReserved = (PUINT) ((UINT_T)pTIM_h->pKey + ((pTIM_h->pConsTIM->NumKeys) * sizeof (KEY_MOD_3_3_0)));
60 else
61 pTIM_h->pReserved = (PUINT) ((UINT_T)pTIM_h->pKey + ((pTIM_h->pConsTIM->NumKeys) * sizeof (KEY_MOD_3_2_0)));
62
63 // Assign a pointer to start of DS
64 pTIM_h->pTBTIM_DS = (pPLAT_DS) ((UINT_T)pTIM_h->pReserved + pTIM_h->pConsTIM->SizeOfReserved);
65 return (NoError);
66}
67
68#if 0
69static void dump_dtim(pTIM t)
70{
71 int i;
72 pIMAGE_INFO_3_4_0 pImg;
73 OTA_DEBUG("### Image in dtim ###\n");
74 OTA_DEBUG("Images number: %d\n", t->pConsTIM->NumImages);
75 for (i = 0; i < t->pConsTIM->NumImages; i++) {
76 pImg = (pIMAGE_INFO_3_4_0)(t->pImg + i);
77 OTA_DEBUG("[%d] ID: %s, NextID: %s, Offset: 0x%x, "
78 "LoadAddr: 0x%x, Size: %d, SizeToHash: %d, HashAlgorithmID: 0x%x\n", i,
79 id2str(pImg->ImageID), id2str(pImg->NextImageID), pImg->FlashEntryAddr,
80 pImg->LoadAddr, pImg->ImageSize, pImg->ImageSizeToHash,
81 pImg->HashAlgorithmID);
82 OTA_DEBUG("[%d] Hash: 0x%x, 0x%x, 0x%x, 0x%x, "
83 "0x%x, 0x%x, 0x%x, 0x%x, "
84 "0x%x, 0x%x, 0x%x, 0x%x, "
85 "0x%x, 0x%x, 0x%x, 0x%x\n", i,
86 pImg->Hash[0], pImg->Hash[1], pImg->Hash[2], pImg->Hash[3],
87 pImg->Hash[4], pImg->Hash[5], pImg->Hash[6], pImg->Hash[7],
88 pImg->Hash[8], pImg->Hash[9], pImg->Hash[10], pImg->Hash[11],
89 pImg->Hash[12], pImg->Hash[13], pImg->Hash[14], pImg->Hash[15]);
90 }
91}
92
93static void *load_dtim(const char *dev)
94{
95 int fd = -1;
96
97 char _dev[32] = {0};
98 char *buf = malloc(DTIM_MAX_SIZE);
99 if (!buf) {
100 OTA_ERR("failed to malloc 0x%x for dtim.\n", DTIM_MAX_SIZE);
101 goto out;
102 }
103
104 sprintf(_dev, "/dev/%s", dev);
105 fd = open(_dev, O_RDWR | O_SYNC);
106 if (fd < 0) {
107 OTA_ERR("failed to open %s.\n", _dev);
108 free(buf);
109 buf = NULL;
110 goto out;
111 }
112
113 if (complete_read(fd, buf, DTIM_MAX_SIZE) < 0) {
114 OTA_ERR("failed to load %s.\n", _dev);
115 free(buf);
116 buf = NULL;
117 goto out;
118 }
119
120out:
121 if (fd >= 0)
122 close(fd);
123 return buf;
124}
125
126static int __save_dtim(int fd, pTIM pTIM_h)
127{
128 int r = -1;
129 struct erase_info_user mtdEraseInfo;
130 struct mtd_info_user mtdInfo;
131
132 if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
133 OTA_ERR("could not get MTD device info.\n");
134 goto out;
135 }
136 mtdEraseInfo.start = 0;
137 mtdEraseInfo.length = mtdInfo.erasesize;
138
139 ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
140 ioctl(fd, MEMERASE, &mtdEraseInfo);
141
142 if (complete_write(fd, (char *)pTIM_h->pConsTIM, DTIM_MAX_SIZE) < 0)
143 goto out;
144
145 r = 0;
146out:
147 return r;
148}
149
150static int save_dtim(const char *dev, pTIM pTIM_h)
151{
152 int fd = -1;
153 int r = -1;
154 char _dev[32] = {0};
155 sprintf(_dev, "/dev/%s", dev);
156 fd = open(_dev, O_RDWR | O_SYNC);
157 if (fd < 0) {
158 OTA_ERR("failed to open %s.\n", _dev);
159 goto out;
160 }
161
162 r = __save_dtim(fd, pTIM_h);
163 if (r)
164 OTA_ERR("failed to save dtim to %s.\n", _dev);
165out:
166 if (fd >= 0)
167 close(fd);
168 return r;
169}
170
171/* sync the new to old */
172static int __sync_dtim(pTIM pNew, pTIM pOld)
173{
174 int r = -1, i, j, found = 0, images;
175 int flag = 0;
176 pIMAGE_INFO_3_4_0 pImgSrc, pImgDst;
177
178 OTA_DEBUG("%s: new dtim mode: %d, old dtim mode: %d.\n", __func__,
179 pNew->pConsTIM->VersionBind.Trusted, pOld->pConsTIM->VersionBind.Trusted);
180 if (pNew->pConsTIM->VersionBind.Trusted != pOld->pConsTIM->VersionBind.Trusted) {
181 OTA_ERR("%s: Fatal Error. Can't sync two different trust mode dtim.\n", __func__);
182 return -1;
183 }
184
185 for (i = 0; i < pNew->pConsTIM->NumImages; i++) {
186 pImgSrc = (pIMAGE_INFO_3_4_0)(pNew->pImg + i);
187 for (j = 0; j < pOld->pConsTIM->NumImages; j++) {
188 pImgDst = (pIMAGE_INFO_3_4_0)(pOld->pImg + j);
189 if (pImgSrc->ImageID == pImgDst->ImageID &&
190 pImgSrc->ImageID != IMAGE_ID_DTIM_A &&
191 pImgSrc->ImageID != IMAGE_ID_DTIM_B) {
192 found++;
193 if (pImgSrc->ImageSize != pImgDst->ImageSize ||
194 pImgSrc->ImageSizeToHash != pImgDst->ImageSizeToHash ||
195 pImgSrc->LoadAddr != pImgDst->LoadAddr ||
196 pImgSrc->HashAlgorithmID != pImgDst->HashAlgorithmID ||
197 memcmp(pImgSrc->Hash, pImgDst->Hash, sizeof(pImgSrc->Hash)) != 0)
198 {
199 OTA_DEBUG("Image: %s has been changed.\n", id2str(pImgSrc->ImageID));
200 pImgDst->ImageID = pImgSrc->ImageID;
201 pImgDst->ImageSize = pImgSrc->ImageSize;
202 pImgDst->ImageSizeToHash = pImgSrc->ImageSizeToHash;
203 pImgDst->LoadAddr = pImgSrc->LoadAddr;
204 pImgDst->HashAlgorithmID = pImgSrc->HashAlgorithmID;
205 memcpy(pImgDst->Hash, pImgSrc->Hash, sizeof(pImgSrc->Hash));
206 flag = 1;
207 break;
208 }
209 }
210 }
211 }
212
213 images = pNew->pConsTIM->NumImages - 1;
214 /* omit the first image(dtim it self) */
215 if (found != images) {
216 OTA_ERR("FATAL ERROR: NumImage: %d, found: %d, not exactly match.\n"
217 , pNew->pConsTIM->NumImages, found);
218 goto out;
219 }
220
221 r = flag;
222out:
223 return r;
224}
225
226static int update_dtim(const char *dev, void *bufNew)
227{
228 int r = -1;
229 TIM tNew, tOld;
230 char *buf = load_dtim(dev);
231
232 if (!buf) {
233 OTA_ERR("%s: failed to load dtim for %s.\n", __func__, dev);
234 goto out;
235 }
236
237 SetTIMPointers(buf, &tOld);
238 SetTIMPointers(bufNew, &tNew);
239
240 OTA_DEBUG("### Dump orignal dtim of %s. ###\n", dev);
241 dump_dtim(&tOld);
242 OTA_DEBUG("### Dump the new dtim. ###\n");
243 dump_dtim(&tNew);
244
245 r = __sync_dtim(&tNew, &tOld);
246 if (r < 0)
247 goto out;
248 if (r > 0) {
249 OTA_DEBUG("Images have been changed, update %s\n", dev);
250 r = save_dtim(dev, &tOld);
251 } else {
252 OTA_DEBUG("Images have NO change, DO NOT need to sync.\n");
253 r = 0;
254 }
255
256 OTA_DEBUG("%s: %s.\n", __func__, (r >= 0) ? "OK" : "FAILED");
257out:
258 if (buf)
259 free(buf);
260 return r;
261}
262
263static int sync_dtim(const char *src, const char *dst)
264{
265 int r = -1;//, i, j, found = 0;
266// int flag = 0;
267// pIMAGE_INFO_3_4_0 pImgSrc, pImgDst;
268 TIM tSrc;
269 TIM tDst;
270 char *bufSrc = load_dtim(src);
271 char *bufDst = load_dtim(dst);
272
273 OTA_DEBUG("Start to sync %s to %s.\n", src, dst);
274 if (!bufSrc || !bufDst) {
275 OTA_ERR("failed to sync %s to %s.\n", src, dst);
276 goto out;
277 }
278
279 SetTIMPointers(bufSrc, &tSrc);
280 SetTIMPointers(bufDst, &tDst);
281
282 OTA_DEBUG("Dump dtim info of %s.\n", src);
283 dump_dtim(&tSrc);
284 OTA_DEBUG("Dump dtim info of %s.\n", dst);
285 dump_dtim(&tDst);
286
287 if (tSrc.pConsTIM->NumImages != tDst.pConsTIM->NumImages) {
288 OTA_ERR("FATAL ERROR: NumImages(%s): %d, NumImages(%s): %d.\n",
289 src, tSrc.pConsTIM->NumImages, dst, tDst.pConsTIM->NumImages);
290 goto out;
291 }
292
293 r = __sync_dtim(&tSrc, &tDst);
294 if (r < 0)
295 goto out;
296 if (r > 0) {
297 OTA_DEBUG("Images have been changed, need to sync %s to %s.\n", src, dst);
298 r = save_dtim(dst, &tDst);
299 } else {
300 OTA_DEBUG("Images have NO change, DO NOT need to sync.\n");
301 r = 0;
302 }
303out:
304 if (bufSrc)
305 free(bufSrc);
306 if (bufDst)
307 free(bufDst);
308 return r;
309}
310
311/* dev is the mtd device of dtim */
312static int get_image_mode(const char *dev)
313{
314 char *buf = load_dtim(dev);
315 TIM tim;
316 int mode;
317
318 if (!buf) {
319 OTA_ERR("%s: failed to load dtim for %s.\n", __func__, dev);
320 return -1;
321 }
322
323 SetTIMPointers(buf, &tim);
324 mode = tim.pConsTIM->VersionBind.Trusted;
325 OTA_DEBUG("%s: it is %s mode(%s).\n", __func__, (mode == 1) ? "Trusted" : "NON-Trusted", dev);
326 free(buf);
327 return mode;
328}
329#endif
330
331static UINT_T CheckReserved (pTIM pTIM_h)
332{
333 pWTP_RESERVED_AREA pWRA = (pWTP_RESERVED_AREA) pTIM_h->pReserved;
334
335 // Make sure that the TIM has a credible size
336 if(pTIM_h->pConsTIM->SizeOfReserved == 0)
337 return NotFoundError;
338
339 // Older TIM's had old reserved fields definition
340 if (pTIM_h->pConsTIM->VersionBind.Version == (0x00030101))
341 return NotFoundError;
342
343 // Was this area in reserved field created by a WTP compliant tool so we can parse?
344 if (pWRA->WTPTP_Reserved_Area_ID != WTPRESERVEDAREAID)
345 return NotFoundError;
346
347 return NoError;
348}
349
350// Finds a Package of WTP recognized information in the reserved area based on identifier
351static pWTP_RESERVED_AREA_HEADER FindPackageInReserved (UINT_T * Retval, pTIM pTIM_h, UINT_T Identifier)
352{
353 UINT_T Count = 0;
354 pWTP_RESERVED_AREA_HEADER pWRAH = NULL;
355 pWTP_RESERVED_AREA pWRA = (pWTP_RESERVED_AREA) pTIM_h->pReserved;
356
357 *Retval = CheckReserved(pTIM_h);
358 if (*Retval != NoError)
359 return NULL;
360
361 // Start from the begining
362 pWRAH = (pWTP_RESERVED_AREA_HEADER) (pWRA + 1);
363
364 while ((pWRAH->Identifier != Identifier) && (pWRAH->Identifier != TERMINATORID) && (Count < pWRA->NumReservedPackages))
365 {
366 pWRAH = (pWTP_RESERVED_AREA_HEADER)((UINT_T)pWRAH + ((pWRAH->Size + 3) & ~3)); // Skip to the next one
367 Count++;
368 }
369 if (pWRAH->Identifier != Identifier)
370 {
371 *Retval = NotFoundError;
372 pWRAH = NULL;
373 }
374
375 return pWRAH;
376}
377
378// This function has been added to support to isolate backwards compatibility to tim.c
379// It will return a point to pIMAGE_INFO based on TIM version.
380static pIMAGE_INFO_3_4_0 ReturnPImgPtr(pTIM pTIM_h, UINT_T ImageNumber)
381{
382 pIMAGE_INFO_3_4_0 pIMG;
383 pIMG = (pIMAGE_INFO_3_4_0) &pTIM_h->pImg[ImageNumber];
384 return pIMG;
385}
386
387// This function is used to find an image information field in the TIM
388// of the image with the ID passed in
389
390static pIMAGE_INFO_3_4_0 FindImageInTIM(pTIM pTIM_h, UINT_T ImageID)
391{
392 pIMAGE_INFO_3_4_0 pImageInfo = NULL;
393 UINT8_T i;
394
395 if (pTIM_h)
396 {
397 for( i = 0; i < pTIM_h->pConsTIM->NumImages; i++)
398 {
399 pImageInfo = ReturnPImgPtr(pTIM_h, i);
400 if(pImageInfo->ImageID == ImageID)
401 return pImageInfo;
402 }
403 }
404 return NULL;
405}
406
407static int __retrive_timh_by_ddrid(pTIM pTIM_h, unsigned int *DDR_ID, int *imagesize)
408{
409 int i, DDRTimIndex = -1;
410 UINT_T /*LoadAddr, TimSize, */TimLoadAddr, Retval;
411 pIMAGE_INFO_3_4_0 pTimInfo = NULL;
412 pWTP_RESERVED_AREA_HEADER pWRAH = NULL;
413 pDDR_FLASH_MCP_PACKAGE pMCP = NULL;
414#if 0
415 if (DDR_ID == 0xFFFFFFFF || DDR_ID == 0) {
416 OTA_ERR("Warning: no valid DDR ID in ASR Flag\n");
417 return NoError;
418 }
419#endif
420 TimLoadAddr = (UINT_T)pTIM_h->pConsTIM;
421
422 pWRAH = FindPackageInReserved(&Retval, pTIM_h, DDR_FLASH_MCP_PACKAGE_ID);
423 if(pWRAH == NULL) {
424 OTA_ERR("No DFMP found, single DDR TIM\n\r");
425 return NoError;
426 } else {
427 pMCP = (DDR_FLASH_MCP_PACKAGE *) pWRAH;
428 for (i = 0; i < pMCP->NumberVendorDdrFlashSpec; i++) {
429 if(pMCP->ddrFlashSpec[i].VendorDdrPid == *DDR_ID) {
430 DDRTimIndex = i;
431 OTA_DEBUG("%s: [%d] got ddr id: 0x%x\n", __func__, i, *DDR_ID);
432 break;
433 }
434 }
435
436 pTimInfo = FindImageInTIM(pTIM_h, IMAGE_ID_TIMH);
437 if(pTimInfo == NULL) {
438 OTA_ERR("%s %d: No TIMH found, error\n", __func__, __LINE__);
439 return TIMNotFound;
440 }
441
442 if (DDRTimIndex < 0) {
443 OTA_ERR("NOT found ddr id: 0x%x, use the first TIM ddrid: 0x%x",
444 *DDR_ID, pMCP->ddrFlashSpec[0].VendorDdrPid);
445 *DDR_ID = pMCP->ddrFlashSpec[0].VendorDdrPid;
446 goto out;
447 }
448
449 /* go through all the TIMs to the right one */
450 for (i = 0; i < (DDRTimIndex + 1); i++) {
451 Retval = SetTIMPointers((void *)TimLoadAddr, pTIM_h);
452 if(Retval) {
453 OTA_ERR("%s %d: failed\n", __func__, __LINE__);
454 return TIMNotFound;
455 }
456
457 pTimInfo = FindImageInTIM(pTIM_h, IMAGE_ID_TIMH);
458 if(pTimInfo == NULL) {
459 OTA_ERR("%s %d: No TIMH found, error\n", __func__, __LINE__);
460 return TIMNotFound;
461 }
462 TimLoadAddr += pTimInfo->ImageSize;
463 }
464 }
465
466out:
467 *imagesize = pTimInfo->ImageSize;
468 OTA_DEBUG("%s: index: %d, size: 0x%x\n", __func__, DDRTimIndex, pTimInfo->ImageSize);
469 return NoError;
470}