cboot.c 15 KB

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