1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2016-2018, NVIDIA CORPORATION.
4  */
5 
6 #include <common.h>
7 #include <env.h>
8 #include <fdt_support.h>
9 #include <fdtdec.h>
10 #include <hang.h>
11 #include <init.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <net.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <asm/global_data.h>
18 
19 #include <linux/ctype.h>
20 #include <linux/sizes.h>
21 
22 #include <asm/arch/tegra.h>
23 #include <asm/arch-tegra/cboot.h>
24 #include <asm/armv8/mmu.h>
25 
26 /*
27  * Size of a region that's large enough to hold the relocated U-Boot and all
28  * other allocations made around it (stack, heap, page tables, etc.)
29  * In practice, running "bdinfo" at the shell prompt, the stack reaches about
30  * 5MB from the address selected for ram_top as of the time of writing,
31  * so a 16MB region should be plenty.
32  */
33 #define MIN_USABLE_RAM_SIZE SZ_16M
34 /*
35  * The amount of space we expect to require for stack usage. Used to validate
36  * that all reservations fit into the region selected for the relocation target
37  */
38 #define MIN_USABLE_STACK_SIZE SZ_1M
39 
40 DECLARE_GLOBAL_DATA_PTR;
41 
42 extern struct mm_region tegra_mem_map[];
43 
44 /*
45  * These variables are written to before relocation, and hence cannot be
46  * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary.
47  * The section attribute forces this into .data and avoids this issue. This
48  * also has the nice side-effect of the content being valid after relocation.
49  */
50 
51 /* The number of valid entries in ram_banks[] */
52 static int ram_bank_count __section(".data");
53 
54 /*
55  * The usable top-of-RAM for U-Boot. This is both:
56  * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing.
57  * b) At the end of a region that has enough space to hold the relocated U-Boot
58  *    and all other allocations made around it (stack, heap, page tables, etc.)
59  */
60 static u64 ram_top __section(".data");
61 /* The base address of the region of RAM that ends at ram_top */
62 static u64 region_base __section(".data");
63 
64 /*
65  * Explicitly put this in the .data section because it is written before the
66  * .bss section is zeroed out but it needs to persist.
67  */
68 unsigned long cboot_boot_x0 __section(".data");
69 
cboot_save_boot_params(unsigned long x0,unsigned long x1,unsigned long x2,unsigned long x3)70 void cboot_save_boot_params(unsigned long x0, unsigned long x1,
71 			    unsigned long x2, unsigned long x3)
72 {
73 	cboot_boot_x0 = x0;
74 }
75 
cboot_dram_init(void)76 int cboot_dram_init(void)
77 {
78 	unsigned int na, ns;
79 	const void *cboot_blob = (void *)cboot_boot_x0;
80 	int node, len, i;
81 	const u32 *prop;
82 
83 	if (!cboot_blob)
84 		return -EINVAL;
85 
86 	na = fdtdec_get_uint(cboot_blob, 0, "#address-cells", 2);
87 	ns = fdtdec_get_uint(cboot_blob, 0, "#size-cells", 2);
88 
89 	node = fdt_path_offset(cboot_blob, "/memory");
90 	if (node < 0) {
91 		pr_err("Can't find /memory node in cboot DTB");
92 		hang();
93 	}
94 	prop = fdt_getprop(cboot_blob, node, "reg", &len);
95 	if (!prop) {
96 		pr_err("Can't find /memory/reg property in cboot DTB");
97 		hang();
98 	}
99 
100 	/* Calculate the true # of base/size pairs to read */
101 	len /= 4;		/* Convert bytes to number of cells */
102 	len /= (na + ns);	/* Convert cells to number of banks */
103 	if (len > CONFIG_NR_DRAM_BANKS)
104 		len = CONFIG_NR_DRAM_BANKS;
105 
106 	/* Parse the /memory node, and save useful entries */
107 	gd->ram_size = 0;
108 	ram_bank_count = 0;
109 	for (i = 0; i < len; i++) {
110 		u64 bank_start, bank_end, bank_size, usable_bank_size;
111 
112 		/* Extract raw memory region data from DTB */
113 		bank_start = fdt_read_number(prop, na);
114 		prop += na;
115 		bank_size = fdt_read_number(prop, ns);
116 		prop += ns;
117 		gd->ram_size += bank_size;
118 		bank_end = bank_start + bank_size;
119 		debug("Bank %d: %llx..%llx (+%llx)\n", i,
120 		      bank_start, bank_end, bank_size);
121 
122 		/*
123 		 * Align the bank to MMU section size. This is not strictly
124 		 * necessary, since the translation table construction code
125 		 * handles page granularity without issue. However, aligning
126 		 * the MMU entries reduces the size and number of levels in the
127 		 * page table, so is worth it.
128 		 */
129 		bank_start = ROUND(bank_start, SZ_2M);
130 		bank_end = bank_end & ~(SZ_2M - 1);
131 		bank_size = bank_end - bank_start;
132 		debug("  aligned: %llx..%llx (+%llx)\n",
133 		      bank_start, bank_end, bank_size);
134 		if (bank_end <= bank_start)
135 			continue;
136 
137 		/* Record data used to create MMU translation tables */
138 		ram_bank_count++;
139 		/* Index below is deliberately 1-based to skip MMIO entry */
140 		tegra_mem_map[ram_bank_count].virt = bank_start;
141 		tegra_mem_map[ram_bank_count].phys = bank_start;
142 		tegra_mem_map[ram_bank_count].size = bank_size;
143 		tegra_mem_map[ram_bank_count].attrs =
144 			PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE;
145 
146 		/* Determine best bank to relocate U-Boot into */
147 		if (bank_end > SZ_4G)
148 			bank_end = SZ_4G;
149 		debug("  end  %llx (usable)\n", bank_end);
150 		usable_bank_size = bank_end - bank_start;
151 		debug("  size %llx (usable)\n", usable_bank_size);
152 		if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) &&
153 		    (bank_end > ram_top)) {
154 			ram_top = bank_end;
155 			region_base = bank_start;
156 			debug("ram top now %llx\n", ram_top);
157 		}
158 	}
159 
160 	/* Ensure memory map contains the desired sentinel entry */
161 	tegra_mem_map[ram_bank_count + 1].virt = 0;
162 	tegra_mem_map[ram_bank_count + 1].phys = 0;
163 	tegra_mem_map[ram_bank_count + 1].size = 0;
164 	tegra_mem_map[ram_bank_count + 1].attrs = 0;
165 
166 	/* Error out if a relocation target couldn't be found */
167 	if (!ram_top) {
168 		pr_err("Can't find a usable RAM top");
169 		hang();
170 	}
171 
172 	return 0;
173 }
174 
cboot_dram_init_banksize(void)175 int cboot_dram_init_banksize(void)
176 {
177 	int i;
178 
179 	if (ram_bank_count == 0)
180 		return -EINVAL;
181 
182 	if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) {
183 		pr_err("Reservations exceed chosen region size");
184 		hang();
185 	}
186 
187 	for (i = 0; i < ram_bank_count; i++) {
188 		gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt;
189 		gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size;
190 	}
191 
192 #ifdef CONFIG_PCI
193 	gd->pci_ram_top = ram_top;
194 #endif
195 
196 	return 0;
197 }
198 
cboot_get_usable_ram_top(ulong total_size)199 ulong cboot_get_usable_ram_top(ulong total_size)
200 {
201 	return ram_top;
202 }
203 
204 /*
205  * The following few functions run late during the boot process and dynamically
206  * calculate the load address of various binaries. To keep track of multiple
207  * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
208  * is used for this purpose to avoid making yet another copy of the list of RAM
209  * banks. This is safe because tegra_mem_map[] is only used once during very
210  * early boot to create U-Boot's page tables, long before this code runs. If
211  * this assumption becomes invalid later, we can just fix the code to copy the
212  * list of RAM banks into some private data structure before running.
213  */
214 
gen_varname(const char * var,const char * ext)215 static char *gen_varname(const char *var, const char *ext)
216 {
217 	size_t len_var = strlen(var);
218 	size_t len_ext = strlen(ext);
219 	size_t len = len_var + len_ext + 1;
220 	char *varext = malloc(len);
221 
222 	if (!varext)
223 		return 0;
224 	strcpy(varext, var);
225 	strcpy(varext + len_var, ext);
226 	return varext;
227 }
228 
mark_ram_allocated(int bank,u64 allocated_start,u64 allocated_end)229 static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
230 {
231 	u64 bank_start = tegra_mem_map[bank].virt;
232 	u64 bank_size = tegra_mem_map[bank].size;
233 	u64 bank_end = bank_start + bank_size;
234 	bool keep_front = allocated_start != bank_start;
235 	bool keep_tail = allocated_end != bank_end;
236 
237 	if (keep_front && keep_tail) {
238 		/*
239 		 * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
240 		 * starting at index 1 (index 0 is MMIO). So, we are at DRAM
241 		 * entry "bank" not "bank - 1" as for a typical 0-base array.
242 		 * The number of remaining DRAM entries is therefore
243 		 * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
244 		 * current entry and shift up the remaining entries, dropping
245 		 * the last one. Thus, we must copy one fewer entry than the
246 		 * number remaining.
247 		 */
248 		memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
249 			CONFIG_NR_DRAM_BANKS - bank - 1);
250 		tegra_mem_map[bank].size = allocated_start - bank_start;
251 		bank++;
252 		tegra_mem_map[bank].virt = allocated_end;
253 		tegra_mem_map[bank].phys = allocated_end;
254 		tegra_mem_map[bank].size = bank_end - allocated_end;
255 	} else if (keep_front) {
256 		tegra_mem_map[bank].size = allocated_start - bank_start;
257 	} else if (keep_tail) {
258 		tegra_mem_map[bank].virt = allocated_end;
259 		tegra_mem_map[bank].phys = allocated_end;
260 		tegra_mem_map[bank].size = bank_end - allocated_end;
261 	} else {
262 		/*
263 		 * We could move all subsequent banks down in the array but
264 		 * that's not necessary for subsequent allocations to work, so
265 		 * we skip doing so.
266 		 */
267 		tegra_mem_map[bank].size = 0;
268 	}
269 }
270 
reserve_ram(u64 start,u64 size)271 static void reserve_ram(u64 start, u64 size)
272 {
273 	int bank;
274 	u64 end = start + size;
275 
276 	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
277 		u64 bank_start = tegra_mem_map[bank].virt;
278 		u64 bank_size = tegra_mem_map[bank].size;
279 		u64 bank_end = bank_start + bank_size;
280 
281 		if (end <= bank_start || start > bank_end)
282 			continue;
283 		mark_ram_allocated(bank, start, end);
284 		break;
285 	}
286 }
287 
alloc_ram(u64 size,u64 align,u64 offset)288 static u64 alloc_ram(u64 size, u64 align, u64 offset)
289 {
290 	int bank;
291 
292 	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
293 		u64 bank_start = tegra_mem_map[bank].virt;
294 		u64 bank_size = tegra_mem_map[bank].size;
295 		u64 bank_end = bank_start + bank_size;
296 		u64 allocated = ROUND(bank_start, align) + offset;
297 		u64 allocated_end = allocated + size;
298 
299 		if (allocated_end > bank_end)
300 			continue;
301 		mark_ram_allocated(bank, allocated, allocated_end);
302 		return allocated;
303 	}
304 	return 0;
305 }
306 
set_calculated_aliases(char * aliases,u64 address)307 static void set_calculated_aliases(char *aliases, u64 address)
308 {
309 	char *tmp, *alias;
310 	int err;
311 
312 	aliases = strdup(aliases);
313 	if (!aliases) {
314 		pr_err("strdup(aliases) failed");
315 		return;
316 	}
317 
318 	tmp = aliases;
319 	while (true) {
320 		alias = strsep(&tmp, " ");
321 		if (!alias)
322 			break;
323 		debug("%s: alias: %s\n", __func__, alias);
324 		err = env_set_hex(alias, address);
325 		if (err)
326 			pr_err("Could not set %s\n", alias);
327 	}
328 
329 	free(aliases);
330 }
331 
set_calculated_env_var(const char * var)332 static void set_calculated_env_var(const char *var)
333 {
334 	char *var_size;
335 	char *var_align;
336 	char *var_offset;
337 	char *var_aliases;
338 	u64 size;
339 	u64 align;
340 	u64 offset;
341 	char *aliases;
342 	u64 address;
343 	int err;
344 
345 	var_size = gen_varname(var, "_size");
346 	if (!var_size)
347 		return;
348 	var_align = gen_varname(var, "_align");
349 	if (!var_align)
350 		goto out_free_var_size;
351 	var_offset = gen_varname(var, "_offset");
352 	if (!var_offset)
353 		goto out_free_var_align;
354 	var_aliases = gen_varname(var, "_aliases");
355 	if (!var_aliases)
356 		goto out_free_var_offset;
357 
358 	size = env_get_hex(var_size, 0);
359 	if (!size) {
360 		pr_err("%s not set or zero\n", var_size);
361 		goto out_free_var_aliases;
362 	}
363 	align = env_get_hex(var_align, 1);
364 	/* Handle extant variables, but with a value of 0 */
365 	if (!align)
366 		align = 1;
367 	offset = env_get_hex(var_offset, 0);
368 	aliases = env_get(var_aliases);
369 
370 	debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
371 	      __func__, var, size, align, offset);
372 	if (aliases)
373 		debug("%s: Aliases: %s\n", __func__, aliases);
374 
375 	address = alloc_ram(size, align, offset);
376 	if (!address) {
377 		pr_err("Could not allocate %s\n", var);
378 		goto out_free_var_aliases;
379 	}
380 	debug("%s: Address %llx\n", __func__, address);
381 
382 	err = env_set_hex(var, address);
383 	if (err)
384 		pr_err("Could not set %s\n", var);
385 	if (aliases)
386 		set_calculated_aliases(aliases, address);
387 
388 out_free_var_aliases:
389 	free(var_aliases);
390 out_free_var_offset:
391 	free(var_offset);
392 out_free_var_align:
393 	free(var_align);
394 out_free_var_size:
395 	free(var_size);
396 }
397 
398 #ifdef DEBUG
dump_ram_banks(void)399 static void dump_ram_banks(void)
400 {
401 	int bank;
402 
403 	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
404 		u64 bank_start = tegra_mem_map[bank].virt;
405 		u64 bank_size = tegra_mem_map[bank].size;
406 		u64 bank_end = bank_start + bank_size;
407 
408 		if (!bank_size)
409 			continue;
410 		printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
411 		       bank_start, bank_end, bank_size);
412 	}
413 }
414 #endif
415 
set_calculated_env_vars(void)416 static void set_calculated_env_vars(void)
417 {
418 	char *vars, *tmp, *var;
419 
420 #ifdef DEBUG
421 	printf("RAM banks before any calculated env. var.s:\n");
422 	dump_ram_banks();
423 #endif
424 
425 	reserve_ram(cboot_boot_x0, fdt_totalsize(cboot_boot_x0));
426 
427 #ifdef DEBUG
428 	printf("RAM after reserving cboot DTB:\n");
429 	dump_ram_banks();
430 #endif
431 
432 	vars = env_get("calculated_vars");
433 	if (!vars) {
434 		debug("%s: No env var calculated_vars\n", __func__);
435 		return;
436 	}
437 
438 	vars = strdup(vars);
439 	if (!vars) {
440 		pr_err("strdup(calculated_vars) failed");
441 		return;
442 	}
443 
444 	tmp = vars;
445 	while (true) {
446 		var = strsep(&tmp, " ");
447 		if (!var)
448 			break;
449 		debug("%s: var: %s\n", __func__, var);
450 		set_calculated_env_var(var);
451 #ifdef DEBUG
452 		printf("RAM banks after allocating %s:\n", var);
453 		dump_ram_banks();
454 #endif
455 	}
456 
457 	free(vars);
458 }
459 
set_fdt_addr(void)460 static int set_fdt_addr(void)
461 {
462 	int ret;
463 
464 	ret = env_set_hex("fdt_addr", cboot_boot_x0);
465 	if (ret) {
466 		printf("Failed to set fdt_addr to point at DTB: %d\n", ret);
467 		return ret;
468 	}
469 
470 	return 0;
471 }
472 
473 /*
474  * Attempt to use /chosen/nvidia,ether-mac in the cboot DTB to U-Boot's
475  * ethaddr environment variable if possible.
476  */
cboot_get_ethaddr_legacy(const void * fdt,uint8_t mac[ETH_ALEN])477 static int cboot_get_ethaddr_legacy(const void *fdt, uint8_t mac[ETH_ALEN])
478 {
479 	const char *const properties[] = {
480 		"nvidia,ethernet-mac",
481 		"nvidia,ether-mac",
482 	};
483 	const char *prop;
484 	unsigned int i;
485 	int node, len;
486 
487 	node = fdt_path_offset(fdt, "/chosen");
488 	if (node < 0) {
489 		printf("Can't find /chosen node in cboot DTB\n");
490 		return node;
491 	}
492 
493 	for (i = 0; i < ARRAY_SIZE(properties); i++) {
494 		prop = fdt_getprop(fdt, node, properties[i], &len);
495 		if (prop)
496 			break;
497 	}
498 
499 	if (!prop) {
500 		printf("Can't find Ethernet MAC address in cboot DTB\n");
501 		return -ENOENT;
502 	}
503 
504 	string_to_enetaddr(prop, mac);
505 
506 	if (!is_valid_ethaddr(mac)) {
507 		printf("Invalid MAC address: %s\n", prop);
508 		return -EINVAL;
509 	}
510 
511 	debug("Legacy MAC address: %pM\n", mac);
512 
513 	return 0;
514 }
515 
cboot_get_ethaddr(const void * fdt,uint8_t mac[ETH_ALEN])516 int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN])
517 {
518 	int node, len, err = 0;
519 	const uchar *prop;
520 	const char *path;
521 
522 	path = fdt_get_alias(fdt, "ethernet");
523 	if (!path) {
524 		err = -ENOENT;
525 		goto out;
526 	}
527 
528 	debug("ethernet alias found: %s\n", path);
529 
530 	node = fdt_path_offset(fdt, path);
531 	if (node < 0) {
532 		err = -ENOENT;
533 		goto out;
534 	}
535 
536 	prop = fdt_getprop(fdt, node, "local-mac-address", &len);
537 	if (!prop) {
538 		err = -ENOENT;
539 		goto out;
540 	}
541 
542 	if (len != ETH_ALEN) {
543 		err = -EINVAL;
544 		goto out;
545 	}
546 
547 	debug("MAC address: %pM\n", prop);
548 	memcpy(mac, prop, ETH_ALEN);
549 
550 out:
551 	if (err < 0)
552 		err = cboot_get_ethaddr_legacy(fdt, mac);
553 
554 	return err;
555 }
556 
strip(const char * ptr)557 static char *strip(const char *ptr)
558 {
559 	const char *end;
560 
561 	while (*ptr && isblank(*ptr))
562 		ptr++;
563 
564 	/* empty string */
565 	if (*ptr == '\0')
566 		return strdup(ptr);
567 
568 	end = ptr;
569 
570 	while (end[1])
571 		end++;
572 
573 	while (isblank(*end))
574 		end--;
575 
576 	return strndup(ptr, end - ptr + 1);
577 }
578 
cboot_get_bootargs(const void * fdt)579 static char *cboot_get_bootargs(const void *fdt)
580 {
581 	const char *args;
582 	int offset, len;
583 
584 	offset = fdt_path_offset(fdt, "/chosen");
585 	if (offset < 0)
586 		return NULL;
587 
588 	args = fdt_getprop(fdt, offset, "bootargs", &len);
589 	if (!args)
590 		return NULL;
591 
592 	return strip(args);
593 }
594 
cboot_late_init(void)595 int cboot_late_init(void)
596 {
597 	const void *fdt = (const void *)cboot_boot_x0;
598 	uint8_t mac[ETH_ALEN];
599 	char *bootargs;
600 	int err;
601 
602 	set_calculated_env_vars();
603 	/*
604 	 * Ignore errors here; the value may not be used depending on
605 	 * extlinux.conf or boot script content.
606 	 */
607 	set_fdt_addr();
608 
609 	/* Ignore errors here; not all cases care about Ethernet addresses */
610 	err = cboot_get_ethaddr(fdt, mac);
611 	if (!err) {
612 		void *blob = (void *)gd->fdt_blob;
613 
614 		err = fdtdec_set_ethernet_mac_address(blob, mac, sizeof(mac));
615 		if (err < 0)
616 			printf("failed to set MAC address %pM: %d\n", mac, err);
617 	}
618 
619 	bootargs = cboot_get_bootargs(fdt);
620 	if (bootargs) {
621 		env_set("cbootargs", bootargs);
622 		free(bootargs);
623 	}
624 
625 	return 0;
626 }
627