blob: 43a51a2dcb227132cab5fa768fbb26d2abcc51d4 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <bootm.h>
8#include <command.h>
9#include <image.h>
10#include <malloc.h>
Bo Lv52186632024-02-22 16:32:44 +080011#include <linux/sizes.h>
Bo Lv72d0e902023-01-02 14:27:34 +000012#include <asm/amlogic/arch/io.h>
13#include <asm/amlogic/arch/secure_apb.h>
14#include <amlogic/partition_table.h>
15#include <bzlib.h>
16#include <gzip.h>
17
18//#define AML_DT_DEBUG
19#ifdef AML_DT_DEBUG
20#define dbg_printf(...) printf(__VA_ARGS__)
21#else
22#define dbg_printf(...) ((void)0)
23#endif
24
25#define AML_MULTI_DTB_API_NEW
26//#define AML_MULTI_DTB_CHECK_CMD //command for multi-dtb test
27
28#ifdef AML_MULTI_DTB_API_NEW
29
30/*for multi-dtb gzip buffer*/
31#define GUNZIP_BUF_SIZE BIT(20) /*1MB is enough?*/
32#define BZIP2_BUF_SIZE BIT(23) /*8MB is enough?*/
33
34/*magic for multi-dtb*/
35#define MAGIC_GZIP_MASK (0x0000FFFF)
36#define MAGIC_GZIP_ID (0x00008B1F)
37#define MAGIC_BZIP2_ID (0x00005a42)
38#define IS_GZIP_PACKED(nMagic) (MAGIC_GZIP_ID == (MAGIC_GZIP_MASK & nMagic))
39#define IS_BZIP2_PACKED(nMagic) (MAGIC_BZIP2_ID == (MAGIC_BZIP2_ID & (nMagic)))
40#define MAGIC_DTB_SGL_ID (0xedfe0dd0)
41#define MAGIC_DTB_MLT_ID (0x5f4c4d41)
42
43/*amlogic multi-dtb version*/
44#define AML_MUL_DTB_VER_1 (1)
45#define AML_MUL_DTB_VER_2 (2)
46
47/*max char for dtb name, fixed to soc_package_board format*/
48#define AML_MAX_DTB_NAME_SIZE (128)
49#define AML_DTB_TOKEN_MAX_COUNT (AML_MAX_DTB_NAME_SIZE>>1)
50
Bo Lv52186632024-02-22 16:32:44 +080051#define MAX_DTB_SIZE SZ_1M
52#define MAX_DTB_COUNT 16
53
Bo Lv72d0e902023-01-02 14:27:34 +000054typedef struct{
55 unsigned int nMagic;
56 unsigned int nVersion;
57 unsigned int nDTBCount;
58}st_dtb_hdr_t,*p_st_dtb_hdr_t;
59
60/*v1,v2 multi-dtb only support max to 3 tokens for each DTB name*/
61#define MULTI_DTB_TOKEN_MAX_COUNT (3)
62#define MULTI_DTB_TOKEN_UNIT_SIZE_V1 (4) //v1 support 4bytes for each token
63#define MULTI_DTB_TOKEN_UNIT_SIZE_V2 (16) //v2 support 16bytes for each token
64
65/*v1 multi-dtb*/
66typedef struct{
67 unsigned char szToken[MULTI_DTB_TOKEN_MAX_COUNT][MULTI_DTB_TOKEN_UNIT_SIZE_V1];
Bo Lv52186632024-02-22 16:32:44 +080068 unsigned int nDTBOffset;
69 unsigned int nDTBIMGSize;
Bo Lv72d0e902023-01-02 14:27:34 +000070}st_dtb_token_v1_t,*p_st_dtb_token_v1_t;
71
72typedef struct{
73 st_dtb_hdr_t hdr;
74 st_dtb_token_v1_t dtb[1];
75}st_dtb_v1_t,*p_st_dtb_v1_t;
76
77
78/*v2 multi-dtb*/
79typedef struct{
80 unsigned char szToken[MULTI_DTB_TOKEN_MAX_COUNT][MULTI_DTB_TOKEN_UNIT_SIZE_V2];
Bo Lv52186632024-02-22 16:32:44 +080081 unsigned int nDTBOffset;
82 unsigned int nDTBIMGSize;
Bo Lv72d0e902023-01-02 14:27:34 +000083}st_dtb_token_v2_t,*p_st_dtb_token_v2_t;
84
85typedef struct{
86 st_dtb_hdr_t hdr;
87 st_dtb_token_v2_t dtb[1];
88}st_dtb_v2_t,*p_st_dtb_v2_t;
89
90
91/*to get the valid DTB index with matched DTB name*/
92static int get_dtb_index(const char aml_dt_buf[128],unsigned long fdt_addr)
93{
94 int nReturn = -1;
95
96 if (aml_dt_buf) {
97 p_st_dtb_hdr_t pDTBHdr = (p_st_dtb_hdr_t)fdt_addr;
98 char sz_aml_dt_msb[10][MULTI_DTB_TOKEN_UNIT_SIZE_V2];
99
100 memset(sz_aml_dt_msb, 0, sizeof(sz_aml_dt_msb));
101
102 /* split aml_dt with token '_', e.g "tm2-revb_t962x3_ab301" */
103 //printf(" aml_dt : %s\n",aml_dt_buf);
104
105 char *tokens[AML_DTB_TOKEN_MAX_COUNT];
106 char sz_temp[AML_MAX_DTB_NAME_SIZE + 4];
107
108 memset(tokens, 0, sizeof(tokens));
109 memset(sz_temp, 0, sizeof(sz_temp));
110 strncpy(sz_temp, aml_dt_buf, 128);
111
112 int i, j;
113 int nLen = strlen(sz_temp);
114
115 sz_temp[nLen] = '_';
116 sz_temp[nLen + 1] = '\0';
117 nLen += 1;
118 tokens[0] = sz_temp;
119 for (i = 1; i < sizeof(tokens) / sizeof(tokens[0]); i++) {
120 tokens[i] = strstr(tokens[i - 1], "_");
121 if (!tokens[i])
122 break;
123
124 *tokens[i] = '\0';
125
126 tokens[i] = tokens[i] + 1;
127
128 if (!(*tokens[i])) {
129 tokens[i] = 0;
130 break;
131 }
132 }
133
134 //for (i=0;i<10 && tokens[i];++i)
135 // printf("token-%d:%s\n",i,tokens[i]);
136
137 int nTokenLen = 0, nDtbcnt = 0;
138
139 switch (pDTBHdr->nVersion) {
140 case AML_MUL_DTB_VER_1: {
141 nTokenLen = MULTI_DTB_TOKEN_UNIT_SIZE_V1;
142 } break;
143 case AML_MUL_DTB_VER_2: {
144 nTokenLen = MULTI_DTB_TOKEN_UNIT_SIZE_V2;
145 } break;
146 default: {
147 goto exit; break;
148 }
149 }
150
151 for (i = 0; i < MULTI_DTB_TOKEN_MAX_COUNT; ++i) {
152 if (tokens[i]) {
153 char *pbyswap = (char *)sz_aml_dt_msb + (nTokenLen * i);
154 unsigned int nValSwap;
155 int m;
156
157 strcpy(pbyswap, tokens[i]);
158 for (j = 0; j < nTokenLen; j += 4) {
159 /*swap byte order with unit@4bytes*/
160 nValSwap = *(unsigned int *)(pbyswap + j);
161 for (m = 0; m < 4; m++) {
162 pbyswap[j + m] = ((nValSwap >>
163 ((3 - m) << 3)) & 0xFF);
164 }
165
166 /*replace 0 with 0x20*/
167 for (m = 0 ; m < MULTI_DTB_TOKEN_UNIT_SIZE_V2; ++m)
168 //if (pbyswap[m] == 0)
169 // pbyswap[m] = 0x20;
170 /* avoid coverity */
171 pbyswap[m] == 0 ? pbyswap[m] = 0x20 : 0;
172 }
173 } else {
174 break;
175 }
176 }
177
178 switch (pDTBHdr->nVersion) {
179 case AML_MUL_DTB_VER_1: {
180 p_st_dtb_v1_t pDTB_V1 = (p_st_dtb_v1_t)fdt_addr;
181
182 nDtbcnt = pDTB_V1->hdr.nDTBCount;
183 for (i = 0; i < pDTB_V1->hdr.nDTBCount; ++i) {
184 if (!memcmp(pDTB_V1->dtb[i].szToken, sz_aml_dt_msb,
185 MULTI_DTB_TOKEN_MAX_COUNT * nTokenLen)) {
186 nReturn = i;
187 break;
188 }
189 }
190
191 } break;
192 case AML_MUL_DTB_VER_2: {
193 p_st_dtb_v2_t pDTB_V2 = (p_st_dtb_v2_t)fdt_addr;
194
195 nDtbcnt = pDTB_V2->hdr.nDTBCount;
196 for (i = 0; i < pDTB_V2->hdr.nDTBCount; ++i) {
197 if (!memcmp(pDTB_V2->dtb[i].szToken, sz_aml_dt_msb,
198 MULTI_DTB_TOKEN_MAX_COUNT * nTokenLen)) {
199 nReturn = i;
200 break;
201 }
202 }
203
204 } break;
205 default: {
206 goto exit; break;
207 }
208 }
209
210 /* print dtb */
211 char **dt_name;
212 unsigned int x = 0, y = 0, z = 0; //loop counter
213 unsigned int nDtbSwap;
214 unsigned int aml_dtb_header_size = 8 + (nTokenLen * 3);
215
216 dt_name = (char **)malloc(sizeof(char *) * MULTI_DTB_TOKEN_MAX_COUNT);
217 for (i = 0; i < MULTI_DTB_TOKEN_MAX_COUNT; i++)
218 dt_name[i] = (char *)malloc(sizeof(char) * nTokenLen);
219
220 for (i = 0; i < nDtbcnt; i++) {
221 for (x = 0; x < MULTI_DTB_TOKEN_MAX_COUNT; x++) {
222 for (y = 0; y < nTokenLen; y += 4) {
223 nDtbSwap = *(unsigned int *)(fdt_addr + 12 +
224 i * aml_dtb_header_size +
225 0 + (x * nTokenLen) + y);
226 for (z = 0; z < 4; z++)
227 dt_name[x][y + z] = (nDtbSwap >>
228 ((3 - z) << 3)) & 0xFF;
229 /*replace 0 with 0x20*/
230 for (z = 0; z < nTokenLen; z++)
231 //if (dt_name[x][z] == 0x20)
232 // dt_name[x][z] = '\0';
233 /* avoid coverity */
234 dt_name[x][z] == 0x20 ? dt_name[x][z] = '\0' : 0;
235 }
236 }
237 if (pDTBHdr->nVersion == 1)
238 printf(" dtb %d soc: %.4s plat: %.4s vari: %.4s\n",
239 i, (char *)(dt_name[0]), (char *)(dt_name[1]),
240 (char *)(dt_name[2]));
241 else if (pDTBHdr->nVersion == 2)
242 printf(" dtb %d soc: %.16s plat: %.16s vari: %.16s\n",
243 i, (char *)(dt_name[0]), (char *)(dt_name[1]),
244 (char *)(dt_name[2]));
245 }
246 if (dt_name)
247 free(dt_name);
248 } else {
249 goto exit;
250 }
251
252exit:
253
254 return nReturn;
255
256}
257
258unsigned long __attribute__((unused)) get_multi_dt_entry(unsigned long fdt_addr)
259{
260 unsigned long lReturn = 0; //return buffer for valid DTB;
261 void * gzip_buf = NULL;
262 unsigned long pInputFDT = fdt_addr;
263 p_st_dtb_hdr_t pDTBHdr = (p_st_dtb_hdr_t)pInputFDT;
264 unsigned long unzip_size = GUNZIP_BUF_SIZE;
265 unsigned int src_len = BZIP2_BUF_SIZE;
266 unsigned int dest_len = BZIP2_BUF_SIZE;
267
268 printf(" Amlogic Multi-DTB tool\n");
269
270 /* first check the blob header, support GZIP format */
271 if ( IS_GZIP_PACKED(pDTBHdr->nMagic))
272 {
273 printf(" GZIP format, decompress...\n");
274 gzip_buf = malloc(GUNZIP_BUF_SIZE);
275 if (!gzip_buf)
276 {
277 printf(" ERROR! fail to allocate memory for GUNZIP...\n");
278 goto exit;
279 }
280 memset(gzip_buf, 0, GUNZIP_BUF_SIZE);
281 if (gunzip(gzip_buf, GUNZIP_BUF_SIZE, (void *)pInputFDT, &unzip_size) < 0)
282 {
283 printf(" ERROR! GUNZIP process fail...\n");
284 goto exit;
285 }
286 if (unzip_size > GUNZIP_BUF_SIZE)
287 {
288 printf(" ERROR! GUNZIP overflow...\n");
289 goto exit;
290 }
291 //memcpy((void*)fdt_addr,gzip_buf,unzip_size);
292 pInputFDT = (unsigned long)gzip_buf;
293 pDTBHdr = (p_st_dtb_hdr_t)pInputFDT;
294 } else if (IS_BZIP2_PACKED(pDTBHdr->nMagic)) {
295 printf(" BZIP2 format, decompress...\n");
296 /*
297 * If we've got less than 4 MB of malloc() space,
298 * use slower decompression algorithm which requires
299 * at most 2300 KB of memory.
300 */
301 gzip_buf = malloc(BZIP2_BUF_SIZE);
302 if (!gzip_buf) {
303 printf(" ERROR! fail to allocate memory for GUNZIP...\n");
304 goto exit;
305 }
306 memset(gzip_buf, 0, BZIP2_BUF_SIZE);
307 int ret = BZ2_bzBuffToBuffDecompress(gzip_buf, &dest_len,
308 (void *)pInputFDT, src_len,
309 1, 2);
310 if (ret != BZ_OK) {
311 printf("BZIP2: uncompress or overwrite error %d must RESET board\n", ret);
312 goto exit;
313 } else {
314 pInputFDT = (unsigned long)gzip_buf;
315 pDTBHdr = (p_st_dtb_hdr_t)pInputFDT;
316 unzip_size = dest_len;
317 }
318 }
319
320 switch (pDTBHdr->nMagic)
321 {
322 case MAGIC_DTB_SGL_ID:
323 {
324 printf(" Single DTB detected\n");
325
326 if (fdt_addr != (unsigned long)pInputFDT) //in case of GZIP single DTB
327 memcpy((void*)fdt_addr,(void*)pInputFDT,unzip_size);
328
329 lReturn = fdt_addr;
330
331 }break;
332 case MAGIC_DTB_MLT_ID:
333 {
334 printf(" Multi DTB detected.\n");
335 printf(" Multi DTB tool version: v%d.\n", pDTBHdr->nVersion);
336 printf(" Found %d DTBS.\n", pDTBHdr->nDTBCount);
337
338
339 /* check and set aml_dt */
340 char aml_dt_buf[AML_MAX_DTB_NAME_SIZE+4];
341 memset(aml_dt_buf, 0, sizeof(aml_dt_buf));
342
343 /* update 2016.07.27, checkhw and setenv everytime,
344 or else aml_dt will set only once if it is reserved */
345 extern int checkhw(char * name);
346#if 1
347 if (checkhw(aml_dt_buf) < 0 || strlen(aml_dt_buf) <= 0)
348 {
349 printf(" Get env aml_dt failed!\n");
350 goto exit;
351 }
352#else
353 char *aml_dt = getenv(AML_DT_UBOOT_ENV);
354 /* if aml_dt not exist or env not ready, get correct dtb by name */
355 if (NULL == aml_dt)
356 checkhw(aml_dt_buf);
357 else
358 memcpy(aml_dt_buf, aml_dt,
359 (strlen(aml_dt)>AML_MAX_DTB_NAME_SIZE?AML_MAX_DTB_NAME_SIZE:(strlen(aml_dt)+1)));
360#endif
361
362 int dtb_match_num = get_dtb_index(aml_dt_buf,(unsigned long)pInputFDT);
363
364 /*check valid dtb index*/
365 if (dtb_match_num < 0 || dtb_match_num >= pDTBHdr->nDTBCount)
366 {
367 printf(" NOT found matched DTB for \"%s\"\n",aml_dt_buf);
368 goto exit;
369 }
370
371 printf(" Matched DTB for \"%s\"\n",aml_dt_buf);
372
373 switch (pDTBHdr->nVersion)
374 {
375 case AML_MUL_DTB_VER_1:
376 {
377 p_st_dtb_v1_t pDTB_V1 = (p_st_dtb_v1_t)pInputFDT;
Bo Lv52186632024-02-22 16:32:44 +0800378
379 if (pDTB_V1->hdr.nDTBCount > MAX_DTB_COUNT) {
380 printf("Wrong dtb cnt1:%d\n", pDTB_V1->hdr.nDTBCount);
381 goto exit;
382 }
383
384 if ((pDTB_V1->dtb[dtb_match_num].nDTBIMGSize > MAX_DTB_SIZE) ||
385 pDTB_V1->dtb[dtb_match_num].nDTBOffset >= MAX_DTB_SIZE * (pDTBHdr->nDTBCount)) {
386 printf("%s, ERROR dtb size:%d or offset:%d\n",
387 __func__,
388 pDTB_V1->dtb[dtb_match_num].nDTBIMGSize,
389 pDTB_V1->dtb[dtb_match_num].nDTBOffset);
390 goto exit;
391 }
392
Bo Lv72d0e902023-01-02 14:27:34 +0000393 lReturn = pDTB_V1->dtb[dtb_match_num].nDTBOffset + pInputFDT;
394
395 //if (pInputFDT != fdt_addr)
396 {
397 memcpy((void*)fdt_addr, (void*)lReturn,pDTB_V1->dtb[dtb_match_num].nDTBIMGSize);
398 lReturn = fdt_addr;
399 }
400
401 }break;
402 case AML_MUL_DTB_VER_2:
403 {
404 p_st_dtb_v2_t pDTB_V2 = (p_st_dtb_v2_t)pInputFDT;
Bo Lv52186632024-02-22 16:32:44 +0800405
406 if (pDTB_V2->hdr.nDTBCount > MAX_DTB_COUNT) {
407 printf("Wrong dtb cnt2:%d\n", pDTB_V2->hdr.nDTBCount);
408 goto exit;
409 }
410
411 if ((pDTB_V2->dtb[dtb_match_num].nDTBIMGSize > MAX_DTB_SIZE) ||
412 pDTB_V2->dtb[dtb_match_num].nDTBOffset >= MAX_DTB_SIZE * (pDTBHdr->nDTBCount)) {
413 printf("%s v2, ERROR dtb size:%d or offset:%d\n",
414 __func__,
415 pDTB_V2->dtb[dtb_match_num].nDTBIMGSize,
416 pDTB_V2->dtb[dtb_match_num].nDTBOffset);
417 goto exit;
418 }
419
Bo Lv72d0e902023-01-02 14:27:34 +0000420 lReturn = pDTB_V2->dtb[dtb_match_num].nDTBOffset + pInputFDT;
421
422 //if (pInputFDT != fdt_addr)
423 {
424 memcpy((void*)fdt_addr, (void*)lReturn,pDTB_V2->dtb[dtb_match_num].nDTBIMGSize);
425 lReturn = fdt_addr;
426 }
427
428 }break;
429 default:
430 {
431 printf(" Invalid Multi-DTB Version [%d]!\n",
432 pDTBHdr->nVersion);
433 goto exit;
434 }break;
435 }
436
437 }break;
438 default: goto exit; break;
439 }
440
441exit:
442
443 if (gzip_buf)
444 {
445 free(gzip_buf);
446 gzip_buf = 0;
447 }
448
449 return lReturn;
450}
451
452#else //#ifdef AML_MULTI_DTB_API_NEW
453
454#define AML_DT_IND_LENGTH_V1 4 /*fixed*/
455#define AML_DT_IND_LENGTH_V2 16 /*fixed*/
456
457#define AML_DT_IND_LENGTH 16
458#define AML_DT_ID_VARI_TOTAL 3 //Total 3 strings
459#define AML_DT_EACH_ID_INT (AML_DT_IND_LENGTH / 4)
460
461/*Latest version: v2*/
462#define AML_DT_VERSION_OFFSET 4
463#define AML_DT_TOTAL_DTB_OFFSET 8
464#define AML_DT_FIRST_DTB_OFFSET 12
465//#define AML_DT_DTB_HEADER_SIZE (8+(AML_DT_IND_LENGTH * AML_DT_ID_VARI_TOTAL))
466#define AML_DT_DTB_DT_INFO_OFFSET 0
467//#define AML_DT_DTB_OFFSET_OFFSET (AML_DT_IND_LENGTH * AML_DT_ID_VARI_TOTAL)
468//#define AML_DT_DTB_SIZE_OFFSET 16
469
470#define AML_DT_UBOOT_ENV "aml_dt"
471#define DT_HEADER_MAGIC 0xedfe0dd0 /*header of dtb file*/
472#define AML_DT_HEADER_MAGIC 0x5f4c4d41 /*"AML_", multi dtbs supported*/
473
474#define IS_GZIP_FORMAT(data) ((data & (0x0000FFFF)) == (0x00008B1F))
475#define GUNZIP_BUF_SIZE (0x500000) /* 5MB */
476#define DTB_MAX_SIZE (AML_DTB_IMG_MAX_SZ)
477
478//#define readl(addr) (*(volatile unsigned int*)(addr))
479extern int checkhw(char * name);
480
481unsigned long __attribute__((unused))
482 get_multi_dt_entry(unsigned long fdt_addr){
483 unsigned int dt_magic = readl(fdt_addr);
484 unsigned int dt_total = 0;
485 unsigned int dt_tool_version = 0;
486 unsigned int gzip_format = 0;
487 void * gzip_buf = NULL;
488 unsigned long dt_entry = fdt_addr;
489
490 printf(" Amlogic multi-dtb tool\n");
491
492 /* first check the file header, support GZIP format */
493 gzip_format = IS_GZIP_FORMAT(dt_magic);
494 if (gzip_format) {
495 printf(" GZIP format, decompress...\n");
496 gzip_buf = malloc(GUNZIP_BUF_SIZE);
497 memset(gzip_buf, 0, GUNZIP_BUF_SIZE);
498 unsigned long unzip_size = GUNZIP_BUF_SIZE;
499 gunzip(gzip_buf, GUNZIP_BUF_SIZE, (void *)fdt_addr, &unzip_size);
500 dbg_printf(" DBG: unzip_size: 0x%x\n", (unsigned int)unzip_size);
501 if (unzip_size > GUNZIP_BUF_SIZE) {
502 printf(" Warning! GUNZIP overflow...\n");
503 }
504 fdt_addr = (unsigned long)gzip_buf;
505 dt_magic = readl(fdt_addr);
506 }
507
508 dbg_printf(" DBG: fdt_addr: 0x%x\n", (unsigned int)fdt_addr);
509 dbg_printf(" DBG: dt_magic: 0x%x\n", (unsigned int)dt_magic);
510
511 /*printf(" Process device tree. dt magic: %x\n", dt_magic);*/
512 if (dt_magic == DT_HEADER_MAGIC) {/*normal dtb*/
513 printf(" Single dtb detected\n");
514 if (gzip_format) {
515 memcpy((void *)dt_entry, (void *)fdt_addr, DTB_MAX_SIZE);
516 fdt_addr = dt_entry;
517 if (gzip_buf)
518 free(gzip_buf);
519 }
520 return fdt_addr;
521 }
522 else if (dt_magic == AML_DT_HEADER_MAGIC) {/*multi dtb*/
523 printf(" Multi dtb detected\n");
524 /* check and set aml_dt */
525 int i = 0;
526 char *aml_dt_buf;
527 aml_dt_buf = (char *)malloc(sizeof(char)*64);
528 printf("Multi dtb malloc aml_dt_buf addr = %p\n", aml_dt_buf);
529 memset(aml_dt_buf, 0, sizeof(aml_dt_buf));
530
531 /* update 2016.07.27, checkhw and setenv everytime,
532 or else aml_dt will set only once if it is reserved */
533#if 1
534 checkhw(aml_dt_buf);
535#else
536 char *aml_dt = getenv(AML_DT_UBOOT_ENV);
537 /* if aml_dt not exist or env not ready, get correct dtb by name */
538 if (NULL == aml_dt)
539 checkhw(aml_dt_buf);
540 else
541 memcpy(aml_dt_buf, aml_dt, (strlen(aml_dt)>64?64:(strlen(aml_dt)+1)));
542#endif
543
544 unsigned int aml_dt_len = aml_dt_buf ? strlen(aml_dt_buf) : 0;
545 if (aml_dt_len <= 0) {
546 printf(" Get env aml_dt failed!\n");
547 if (aml_dt_buf)
548 free(aml_dt_buf);
549 if (gzip_buf)
550 free(gzip_buf);
551 return fdt_addr;
552 }
553
554 /*version control, compatible with v1*/
555 dt_tool_version = readl(fdt_addr + AML_DT_VERSION_OFFSET);
556 unsigned int aml_each_id_length=0;
557 unsigned int aml_dtb_offset_offset;
558 unsigned int aml_dtb_header_size;
559 if (dt_tool_version == 1)
560 aml_each_id_length = 4;
561 else if(dt_tool_version == 2)
562 aml_each_id_length = 16;
563
564 aml_dtb_offset_offset = aml_each_id_length * AML_DT_ID_VARI_TOTAL;
565 aml_dtb_header_size = 8+(aml_each_id_length * AML_DT_ID_VARI_TOTAL);
566 printf(" Multi dtb tool version: v%d .\n", dt_tool_version);
567
568 /*fdt_addr + 0x8: num of dtbs*/
569 dt_total = readl(fdt_addr + AML_DT_TOTAL_DTB_OFFSET);
570 printf(" Support %d dtbs.\n", dt_total);
571
572 /* split aml_dt to 3 strings */
573 char *tokens[3] = {NULL, NULL, NULL};
574 for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) {
575 tokens[i] = strsep(&aml_dt_buf, "_");
576 }
577 //if (aml_dt_buf)
578 //free(aml_dt_buf);
579 printf(" aml_dt soc: %s platform: %s variant: %s\n", tokens[0], tokens[1], tokens[2]);
580
581 /*match and print result*/
582 char **dt_info;
583 dt_info = (char **)malloc(sizeof(char *)*AML_DT_ID_VARI_TOTAL);
584 for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++)
585 dt_info[i] = (char *)malloc(sizeof(char)*aml_each_id_length);
586 unsigned int dtb_match_num = 0xffff;
587 unsigned int x = 0, y = 0, z = 0; //loop counter
588 unsigned int read_data;
589 for (i = 0; i < dt_total; i++) {
590 for (x = 0; x < AML_DT_ID_VARI_TOTAL; x++) {
591 for (y = 0; y < aml_each_id_length; y+=4) {
592 read_data = readl(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \
593 i * aml_dtb_header_size + AML_DT_DTB_DT_INFO_OFFSET + \
594 (x * aml_each_id_length) + y);
595 dt_info[x][y+0] = (read_data >> 24) & 0xff;
596 dt_info[x][y+1] = (read_data >> 16) & 0xff;
597 dt_info[x][y+2] = (read_data >> 8) & 0xff;
598 dt_info[x][y+3] = (read_data >> 0) & 0xff;
599 }
600 for (z=0; z<aml_each_id_length; z++) {
601 /*fix string with \0*/
602 if (0x20 == (uint)dt_info[x][z]) {
603 dt_info[x][z] = '\0';
604 }
605 }
606 //printf("dt_info[x]: %s\n", dt_info[x]);
607 //printf("strlen(dt_info[x]): %d\n", strlen(dt_info[x]));
608 }
609 if (dt_tool_version == 1)
610 printf(" dtb %d soc: %.4s plat: %.4s vari: %.4s\n", i, (char *)(dt_info[0]), (char *)(dt_info[1]), (char *)(dt_info[2]));
611 else if(dt_tool_version == 2)
612 printf(" dtb %d soc: %.16s plat: %.16s vari: %.16s\n", i, (char *)(dt_info[0]), (char *)(dt_info[1]), (char *)(dt_info[2]));
613 uint match_str_counter = 0;
614 for (z=0; z<AML_DT_ID_VARI_TOTAL; z++) {
615 /*must match 3 strings*/
616 if (!strncmp(tokens[z], (char *)(dt_info[z]), strlen(tokens[z])) && \
617 (strlen(tokens[z]) == strlen(dt_info[z])))
618 match_str_counter++;
619 }
620 if (match_str_counter == AML_DT_ID_VARI_TOTAL) {
621 //printf("Find match dtb\n");
622 dtb_match_num = i;
623 }
624 for (z=0; z<AML_DT_ID_VARI_TOTAL; z++) {
625 /*clear data for next loop*/
626 memset(dt_info[z], 0, sizeof(aml_each_id_length));
627 }
628 }
629 /*clean malloc memory*/
630 for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) {
631 if (dt_info[i])
632 free(dt_info[i]);
633 }
634 if (dt_info)
635 free(dt_info);
636
637 /*if find match dtb, return address, or else return main entrance address*/
638 if (0xffff != dtb_match_num) {
639 printf(" Find match dtb: %d\n", dtb_match_num);
640 /*this offset is based on dtb image package, so should add on base address*/
641 fdt_addr = (fdt_addr + readl(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \
642 dtb_match_num * aml_dtb_header_size + aml_dtb_offset_offset));
643 if (gzip_format) {
644 memcpy((void *)dt_entry, (void *)fdt_addr, DTB_MAX_SIZE);
645 fdt_addr = dt_entry;
646 if (gzip_buf)
647 free(gzip_buf);
648 }
649 return fdt_addr;
650 }
651 else{
652 printf(" Not match any dtb.\n");
653 if (gzip_buf)
654 free(gzip_buf);
655 return fdt_addr;
656 }
657 }
658 else {
659 printf(" Cannot find legal dtb!\n");
660 if (gzip_buf)
661 free(gzip_buf);
662 return fdt_addr;
663 }
664}
665#endif //#ifdef AML_MULTI_DTB_API_NEW
666
667extern int check_valid_dts(unsigned char *buffer);
668#ifdef AML_MULTI_DTB_CHECK_CMD
669static int do_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
670{
671 unsigned long loadaddr = 0x1080000;
672
673 if (argc > 1)
674 loadaddr = simple_strtoul(argv[1],NULL,16);
675
676 check_valid_dts((void*)loadaddr);
677
678 return 0;
679}
680
681U_BOOT_CMD(
682 dtb_chk, //command name
683 2, //maxargs
684 0, //repeatable
685 do_test, //command function
686 "multi-dtb check command", //description
687 " argv: dtb_chk <dtbLoadaddr> \n" //usage
688 " do dtb check, which already loaded at <dtbLoadaddr>.\n"
689);
690#endif //#ifdef AML_MULTI_DTB_CHECK_CMD