blob: 9d13beee52c1754393b97821a8e6cd133143dd76
1 | #include <errno.h> |
2 | #include <ctype.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <fcntl.h> |
6 | #include <unistd.h> |
7 | #include <string.h> |
8 | #include <sys/stat.h> |
9 | #include <sys/types.h> |
10 | #include <ziparchive/zip_archive.h> |
11 | #include "dtbcheck.h" |
12 | |
13 | |
14 | extern "C" { |
15 | #include "fdt/libfdt.h" |
16 | } |
17 | |
18 | |
19 | |
20 | #define MAX_LEVEL 32 /* how deeply nested we will go */ |
21 | #define CONFIG_CMD_FDT_MAX_DUMP 64 |
22 | |
23 | #define DT_HEADER_MAGIC 0xedfe0dd0 /*header of dtb file*/ |
24 | #define AML_DT_HEADER_MAGIC 0x5f4c4d41 /*"AML_", multi dtbs supported*/ |
25 | |
26 | #define AML_DT_ID_VARI_TOTAL 3 //Total 3 strings |
27 | /*Latest version: v2*/ |
28 | #define AML_DT_VERSION_OFFSET 4 |
29 | #define AML_DT_TOTAL_DTB_OFFSET 8 |
30 | #define AML_DT_FIRST_DTB_OFFSET 12 |
31 | |
32 | #define AML_DT_DTB_DT_INFO_OFFSET 0 |
33 | |
34 | #define ENV_DTB "aml_dt" |
35 | #define CMDLINE "/proc/cmdline" |
36 | #define STORE_DEVICE "/sys/class/aml_store/store_device" |
37 | #define DEVICE_NAND 2 |
38 | #define DEVICE_EMMC 1 |
39 | |
40 | extern int IsPlatformEncrypted(void); |
41 | |
42 | extern int DtbImgEncrypted( |
43 | const char *imageName, |
44 | const unsigned char *imageBuffer, |
45 | const int imageSize, |
46 | const char *flag, |
47 | unsigned char *encryptedbuf); |
48 | |
49 | struct fdt_header *working_fdt; |
50 | |
51 | static Dtb_Partition_S dtb_zip[24]; |
52 | static Dtb_Partition_S dtb_dev[24]; |
53 | |
54 | unsigned int recovery_size1 = 32*1024*1024; //default value 32M |
55 | |
56 | static int isEncrypted = 0; |
57 | |
58 | struct Dtb_header { |
59 | unsigned int dt_magic; |
60 | unsigned int dt_tool_version; |
61 | unsigned int dt_total; |
62 | char data[0]; |
63 | }; |
64 | |
65 | |
66 | /****************************************************************************/ |
67 | |
68 | |
69 | unsigned int |
70 | STRTOU32(unsigned char* p){ |
71 | return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]; |
72 | } |
73 | |
74 | int GetDeviceType() |
75 | { |
76 | FILE *p = NULL; |
77 | int len = 0; |
78 | char buffer[32] = {0}; |
79 | int type = 0; |
80 | |
81 | p = fopen(STORE_DEVICE, "r"); |
82 | if (p == NULL) { |
83 | printf("open failed!\n"); |
84 | return -1; |
85 | } |
86 | |
87 | len = fread(buffer, 1, 32, p); |
88 | if (len <= 0) { |
89 | printf("fread failed!\n"); |
90 | fclose(p); |
91 | return -1; |
92 | } |
93 | fclose(p); |
94 | |
95 | printf("buffer:%s\n",buffer); |
96 | |
97 | type = atoi(buffer); |
98 | printf("type=%d\n",type); |
99 | return type; |
100 | } |
101 | |
102 | signed int |
103 | GetDtbId(char *pdt){ |
104 | FILE *p = NULL; |
105 | int len = 0; |
106 | char buffer[1024] = {0}; |
107 | |
108 | if (pdt == NULL) { |
109 | printf("param error!\n"); |
110 | return -1; |
111 | } |
112 | |
113 | p = fopen(CMDLINE, "r"); |
114 | if (p == NULL) { |
115 | printf("open failed!\n"); |
116 | return -1; |
117 | } |
118 | |
119 | len = fread(buffer, 1, 1023, p); |
120 | if (len <= 0) { |
121 | printf("fread failed!\n"); |
122 | fclose(p); |
123 | return -1; |
124 | } |
125 | fclose(p); |
126 | |
127 | char *paddr=strstr(buffer, ENV_DTB); |
128 | if (paddr == NULL) { |
129 | printf("not find env:aml_dt !\n"); |
130 | return -1; |
131 | } |
132 | |
133 | paddr = strtok(paddr, " "); |
134 | |
135 | paddr = paddr+strlen(ENV_DTB)+1; |
136 | //printf("cmdline, aml_dt=%s\n", paddr); |
137 | |
138 | strcpy(pdt, paddr); |
139 | return 0; |
140 | } |
141 | |
142 | |
143 | /* |
144 | * Heuristic to guess if this is a string or concatenated strings. |
145 | */ |
146 | |
147 | static int |
148 | is_printable_string(const void *data, int len){ |
149 | const char *s = (char *)data; |
150 | |
151 | /* zero length is not */ |
152 | if (len == 0) |
153 | return 0; |
154 | |
155 | /* must terminate with zero or '\n' */ |
156 | if (s[len - 1] != '\0' && s[len - 1] != '\n') |
157 | return 0; |
158 | |
159 | /* printable or a null byte (concatenated strings) */ |
160 | while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { |
161 | /* |
162 | * If we see a null, there are three possibilities: |
163 | * 1) If len == 1, it is the end of the string, printable |
164 | * 2) Next character also a null, not printable. |
165 | * 3) Next character not a null, continue to check. |
166 | */ |
167 | if (s[0] == '\0') { |
168 | if (len == 1) |
169 | return 1; |
170 | if (s[1] == '\0') |
171 | return 0; |
172 | } |
173 | s++; |
174 | len--; |
175 | } |
176 | |
177 | /* Not the null termination, or not done yet: not printable */ |
178 | if (*s != '\0' || (len != 0)) |
179 | return 0; |
180 | |
181 | return 1; |
182 | } |
183 | |
184 | |
185 | |
186 | /* |
187 | * Print the property in the best format, a heuristic guess. Print as |
188 | * a string, concatenated strings, a byte, word, double word, or (if all |
189 | * else fails) it is printed as a stream of bytes. |
190 | */ |
191 | static void print_data(const void *data, int len, int *index, int flag) |
192 | { |
193 | int j; |
194 | |
195 | char *pd = (char *)data; |
196 | |
197 | /* no data, don't print */ |
198 | if (len == 0) |
199 | return; |
200 | |
201 | /* |
202 | * It is a string, but it may have multiple strings (embedded '\0's). |
203 | */ |
204 | if (is_printable_string(pd, len)) { |
205 | j = 0; |
206 | while (j < len) { |
207 | if (flag == 0) { |
208 | strcpy(dtb_zip[*index].partition_name, pd); |
209 | } else { |
210 | strcpy(dtb_dev[*index].partition_name, pd); |
211 | } |
212 | j += strlen(pd) + 1; |
213 | pd += strlen(pd) + 1; |
214 | } |
215 | return; |
216 | } |
217 | |
218 | if ((len %4) == 0) { |
219 | if (len > CONFIG_CMD_FDT_MAX_DUMP) |
220 | ; |
221 | else if (len == 8){ |
222 | const __be32 *p; |
223 | p = (__be32 *)pd; |
224 | if (flag == 0) |
225 | { |
226 | dtb_zip[*index].partition_size = fdt32_to_cpu(p[1]) - fdt32_to_cpu(p[0]); |
227 | } |
228 | else |
229 | { |
230 | dtb_dev[*index].partition_size = fdt32_to_cpu(p[1]) - fdt32_to_cpu(p[0]); |
231 | } |
232 | (*index)++; |
233 | } |
234 | } else { /* anything else... hexdump */ |
235 | if (len > CONFIG_CMD_FDT_MAX_DUMP) |
236 | ; |
237 | else { |
238 | const unsigned char *s; |
239 | } |
240 | } |
241 | } |
242 | |
243 | |
244 | int |
245 | GetPartitionFromDtb(const char *pathp, int depth, int *partition_num, int flag){ |
246 | static char tabs[MAX_LEVEL+1] = |
247 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" |
248 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; |
249 | const void *nodep; /* property node pointer */ |
250 | int nodeoffset; /* node offset from libfdt */ |
251 | int index = 0; |
252 | int nextoffset; /* next node offset from libfdt */ |
253 | uint32_t tag; /* tag */ |
254 | int len; /* length of the property */ |
255 | int level = 0; /* keep track of nesting level */ |
256 | const struct fdt_property *fdt_prop; |
257 | |
258 | nodeoffset = fdt_path_offset (working_fdt, pathp); |
259 | if (nodeoffset < 0) { |
260 | /* |
261 | * Not found or something else bad happened. |
262 | */ |
263 | printf ("libfdt fdt_path_offset() returned %s\n", |
264 | fdt_strerror(nodeoffset)); |
265 | return 1; |
266 | } |
267 | |
268 | |
269 | /* |
270 | * The user passed in a node path and no property, |
271 | * print the node and all subnodes. |
272 | */ |
273 | while (level >= 0) { |
274 | tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); |
275 | switch (tag) { |
276 | case FDT_BEGIN_NODE: |
277 | pathp = fdt_get_name(working_fdt, nodeoffset, NULL); |
278 | if (level <= depth) { |
279 | if (pathp == NULL) |
280 | pathp = "/* NULL pointer error */"; |
281 | if (*pathp == '\0') |
282 | pathp = "/"; /* root is nameless */ |
283 | } |
284 | level++; |
285 | if (level >= MAX_LEVEL) { |
286 | printf("Nested too deep, aborting.\n"); |
287 | return 1; |
288 | } |
289 | break; |
290 | case FDT_END_NODE: |
291 | level--; |
292 | if (level <= depth) |
293 | ; |
294 | if (level == 0) { |
295 | level = -1; /* exit the loop */ |
296 | } |
297 | break; |
298 | case FDT_PROP: |
299 | fdt_prop = (struct fdt_property *)fdt_offset_ptr(working_fdt, nodeoffset, |
300 | sizeof(*fdt_prop)); |
301 | pathp = fdt_string(working_fdt, |
302 | fdt32_to_cpu(fdt_prop->nameoff)); |
303 | len = fdt32_to_cpu(fdt_prop->len); |
304 | nodep = fdt_prop->data; |
305 | if (len < 0) { |
306 | printf ("libfdt fdt_getprop(): %s\n", |
307 | fdt_strerror(len)); |
308 | return 1; |
309 | } else if (len == 0) { |
310 | /* the property has no value */ |
311 | if (level <= depth) |
312 | ; |
313 | } else { |
314 | if (level <= depth) { |
315 | print_data (nodep, len, &index, flag); |
316 | } |
317 | } |
318 | break; |
319 | case FDT_NOP: |
320 | printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); |
321 | break; |
322 | case FDT_END: |
323 | return 1; |
324 | default: |
325 | if (level <= depth) |
326 | printf("Unknown tag 0x%08X\n", tag); |
327 | return 1; |
328 | } |
329 | nodeoffset = nextoffset; |
330 | } |
331 | |
332 | *partition_num = index; |
333 | return 0; |
334 | } |
335 | |
336 | unsigned char * |
337 | GetMultiDtbEntry(unsigned char *fdt_addr, int *plen){ |
338 | unsigned int dt_magic = STRTOU32(fdt_addr); |
339 | signed int dt_total = 0; |
340 | unsigned int dt_tool_version = 0; |
341 | |
342 | //printf(" Amlogic multi-dtb tool\n"); |
343 | if (dt_magic == DT_HEADER_MAGIC) {/*normal dtb*/ |
344 | printf(" Single dtb detected\n"); |
345 | return fdt_addr; |
346 | } |
347 | else if (dt_magic == AML_DT_HEADER_MAGIC) {/*multi dtb*/ |
348 | printf(" Multi dtb detected\n"); |
349 | /* check and set aml_dt */ |
350 | int i = 0; |
351 | char *aml_dt_buf; |
352 | aml_dt_buf = (char *)malloc(sizeof(char)*64); |
353 | memset(aml_dt_buf, 0, sizeof(aml_dt_buf)); |
354 | |
355 | GetDtbId(aml_dt_buf); |
356 | //printf("aml_dt_buf:%s\n", aml_dt_buf); |
357 | |
358 | unsigned int aml_dt_len = aml_dt_buf ? strlen(aml_dt_buf) : 0; |
359 | if (aml_dt_len <= 0) { |
360 | printf("Get env aml_dt failed!Ignore dtb check !\n"); |
361 | *plen = 0; |
362 | return fdt_addr; |
363 | } |
364 | |
365 | /*version control, compatible with v1*/ |
366 | dt_tool_version = STRTOU32(fdt_addr + AML_DT_VERSION_OFFSET); |
367 | unsigned int aml_each_id_length=0; |
368 | unsigned int aml_dtb_offset_offset; |
369 | unsigned int aml_dtb_header_size; |
370 | |
371 | if (dt_tool_version == 1) |
372 | aml_each_id_length = 4; |
373 | else if(dt_tool_version == 2) |
374 | aml_each_id_length = 16; |
375 | |
376 | aml_dtb_offset_offset = aml_each_id_length * AML_DT_ID_VARI_TOTAL; |
377 | aml_dtb_header_size = 8+(aml_each_id_length * AML_DT_ID_VARI_TOTAL); |
378 | //printf(" Multi dtb tool version: v%d .\n", dt_tool_version); |
379 | |
380 | /*fdt_addr + 0x8: num of dtbs*/ |
381 | dt_total = STRTOU32(fdt_addr + AML_DT_TOTAL_DTB_OFFSET); |
382 | //printf(" Support %d dtbs.\n", dt_total); |
383 | |
384 | /* split aml_dt to 3 strings */ |
385 | char *tokens[3] = {NULL, NULL, NULL}; |
386 | for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) { |
387 | tokens[i] = strsep(&aml_dt_buf, "_"); |
388 | } |
389 | |
390 | if (aml_dt_buf) |
391 | free(aml_dt_buf); |
392 | //printf(" aml_dt soc: %s platform: %s variant: %s\n", tokens[0], tokens[1], tokens[2]); |
393 | |
394 | /*match and print result*/ |
395 | char **dt_info; |
396 | dt_info = (char **)malloc(sizeof(char *)*AML_DT_ID_VARI_TOTAL); |
397 | for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) |
398 | dt_info[i] = (char *)malloc(sizeof(char)*aml_each_id_length); |
399 | |
400 | unsigned int dtb_match_num = 0xffff; |
401 | unsigned int x = 0, y = 0, z = 0; //loop counter |
402 | unsigned int read_data; |
403 | for (i = 0; i < dt_total; i++) { |
404 | for (x = 0; x < AML_DT_ID_VARI_TOTAL; x++) { |
405 | for (y = 0; y < aml_each_id_length; y+=4) { |
406 | read_data = STRTOU32(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \ |
407 | i * aml_dtb_header_size + AML_DT_DTB_DT_INFO_OFFSET + \ |
408 | (x * aml_each_id_length) + y); |
409 | dt_info[x][y+0] = (read_data >> 24) & 0xff; |
410 | dt_info[x][y+1] = (read_data >> 16) & 0xff; |
411 | dt_info[x][y+2] = (read_data >> 8) & 0xff; |
412 | dt_info[x][y+3] = (read_data >> 0) & 0xff; |
413 | } |
414 | |
415 | for (z=0; z<aml_each_id_length; z++) { |
416 | /*fix string with \0*/ |
417 | if (0x20 == (uint)dt_info[x][z]) { |
418 | dt_info[x][z] = '\0'; |
419 | } |
420 | } |
421 | } |
422 | |
423 | if (dt_tool_version == 1) |
424 | printf(" dtb %d soc: %.4s plat: %.4s vari: %.4s\n", i, (char *)(dt_info[0]), (char *)(dt_info[1]), (char *)(dt_info[2])); |
425 | else if(dt_tool_version == 2) |
426 | printf(" dtb %d soc: %.16s plat: %.16s vari: %.16s\n", i, (char *)(dt_info[0]), (char *)(dt_info[1]), (char *)(dt_info[2])); |
427 | uint match_str_counter = 0; |
428 | |
429 | for (z=0; z<AML_DT_ID_VARI_TOTAL; z++) { |
430 | /*must match 3 strings*/ |
431 | if (!strncmp(tokens[z], (char *)(dt_info[z]), strlen(tokens[z])) && \ |
432 | (strlen(tokens[z]) == strlen(dt_info[z]))) |
433 | match_str_counter++; |
434 | } |
435 | |
436 | if (match_str_counter == AML_DT_ID_VARI_TOTAL) { |
437 | //printf("Find match dtb\n"); |
438 | dtb_match_num = i; |
439 | } |
440 | |
441 | for (z=0; z<AML_DT_ID_VARI_TOTAL; z++) { |
442 | /*clear data for next loop*/ |
443 | memset(dt_info[z], 0, sizeof(aml_each_id_length)); |
444 | } |
445 | } |
446 | |
447 | /*clean malloc memory*/ |
448 | for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) { |
449 | if (dt_info[i]) |
450 | free(dt_info[i]); |
451 | } |
452 | |
453 | if (dt_info) |
454 | free(dt_info); |
455 | |
456 | /*if find match dtb, return address, or else return main entrance address*/ |
457 | if (0xffff != dtb_match_num) { |
458 | printf(" Find match dtb: %d\n", dtb_match_num); |
459 | /*this offset is based on dtb image package, so should add on base address*/ |
460 | *plen = STRTOU32(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \ |
461 | dtb_match_num * aml_dtb_header_size + aml_dtb_offset_offset+4); |
462 | return fdt_addr + STRTOU32(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \ |
463 | dtb_match_num * aml_dtb_header_size + aml_dtb_offset_offset); |
464 | } else { |
465 | printf(" Not match any dtb.\n"); |
466 | return NULL; |
467 | } |
468 | } else { |
469 | printf(" Cannot find legal dtb!\n"); |
470 | return NULL; |
471 | } |
472 | |
473 | return NULL; |
474 | } |
475 | |
476 | |
477 | /** |
478 | * --- get upgrade package image data |
479 | * |
480 | * @zipArchive: zip archive object |
481 | * @imageName: upgrade package image's name |
482 | * @imageSize: upgrade package image's size |
483 | * |
484 | * return value: |
485 | * <0: failed |
486 | * =0: can't find image |
487 | * >0: get image data successful |
488 | */ |
489 | static unsigned char *s_pDtbBuffer = NULL; |
490 | static int |
491 | GetZipDtbImage(const ZipArchiveHandle za, const char *imageName, int *imageSize){ |
492 | int len = 0; |
493 | int ret = 0; |
494 | unsigned char *paddr = NULL; |
495 | |
496 | ZipString zip_path(imageName); |
497 | ZipEntry entry; |
498 | if (FindEntry(za, zip_path, &entry) != 0) { |
499 | printf("no %s in package!\n", imageName); |
500 | return 0; |
501 | } |
502 | |
503 | *imageSize = entry.uncompressed_length; |
504 | if (*imageSize <= 0) { |
505 | printf("can't get package entry uncomp len(%d) (%s)\n",*imageSize, strerror(errno)); |
506 | return -1; |
507 | } |
508 | |
509 | len = *imageSize; |
510 | |
511 | unsigned char* buffer = (unsigned char *)calloc(len, sizeof(unsigned char)); |
512 | if (!buffer) { |
513 | printf("can't malloc %d size space (%s)\n",len, strerror(errno)); |
514 | return -1; |
515 | } |
516 | |
517 | ret = ExtractToMemory(za, &entry, buffer, entry.uncompressed_length); |
518 | if (ret != 0) { |
519 | printf("can't extract package entry to image buffer\n"); |
520 | free(buffer); |
521 | return -1; |
522 | } |
523 | |
524 | |
525 | if (isEncrypted == 1) { |
526 | ret = DtbImgEncrypted(DTB_IMG, buffer, len, "1", buffer); |
527 | if (ret == 2) { |
528 | printf("no decrypt_dtb and no support!"); |
529 | free(buffer); |
530 | return 2; |
531 | }else if (ret <= 0) { |
532 | printf("dtb.img encrypt from zip failed!\n"); |
533 | free(buffer); |
534 | return -1; |
535 | } |
536 | } |
537 | |
538 | paddr = GetMultiDtbEntry(buffer, &len); |
539 | if (paddr == NULL) |
540 | { |
541 | printf("Cannot find legal dtb from zip \n"); |
542 | free(buffer); |
543 | return -1; |
544 | } else if (len == 0) { |
545 | printf("No need to check dtb \n"); |
546 | free(buffer); |
547 | return 2; |
548 | } |
549 | |
550 | if (s_pDtbBuffer != NULL) { |
551 | free(s_pDtbBuffer); |
552 | s_pDtbBuffer = NULL; |
553 | } |
554 | |
555 | s_pDtbBuffer = (unsigned char *)calloc(len, sizeof(unsigned char)); |
556 | if (!s_pDtbBuffer) { |
557 | printf("can't malloc %d size space (%s)\n",len, strerror(errno)); |
558 | free(buffer); |
559 | return -1; |
560 | } |
561 | |
562 | memcpy(s_pDtbBuffer, paddr, len); |
563 | free(buffer); |
564 | |
565 | return 1; |
566 | } |
567 | |
568 | static int |
569 | GetDevDtbImage(){ |
570 | int fd = 0; |
571 | int len = 0; |
572 | int ret = 0; |
573 | unsigned char *paddr = NULL; |
574 | const char *DTB_DEV= "/dev/dtb"; |
575 | const int DTB_DATA_MAX = 256*1024; |
576 | |
577 | unsigned char* buffer = (unsigned char *)calloc(DTB_DATA_MAX+256, sizeof(unsigned char)); |
578 | if (buffer == NULL) { |
579 | printf("malloc %d failed!\n", DTB_DATA_MAX+256); |
580 | return -1; |
581 | } |
582 | |
583 | fd = open(DTB_DEV, O_RDONLY); |
584 | if (fd < 0) { |
585 | printf("open %s failed!\n", DTB_DEV); |
586 | free(buffer); |
587 | return -1; |
588 | } |
589 | |
590 | len = read(fd, buffer, DTB_DATA_MAX); |
591 | if (len < 0) { |
592 | printf("read failed len = %d\n", len); |
593 | close(fd); |
594 | free(buffer); |
595 | return -1; |
596 | } |
597 | |
598 | close(fd); |
599 | |
600 | if (isEncrypted == 1) { |
601 | ret = DtbImgEncrypted(DTB_IMG, buffer, len, "1", buffer); |
602 | if (ret <= 0) { |
603 | printf("dtb.img encrypt from dev failed!\n"); |
604 | free(buffer); |
605 | return -1; |
606 | } |
607 | } |
608 | paddr = GetMultiDtbEntry(buffer, &len); |
609 | if (paddr == NULL) { |
610 | printf("Cannot find legal dtb from dev block \n"); |
611 | free(buffer); |
612 | return -1; |
613 | } |
614 | |
615 | if (s_pDtbBuffer != NULL) { |
616 | free(s_pDtbBuffer); |
617 | s_pDtbBuffer = NULL; |
618 | } |
619 | |
620 | s_pDtbBuffer = (unsigned char *)calloc(len, sizeof(unsigned char)); |
621 | if (s_pDtbBuffer == NULL) { |
622 | printf("malloc %d failed!\n", len); |
623 | free(buffer); |
624 | return -1; |
625 | } |
626 | |
627 | memcpy(s_pDtbBuffer, paddr, len); |
628 | free(buffer); |
629 | |
630 | return 0; |
631 | } |
632 | |
633 | int |
634 | GetEnvPartitionOffset(const ZipArchiveHandle za) { |
635 | int i = 0; |
636 | int find = 0; |
637 | int ret = -1; |
638 | int offset = 116*1024*1024; //bootloader(4M) GAP(32M) reserved(64M) GAP(8M) cache(--) GAP(8M) |
639 | int imageSize = 0; |
640 | int partition_num_zip = 0; |
641 | |
642 | ret = GetZipDtbImage(za, DTB_IMG, &imageSize); |
643 | if ((ret == 0) || (ret == 2)) { |
644 | printf("no dtb.img in the update or no need check dtb, check dtb over!\n"); |
645 | return 0; |
646 | } else if (ret < 0) { |
647 | printf("get dtb.img from update.zip failed!\n"); |
648 | ret = -1; |
649 | goto END; |
650 | } |
651 | |
652 | working_fdt = (struct fdt_header *)s_pDtbBuffer; |
653 | |
654 | ret = GetPartitionFromDtb("/partitions", MAX_LEVEL, &partition_num_zip, 0); |
655 | if (ret != 0) { |
656 | printf("get partition map from dtb.img failed!\n"); |
657 | ret = -1; |
658 | goto END; |
659 | } |
660 | |
661 | for (i=0; i<partition_num_zip;i++) { |
662 | printf("%s:0x%08x\n", dtb_zip[i].partition_name, dtb_zip[i].partition_size); |
663 | if (!strcmp("cache", dtb_zip[i].partition_name)) { |
664 | offset += dtb_zip[i].partition_size; |
665 | find = 1; |
666 | } |
667 | } |
668 | |
669 | if (find == 0) { |
670 | printf("get cache partition size from dtb.img failed!\n"); |
671 | ret = -1; |
672 | goto END; |
673 | } |
674 | printf("env partition offset:0x%08x\n", offset); |
675 | |
676 | ret = offset; |
677 | |
678 | END: |
679 | if (s_pDtbBuffer != NULL) |
680 | { |
681 | free(s_pDtbBuffer); |
682 | s_pDtbBuffer = NULL; |
683 | } |
684 | |
685 | return ret; |
686 | } |
687 | |
688 | int |
689 | RecoveryDtbCheck(const ZipArchiveHandle za){ |
690 | int i = 0, ret = -1, err = -1; |
691 | int fd = -1; |
692 | int partition_num_zip = 0; |
693 | int partition_num_dev = 0; |
694 | int imageSize = 0; |
695 | int recovery_dev = 0, recovery_zip = 0; |
696 | int data_dev = 0, data_zip = 0; |
697 | int recovery_offset_dev = 0, recovery_offset_zip = 0; |
698 | int data_offset_dev = 0, data_offset_zip = 0; |
699 | int device_type = 0; |
700 | int partition_num; |
701 | int cache_offset_dev = 0, cache_offset_zip = 0; |
702 | int recovery_size_dev = 0, recovery_size_zip = 0; |
703 | int cache_size_dev = 0, cache_size_zip = 0; |
704 | |
705 | isEncrypted = IsPlatformEncrypted(); |
706 | if (isEncrypted == 2) { |
707 | printf("kernel doesn't support!\n"); |
708 | return 0; |
709 | } else if (isEncrypted < 0) { |
710 | return -1; |
711 | } |
712 | |
713 | ret = GetZipDtbImage(za, DTB_IMG, &imageSize); |
714 | if ((ret == 0) || (ret == 2)) { |
715 | printf("no dtb.img in the update or no need check dtb, check dtb over!\n"); |
716 | return 0; |
717 | } else if (ret < 0) { |
718 | printf("get dtb.img from update.zip failed!\n"); |
719 | ret = -1; |
720 | goto END; |
721 | } |
722 | |
723 | working_fdt = (struct fdt_header *)s_pDtbBuffer; |
724 | |
725 | ret = GetPartitionFromDtb("/partitions", MAX_LEVEL, &partition_num_zip, 0); |
726 | if (ret != 0) { |
727 | printf("get partition map from dtb.img failed!\n"); |
728 | ret = -1; |
729 | goto END; |
730 | } |
731 | |
732 | ret = GetDevDtbImage(); |
733 | if (ret != 0) { |
734 | printf("read dtb from /dev/dtb failed!\n"); |
735 | ret = -1; |
736 | goto END; |
737 | } |
738 | |
739 | working_fdt = (struct fdt_header *)s_pDtbBuffer; |
740 | ret = GetPartitionFromDtb("/partitions", MAX_LEVEL, &partition_num_dev, 1); |
741 | if (ret != 0) { |
742 | printf("get partition map from /dev/dtb failed!\n"); |
743 | ret = -1; |
744 | goto END; |
745 | } |
746 | |
747 | partition_num = partition_num_dev; |
748 | device_type = GetDeviceType(); |
749 | printf("device_type = %d \n",device_type); |
750 | |
751 | if (partition_num_zip != partition_num_dev) { |
752 | printf("partition num don't match zip:%d, dev:%d\n",partition_num_zip, partition_num_dev); |
753 | if (device_type == DEVICE_NAND) { |
754 | printf("the partitions changed & device is nand! can not upgrade!\n "); |
755 | ret = -1; |
756 | goto END; |
757 | } |
758 | #ifdef SUPPORT_PARTNUM_CHANGE |
759 | ret = 2; |
760 | partition_num = partition_num_zip > partition_num_dev ? partition_num_zip : partition_num_dev; |
761 | #else |
762 | printf("partition num don't match zip:%d, dev:%d, can not upgrade!\n",partition_num_zip, partition_num_dev); |
763 | ret = -1; |
764 | goto END; |
765 | #endif |
766 | } |
767 | printf("partition_num = %d \n",partition_num); |
768 | |
769 | for (i=0; i<partition_num;i++) { |
770 | printf("%s:0x%08x\n", dtb_zip[i].partition_name, dtb_zip[i].partition_size); |
771 | printf("%s:0x%08x\n", dtb_dev[i].partition_name, dtb_dev[i].partition_size); |
772 | |
773 | if (!strcmp("recovery", dtb_dev[i].partition_name)) { |
774 | recovery_size1 = dtb_zip[i].partition_size; |
775 | recovery_dev = i; |
776 | recovery_size_dev = dtb_dev[i].partition_size; |
777 | } |
778 | if (!strcmp("recovery", dtb_zip[i].partition_name)) { |
779 | recovery_zip = i; |
780 | recovery_size_zip = dtb_zip[i].partition_size; |
781 | } |
782 | |
783 | if (!strcmp("data", dtb_dev[i].partition_name)) { |
784 | data_dev = i; |
785 | } |
786 | if (!strcmp("data", dtb_zip[i].partition_name)) { |
787 | data_zip = i; |
788 | } |
789 | |
790 | if (!strcmp("cache", dtb_dev[i].partition_name)) { |
791 | cache_size_dev = dtb_dev[i].partition_size; |
792 | } |
793 | if (!strcmp("cache", dtb_zip[i].partition_name)) { |
794 | cache_size_zip = dtb_zip[i].partition_size; |
795 | } |
796 | |
797 | if ((strcmp(dtb_zip[i].partition_name, dtb_dev[i].partition_name) != 0)|| |
798 | (dtb_zip[i].partition_size != dtb_dev[i].partition_size)) { |
799 | ret = 2; |
800 | /*just emmc support partition changes*/ |
801 | if (device_type == DEVICE_NAND) { |
802 | printf("the partitions changed & device is nand! can not upgrade!\n "); |
803 | ret = -1; |
804 | goto END; |
805 | } |
806 | } |
807 | } |
808 | |
809 | /*the offset of recovery/data cannot be changed*/ |
810 | for (i=0;i<recovery_dev;i++) { |
811 | recovery_offset_dev += dtb_dev[i].partition_size; |
812 | } |
813 | for (i=0;i<recovery_zip;i++) { |
814 | recovery_offset_zip += dtb_zip[i].partition_size; |
815 | } |
816 | for (i=0;i<data_dev;i++) { |
817 | data_offset_dev += dtb_dev[i].partition_size; |
818 | } |
819 | for (i=0;i<data_zip;i++) { |
820 | data_offset_zip += dtb_zip[i].partition_size; |
821 | } |
822 | |
823 | for (i=0;i<2;i++) { |
824 | cache_offset_dev += dtb_dev[i].partition_size; |
825 | cache_offset_zip += dtb_zip[i].partition_size; |
826 | } |
827 | |
828 | printf("recovery_dev: %d recovery_offset_dev :0x%08x\n", recovery_dev, recovery_offset_dev); |
829 | printf("recovery_zip: %d recovery_offset_zip :0x%08x\n", recovery_zip, recovery_offset_zip); |
830 | printf("data_dev: %d data_offset_dev :0x%08x\n", data_dev, data_offset_dev); |
831 | printf("data_zip: %d data_offset_zip :0x%08x\n", data_zip, data_offset_zip); |
832 | printf("cache_offset_dev :0x%08x, cache_size_dev: %d\n", cache_offset_dev, cache_size_dev); |
833 | printf("cache_offset_zip :0x%08x, cache_size_zip: %d\n", cache_offset_zip, cache_size_zip); |
834 | |
835 | if (data_offset_dev != data_offset_zip) { |
836 | printf("data changed, need wipe_data\n "); |
837 | ret = 3; |
838 | } |
839 | |
840 | if ((recovery_offset_dev != recovery_offset_zip) || (recovery_size_dev != recovery_size_zip)) { |
841 | printf("recovery part changed! can not upgrade!\n "); |
842 | ret = -1; |
843 | goto END; |
844 | } |
845 | |
846 | if ((cache_offset_dev != cache_offset_zip) || (cache_size_dev != cache_size_zip)) { |
847 | printf("cache part changed! can not upgrade!\n "); |
848 | ret = -1; |
849 | goto END; |
850 | } |
851 | |
852 | END: |
853 | if (s_pDtbBuffer != NULL) |
854 | { |
855 | free(s_pDtbBuffer); |
856 | s_pDtbBuffer = NULL; |
857 | } |
858 | |
859 | return ret; |
860 | } |
861 |