hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
 */
 
#include <common.h>
#include <dm.h>
#include <ram.h>
#include <asm/io.h>
#include <asm/arch/rk_atags.h>
#include <asm/arch/param.h>
 
DECLARE_GLOBAL_DATA_PTR;
 
#define SZ_4GB                0x100000000ULL
 
#ifndef CONFIG_SPL_BUILD
#define SDRAM_OFFSET(offset)        (CONFIG_SYS_SDRAM_BASE + (offset))
#define PARAM_DRAM_INFO_OFFSET        (SZ_32M)
#define PARAM_OPTEE_INFO_OFFSET        (SZ_32M + SZ_2M)
 
struct tos_param_t {
   u32 version;
   u32 checksum;
   struct {
       char name[8];
       s64 phy_addr;
       u32 size;
       u32 flags;
   } tee_mem;
   struct {
       char name[8];
       s64 phy_addr;
       u32 size;
       u32 flags;
   } drm_mem;
   s64 reserve[8];
};
 
static uint16_t trust_checksum(const uint8_t *buf, uint16_t len)
{
   uint16_t i, checksum = 0;
 
   for (i = 0; i < len; i++) {
       if (i % 2)
           checksum += buf[i] << 8;
       else
           checksum += buf[i];
   }
   checksum = ~checksum;
 
   return checksum;
}
 
struct memblock param_parse_atf_mem(void)
{
   struct memblock mem;
 
   mem.base = 0;
   mem.size = 0;
 
#ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
   struct tag *t = NULL;
 
   /*
    * Get memory region of ATF
    *
    * 1. New way: atags info;
    * 2. Leagcy way: 2MB size and start from ddr 0x0 offset;
    */
   t = atags_get_tag(ATAG_ATF_MEM);
   if (t && t->u.atf_mem.size) {
       mem.base = t->u.atf_mem.phy_addr;
       mem.size = t->u.atf_mem.size;
       /* Sanity */
       if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) {
           printf("%s: ATF reserved region is not within 0-1MB "
                  "offset(0x%08llx-0x%08llx)!\n",
                  __func__, (u64)mem.base, (u64)mem.base + mem.size);
           return mem;
       }
   }
#endif
 
   /* Legacy */
   if (!mem.size) {
       if (IS_ENABLED(CONFIG_ARM64) ||
           IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) {
           mem.base = SDRAM_OFFSET(0);
           mem.size = SZ_1M;
       }
   }
 
   debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size);
 
   return mem;
}
 
struct memblock param_parse_optee_mem(void)
{
   struct tos_param_t *tos_parameter;
   struct memblock mem;
   u32 checksum;
 
   mem.base = 0;
   mem.size = 0;
 
#ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
   struct tag *t = NULL;
 
   /*
    * Get memory region of OP-TEE
    *
    * 1. New way: atags info;
    * 2. Leagcy way: info in ddr 34M offset;
    */
   t = atags_get_tag(ATAG_TOS_MEM);
   if (t && (t->u.tos_mem.tee_mem.flags == 1)) {
       mem.base = t->u.tos_mem.tee_mem.phy_addr;
       mem.size = t->u.tos_mem.tee_mem.size;
   }
#endif
 
   /* Legacy */
   if (!mem.size) {
       tos_parameter =
       (struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET));
       checksum =
       trust_checksum((uint8_t *)(unsigned long)tos_parameter + 8,
                  sizeof(struct tos_param_t) - 8);
       if ((checksum == tos_parameter->checksum) &&
           (tos_parameter->tee_mem.flags == 1)) {
           mem.base = tos_parameter->tee_mem.phy_addr;
           mem.size = tos_parameter->tee_mem.size;
       }
   }
 
   if (mem.size)
       gd->flags |= GD_FLG_BL32_ENABLED;
 
   debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size);
 
   return mem;
}
 
struct memblock param_parse_common_resv_mem(void)
{
   struct memblock mem;
 
#if defined(CONFIG_ARM64)
   mem.base = SDRAM_OFFSET(SZ_1M);
   mem.size = SZ_1M;
/*
 * The ARMv8 platform enabling AArch32 mode should reserve memory the same
 * as AArch64 mode(because there is no difference about ATF), only some
 * platform has special request, they are: RK3308.
 */
#elif defined(CONFIG_ARM64_BOOT_AARCH32) && !defined(CONFIG_ROCKCHIP_RK3308)
   mem.base = SDRAM_OFFSET(SZ_1M);
   mem.size = SZ_1M;
#else
   mem.size = 0;
#endif
   return mem;
}
 
int param_parse_assign_bootdev(char **devtype, char **devnum)
{
   char *bootdev_str = CONFIG_ROCKCHIP_BOOTDEV;
   char *type, *num;
 
   num = strchr(bootdev_str, ' ');
   if (!num)
       return -ENODEV;
 
   type = strdup(bootdev_str);
   type[num - bootdev_str] = 0;
   num++;
 
   *devtype = type;
   *devnum = num;
 
   return 0;
}
 
int param_parse_atags_bootdev(char **devtype, char **devnum)
{
#ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
   struct tag *t;
 
   t = atags_get_tag(ATAG_BOOTDEV);
   if (t) {
       switch (t->u.bootdev.devtype) {
#ifdef CONFIG_DM_MMC
       case BOOT_TYPE_EMMC:
           *devtype = "mmc";
           *devnum = "0";
           break;
       case BOOT_TYPE_SD0:
       case BOOT_TYPE_SD1:
           *devtype = "mmc";
           *devnum = "1";
           /*
            * If preloader does not pass sdupdate value, we treat it
            * as a unknown card and call the rkimgtest cmd to find
            * out what it is.
            *
            * If preloader pass sdupdate value as an update card,
            * we just set "sdfwupdate" to bootargs instead of
            * calling rkimgtest cmd which consumes time.
            */
           if (t->u.bootdev.sdupdate == SD_UNKNOWN_CARD) {
               run_command("mmc dev 1", 0);
               run_command("rkimgtest mmc 1", 0);
           } else if (t->u.bootdev.sdupdate == SD_UPDATE_CARD) {
               env_update("bootargs", "sdfwupdate");
           }
           break;
#endif
#if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
       case BOOT_TYPE_NAND:
           *devtype = "rknand";
           *devnum = "0";
           break;
#endif
#ifdef CONFIG_RKSFC_NAND
       case BOOT_TYPE_SPI_NAND:
           *devtype = "spinand";
           *devnum = "0";
           break;
#endif
#ifdef CONFIG_RKSFC_NOR
       case BOOT_TYPE_SPI_NOR:
           *devtype = "spinor";
           *devnum = "1";
           break;
#endif
#ifdef CONFIG_DM_RAMDISK
       case BOOT_TYPE_RAM:
           *devtype = "ramdisk";
           *devnum = "0";
           break;
#endif
#ifdef CONFIG_NAND
       case BOOT_TYPE_MTD_BLK_NAND:
           *devtype = "mtd";
           *devnum = "0";
           break;
#endif
#ifdef CONFIG_MTD_SPI_NAND
       case BOOT_TYPE_MTD_BLK_SPI_NAND:
           *devtype = "mtd";
           *devnum = "1";
           break;
#endif
#ifdef CONFIG_SPI_FLASH_MTD
       case BOOT_TYPE_MTD_BLK_SPI_NOR:
           *devtype = "mtd";
           *devnum = "2";
           break;
#endif
       default:
           printf("Unknown bootdev type: 0x%x\n",
                  t->u.bootdev.devtype);
           return -EINVAL;
       }
 
       return 0;
   }
#endif
 
   return -ENOSYS;
}
#endif
 
static phys_size_t ddr_mem_get_usable_size(u64 base, u64 size)
{
   return (base + size >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) ?
          (CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE - base) : size;
}
 
struct memblock *param_parse_ddr_mem(int *out_count)
{
   struct udevice *dev;
   struct memblock *mem;
   struct ram_info ram;
   int i, ret, count;
 
   /*
    * Get memory region of DDR
    *
    * 1. New: atags info;
    * 2. Leagcy: os register;
    */
#ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
   struct tag *t;
   u64 base, size;
   int n;
 
   t = atags_get_tag(ATAG_DDR_MEM);
   if (t && t->u.ddr_mem.count) {
       /* extend top ram size */
       if (t->u.ddr_mem.flags & DDR_MEM_FLG_EXT_TOP)
           gd->ram_top_ext_size = t->u.ddr_mem.data[0];
 
       /* normal ram size */
       count = t->u.ddr_mem.count;
       mem = calloc(count + MEM_RESV_COUNT, sizeof(*mem));
       if (!mem) {
           printf("Calloc ddr memory failed\n");
           return 0;
       }
 
       for (i = 0, n = 0; i < count; i++, n++) {
           base = t->u.ddr_mem.bank[i];
           size = t->u.ddr_mem.bank[i + count];
 
           /* 0~4GB */
           if (base < SZ_4GB) {
               mem[n].base = base;
               mem[n].size = ddr_mem_get_usable_size(base, size);
               if (base + size > SZ_4GB) {
                   n++;
                   mem[n].base_u64 = SZ_4GB;
                   mem[n].size_u64 = base + size - SZ_4GB;
               }
           } else {
               /* 4GB+ */
               mem[n].base_u64 = base;
               mem[n].size_u64 = size;
           }
 
           assert(n < count + MEM_RESV_COUNT);
       }
 
       *out_count = n;
       return mem;
   }
#endif
 
   /* Leagcy */
   ret = uclass_get_device(UCLASS_RAM, 0, &dev);
   if (ret) {
       debug("DRAM init failed: %d\n", ret);
       return NULL;
   }
   ret = ram_get_info(dev, &ram);
   if (ret) {
       debug("Cannot get DRAM size: %d\n", ret);
       return NULL;
   }
 
   debug("SDRAM base=%lx, size=%lx\n",
         (unsigned long)ram.base, (unsigned long)ram.size);
 
   count = 1;
   mem = calloc(1, sizeof(*mem));
   if (!mem) {
       printf("Calloc ddr memory failed\n");
       return 0;
   }
 
   for (i = 0; i < count; i++) {
       mem[i].base = CONFIG_SYS_SDRAM_BASE;
       mem[i].size = ddr_mem_get_usable_size(mem[i].base, ram.size);
   }
 
   *out_count = count;
   return mem;
}
 
#ifndef CONFIG_BIDRAM
/*
 * init_bank=0: called from dram_init_banksize()
 * init_bank=0: called from dram_init()
 */
phys_size_t param_simple_parse_ddr_mem(int init_bank)
{
   struct memblock *list;
   int i, count;
 
   list = param_parse_ddr_mem(&count);
   if (!list) {
       printf("Can't get dram banks\n");
       return 0;
   }
 
   if (count > CONFIG_NR_DRAM_BANKS) {
       printf("Dram banks num=%d, over %d\n", count, CONFIG_NR_DRAM_BANKS);
       return 0;
   }
 
   if (!init_bank) {
       i = count - 1;
       return ddr_mem_get_usable_size(list[i].base, list[i].size);
   }
 
   for (i = 0; i < count; i++) {
       gd->bd->bi_dram[i].start = list[i].base;
       gd->bd->bi_dram[i].size =
           ddr_mem_get_usable_size(list[i].base, list[i].size);
       debug("bank[%d]: 0x%08lx - 0x%08lx\n", i,
             (ulong)gd->bd->bi_dram[i].start,
             (ulong)gd->bd->bi_dram[i].start +
             (ulong)gd->bd->bi_dram[i].size);
   }
 
   return 0;
}
#endif
 
int param_parse_pre_serial(int *flags)
{
#if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \
    defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS)
   struct tag *t;
 
   t = atags_get_tag(ATAG_SERIAL);
   if (t) {
       gd->serial.using_pre_serial = 1;
       gd->serial.enable = t->u.serial.enable;
       gd->serial.baudrate = t->u.serial.baudrate;
       gd->serial.addr = t->u.serial.addr;
       gd->serial.id = t->u.serial.id;
       gd->baudrate = CONFIG_BAUDRATE;
       if (!gd->serial.enable && flags)
           *flags |= GD_FLG_DISABLE_CONSOLE;
       debug("preloader: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n",
             gd->serial.enable, gd->serial.addr,
             gd->serial.baudrate, gd->serial.id);
   } else
#endif
   {
       gd->baudrate = CONFIG_BAUDRATE;
       gd->serial.baudrate = CONFIG_BAUDRATE;
       gd->serial.addr = CONFIG_DEBUG_UART_BASE;
   }
 
   return 0;
}
 
int param_parse_pubkey_fuse_programmed(void)
{
#ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
   struct tag *t;
 
   t = atags_get_tag(ATAG_PUB_KEY);
   if (t) {
       /* Pass if efuse/otp programmed */
       if (t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED)
           env_update("bootargs", "fuse.programmed=1");
       else
           env_update("bootargs", "fuse.programmed=0");
   }
#endif
   return 0;
}