Deleted Added
full compact
fdt_loader_cmd.c (273927) fdt_loader_cmd.c (273934)
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Semihalf under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Semihalf under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/boot/fdt/fdt_loader_cmd.c 273927 2014-11-01 10:50:18Z andrew $");
31__FBSDID("$FreeBSD: head/sys/boot/fdt/fdt_loader_cmd.c 273934 2014-11-01 17:12:44Z andrew $");
32
33#include <stand.h>
34#include <fdt.h>
35#include <libfdt.h>
36#include <sys/param.h>
37#include <sys/linker.h>
38#include <machine/elf.h>
39
40#include "bootstrap.h"
41#include "fdt_platform.h"
32
33#include <stand.h>
34#include <fdt.h>
35#include <libfdt.h>
36#include <sys/param.h>
37#include <sys/linker.h>
38#include <machine/elf.h>
39
40#include "bootstrap.h"
41#include "fdt_platform.h"
42#include "glue.h"
43
44#ifdef DEBUG
45#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
46 printf(fmt,##args); } while (0)
47#else
48#define debugf(fmt, args...)
49#endif
50
51#define FDT_CWD_LEN 256
52#define FDT_MAX_DEPTH 6
53
54#define FDT_PROP_SEP " = "
55
42
43#ifdef DEBUG
44#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
45 printf(fmt,##args); } while (0)
46#else
47#define debugf(fmt, args...)
48#endif
49
50#define FDT_CWD_LEN 256
51#define FDT_MAX_DEPTH 6
52
53#define FDT_PROP_SEP " = "
54
56#define STR(number) #number
57#define STRINGIFY(number) STR(number)
58
59#define COPYOUT(s,d,l) archsw.arch_copyout(s, d, l)
60#define COPYIN(s,d,l) archsw.arch_copyin(s, d, l)
61
62#define FDT_STATIC_DTB_SYMBOL "fdt_static_dtb"
63
64#define CMD_REQUIRES_BLOB 0x01
65
66/* Location of FDT yet to be loaded. */

--- 157 unchanged lines hidden (view full) ---

224
225 fdtp_va = va;
226 COPYOUT(va, fdtp, fdtp_size);
227 debugf("DTB blob found at 0x%jx, size: 0x%jx\n", (uintmax_t)va, (uintmax_t)fdtp_size);
228
229 return (0);
230}
231
55#define COPYOUT(s,d,l) archsw.arch_copyout(s, d, l)
56#define COPYIN(s,d,l) archsw.arch_copyin(s, d, l)
57
58#define FDT_STATIC_DTB_SYMBOL "fdt_static_dtb"
59
60#define CMD_REQUIRES_BLOB 0x01
61
62/* Location of FDT yet to be loaded. */

--- 157 unchanged lines hidden (view full) ---

220
221 fdtp_va = va;
222 COPYOUT(va, fdtp, fdtp_size);
223 debugf("DTB blob found at 0x%jx, size: 0x%jx\n", (uintmax_t)va, (uintmax_t)fdtp_size);
224
225 return (0);
226}
227
232static int
228int
233fdt_load_dtb_addr(struct fdt_header *header)
234{
235 int err;
236
237 debugf("fdt_load_dtb_addr(%p)\n", header);
238
239 fdtp_size = fdt_totalsize(header);
240 err = fdt_check_header(header);

--- 8 unchanged lines hidden (view full) ---

249 return (1);
250 }
251
252 fdtp_va = 0; // Don't write this back into module or kernel.
253 bcopy(header, fdtp, fdtp_size);
254 return (0);
255}
256
229fdt_load_dtb_addr(struct fdt_header *header)
230{
231 int err;
232
233 debugf("fdt_load_dtb_addr(%p)\n", header);
234
235 fdtp_size = fdt_totalsize(header);
236 err = fdt_check_header(header);

--- 8 unchanged lines hidden (view full) ---

245 return (1);
246 }
247
248 fdtp_va = 0; // Don't write this back into module or kernel.
249 bcopy(header, fdtp, fdtp_size);
250 return (0);
251}
252
257static int
253int
258fdt_load_dtb_file(const char * filename)
259{
260 struct preloaded_file *bfp, *oldbfp;
261 int err;
262
263 debugf("fdt_load_dtb_file(%s)\n", filename);
264
265 oldbfp = file_findfile(NULL, "dtb");

--- 13 unchanged lines hidden (view full) ---

279 file_discard(oldbfp);
280 return (0);
281}
282
283int
284fdt_setup_fdtp()
285{
286 struct preloaded_file *bfp;
254fdt_load_dtb_file(const char * filename)
255{
256 struct preloaded_file *bfp, *oldbfp;
257 int err;
258
259 debugf("fdt_load_dtb_file(%s)\n", filename);
260
261 oldbfp = file_findfile(NULL, "dtb");

--- 13 unchanged lines hidden (view full) ---

275 file_discard(oldbfp);
276 return (0);
277}
278
279int
280fdt_setup_fdtp()
281{
282 struct preloaded_file *bfp;
287 struct fdt_header *hdr;
288 const char *s;
289 char *p;
290 vm_offset_t va;
291
292 debugf("fdt_setup_fdtp()\n");
293
294 /* If we already loaded a file, use it. */
295 if ((bfp = file_findfile(NULL, "dtb")) != NULL) {
296 if (fdt_load_dtb(bfp->f_addr) == 0) {
297 printf("Using DTB from loaded file '%s'.\n",

--- 6 unchanged lines hidden (view full) ---

304 if (fdt_to_load != NULL) {
305 if (fdt_load_dtb_addr(fdt_to_load) == 0) {
306 printf("Using DTB from memory address 0x%08X.\n",
307 (unsigned int)fdt_to_load);
308 return (0);
309 }
310 }
311
283 vm_offset_t va;
284
285 debugf("fdt_setup_fdtp()\n");
286
287 /* If we already loaded a file, use it. */
288 if ((bfp = file_findfile(NULL, "dtb")) != NULL) {
289 if (fdt_load_dtb(bfp->f_addr) == 0) {
290 printf("Using DTB from loaded file '%s'.\n",

--- 6 unchanged lines hidden (view full) ---

297 if (fdt_to_load != NULL) {
298 if (fdt_load_dtb_addr(fdt_to_load) == 0) {
299 printf("Using DTB from memory address 0x%08X.\n",
300 (unsigned int)fdt_to_load);
301 return (0);
302 }
303 }
304
312 /*
313 * If the U-boot environment contains a variable giving the address of a
314 * valid blob in memory, use it. The U-boot README says the right
315 * variable for fdt data loaded into ram is fdt_addr_r, so try that
316 * first. Board vendors also use both fdtaddr and fdt_addr names.
317 */
318 s = ub_env_get("fdt_addr_r");
319 if (s == NULL)
320 s = ub_env_get("fdtaddr");
321 if (s == NULL)
322 s = ub_env_get("fdt_addr");
323 if (s != NULL && *s != '\0') {
324 hdr = (struct fdt_header *)strtoul(s, &p, 16);
325 if (*p == '\0') {
326 if (fdt_load_dtb_addr(hdr) == 0) {
327 printf("Using DTB provided by U-Boot at "
328 "address %p.\n", hdr);
329 return (0);
330 }
331 }
332 }
305 if (fdt_platform_load_dtb() == 0)
306 return (0);
333
307
334 /*
335 * If the U-boot environment contains a variable giving the name of a
336 * file, use it if we can load and validate it.
337 */
338 s = ub_env_get("fdtfile");
339 if (s == NULL)
340 s = ub_env_get("fdt_file");
341 if (s != NULL && *s != '\0') {
342 if (fdt_load_dtb_file(s) == 0) {
343 printf("Loaded DTB from file '%s'.\n", s);
344 return (0);
345 }
346 }
347
348 /* If there is a dtb compiled into the kernel, use it. */
349 if ((va = fdt_find_static_dtb()) != 0) {
350 if (fdt_load_dtb(va) == 0) {
351 printf("Using DTB compiled into kernel.\n");
352 return (0);
353 }
354 }
355

--- 46 unchanged lines hidden (view full) ---

402 buf++;
403 /* Find another number */
404 while ((isxdigit(*buf) || *buf == 'x') && buf < end)
405 buf++;
406 }
407 return (cnt);
408}
409
308 /* If there is a dtb compiled into the kernel, use it. */
309 if ((va = fdt_find_static_dtb()) != 0) {
310 if (fdt_load_dtb(va) == 0) {
311 printf("Using DTB compiled into kernel.\n");
312 return (0);
313 }
314 }
315

--- 46 unchanged lines hidden (view full) ---

362 buf++;
363 /* Find another number */
364 while ((isxdigit(*buf) || *buf == 'x') && buf < end)
365 buf++;
366 }
367 return (cnt);
368}
369
410#define TMP_MAX_ETH 8
411
412static void
413fixup_ethernet(const char *env, char *ethstr, int *eth_no, int len)
370void
371fdt_fixup_ethernet(const char *str, char *ethstr, int len)
414{
372{
415 const char *str;
416 char *end;
417 uint8_t tmp_addr[6];
373 uint8_t tmp_addr[6];
418 int i, n;
419
374
420 /* Extract interface number */
421 i = strtol(env + 3, &end, 10);
422 if (end == (env + 3))
423 /* 'ethaddr' means interface 0 address */
424 n = 0;
425 else
426 n = i;
427
428 if (n > TMP_MAX_ETH)
429 return;
430
431 str = ub_env_get(env);
432
433 /* Convert macaddr string into a vector of uints */
434 fdt_strtovectx(str, &tmp_addr, 6, sizeof(uint8_t));
375 /* Convert macaddr string into a vector of uints */
376 fdt_strtovectx(str, &tmp_addr, 6, sizeof(uint8_t));
435 if (n != 0) {
436 i = strlen(env) - 7;
437 strncpy(ethstr + 8, env + 3, i);
438 }
439 /* Set actual property to a value from vect */
440 fdt_setprop(fdtp, fdt_path_offset(fdtp, ethstr),
441 "local-mac-address", &tmp_addr, 6 * sizeof(uint8_t));
377 /* Set actual property to a value from vect */
378 fdt_setprop(fdtp, fdt_path_offset(fdtp, ethstr),
379 "local-mac-address", &tmp_addr, 6 * sizeof(uint8_t));
442
443 /* Clear ethernet..XXXX.. string */
444 bzero(ethstr + 8, len - 8);
445
446 if (n + 1 > *eth_no)
447 *eth_no = n + 1;
448}
449
380}
381
450static void
451fixup_cpubusfreqs(unsigned long cpufreq, unsigned long busfreq)
382void
383fdt_fixup_cpubusfreqs(unsigned long cpufreq, unsigned long busfreq)
452{
453 int lo, o = 0, o2, maxo = 0, depth;
454 const uint32_t zero = 0;
455
456 /* We want to modify every subnode of /cpus */
457 o = fdt_path_offset(fdtp, "/cpus");
458 if (o < 0)
459 return;

--- 62 unchanged lines hidden (view full) ---

522 return (EINVAL);
523
524 debugf(" reg#%d (start: 0x%0x size: 0x%0x) valid!\n",
525 i, cur_start, cur_size);
526 }
527 return (0);
528}
529
384{
385 int lo, o = 0, o2, maxo = 0, depth;
386 const uint32_t zero = 0;
387
388 /* We want to modify every subnode of /cpus */
389 o = fdt_path_offset(fdtp, "/cpus");
390 if (o < 0)
391 return;

--- 62 unchanged lines hidden (view full) ---

454 return (EINVAL);
455
456 debugf(" reg#%d (start: 0x%0x size: 0x%0x) valid!\n",
457 i, cur_start, cur_size);
458 }
459 return (0);
460}
461
530static void
531fixup_memory(struct sys_info *si)
462void
463fdt_fixup_memory(struct fdt_mem_region *region, size_t num)
532{
464{
533 struct mem_region *curmr;
465 struct fdt_mem_region *curmr;
534 uint32_t addr_cells, size_cells;
535 uint32_t *addr_cellsp, *reg, *size_cellsp;
466 uint32_t addr_cells, size_cells;
467 uint32_t *addr_cellsp, *reg, *size_cellsp;
536 int err, i, len, memory, realmrno, root;
468 int err, i, len, memory, root;
469 size_t realmrno;
537 uint8_t *buf, *sb;
538 uint64_t rstart, rsize;
539 int reserved;
540
541 root = fdt_path_offset(fdtp, "/");
542 if (root < 0) {
543 sprintf(command_errbuf, "Could not find root node !");
544 return;

--- 41 unchanged lines hidden (view full) ---

586 len = (addr_cells + size_cells) * reserved * sizeof(uint32_t);
587 sb = buf = (uint8_t *)malloc(len);
588 if (!buf)
589 return;
590
591 bzero(buf, len);
592
593 for (i = 0; i < reserved; i++) {
470 uint8_t *buf, *sb;
471 uint64_t rstart, rsize;
472 int reserved;
473
474 root = fdt_path_offset(fdtp, "/");
475 if (root < 0) {
476 sprintf(command_errbuf, "Could not find root node !");
477 return;

--- 41 unchanged lines hidden (view full) ---

519 len = (addr_cells + size_cells) * reserved * sizeof(uint32_t);
520 sb = buf = (uint8_t *)malloc(len);
521 if (!buf)
522 return;
523
524 bzero(buf, len);
525
526 for (i = 0; i < reserved; i++) {
594 curmr = &si->mr[i];
595 if (fdt_get_mem_rsv(fdtp, i, &rstart, &rsize))
596 break;
597 if (rsize) {
598 /* Ensure endianess, and put cells into a buffer */
599 if (addr_cells == 2)
600 *(uint64_t *)buf =
601 cpu_to_fdt64(rstart);
602 else

--- 15 unchanged lines hidden (view full) ---

618 /* Set property */
619 if ((err = fdt_setprop(fdtp, root, "memreserve", sb, len)) < 0)
620 printf("Could not fixup 'memreserve' property.\n");
621
622 free(sb);
623 }
624
625 /* Count valid memory regions entries in sysinfo. */
527 if (fdt_get_mem_rsv(fdtp, i, &rstart, &rsize))
528 break;
529 if (rsize) {
530 /* Ensure endianess, and put cells into a buffer */
531 if (addr_cells == 2)
532 *(uint64_t *)buf =
533 cpu_to_fdt64(rstart);
534 else

--- 15 unchanged lines hidden (view full) ---

550 /* Set property */
551 if ((err = fdt_setprop(fdtp, root, "memreserve", sb, len)) < 0)
552 printf("Could not fixup 'memreserve' property.\n");
553
554 free(sb);
555 }
556
557 /* Count valid memory regions entries in sysinfo. */
626 realmrno = si->mr_no;
627 for (i = 0; i < si->mr_no; i++)
628 if (si->mr[i].start == 0 && si->mr[i].size == 0)
558 realmrno = num;
559 for (i = 0; i < num; i++)
560 if (region[i].start == 0 && region[i].size == 0)
629 realmrno--;
630
631 if (realmrno == 0) {
632 sprintf(command_errbuf, "Could not fixup '/memory' node : "
633 "sysinfo doesn't contain valid memory regions info!\n");
634 return;
635 }
636

--- 10 unchanged lines hidden (view full) ---

647
648 len = (addr_cells + size_cells) * realmrno * sizeof(uint32_t);
649 sb = buf = (uint8_t *)malloc(len);
650 if (!buf)
651 return;
652
653 bzero(buf, len);
654
561 realmrno--;
562
563 if (realmrno == 0) {
564 sprintf(command_errbuf, "Could not fixup '/memory' node : "
565 "sysinfo doesn't contain valid memory regions info!\n");
566 return;
567 }
568

--- 10 unchanged lines hidden (view full) ---

579
580 len = (addr_cells + size_cells) * realmrno * sizeof(uint32_t);
581 sb = buf = (uint8_t *)malloc(len);
582 if (!buf)
583 return;
584
585 bzero(buf, len);
586
655 for (i = 0; i < si->mr_no; i++) {
656 curmr = &si->mr[i];
587 for (i = 0; i < num; i++) {
588 curmr = &region[i];
657 if (curmr->size != 0) {
658 /* Ensure endianess, and put cells into a buffer */
659 if (addr_cells == 2)
660 *(uint64_t *)buf =
661 cpu_to_fdt64(curmr->start);
662 else
663 *(uint32_t *)buf =
664 cpu_to_fdt32(curmr->start);

--- 12 unchanged lines hidden (view full) ---

677
678 /* Set property */
679 if ((err = fdt_setprop(fdtp, memory, "reg", sb, len)) < 0)
680 sprintf(command_errbuf, "Could not fixup '/memory' node.\n");
681
682 free(sb);
683}
684
589 if (curmr->size != 0) {
590 /* Ensure endianess, and put cells into a buffer */
591 if (addr_cells == 2)
592 *(uint64_t *)buf =
593 cpu_to_fdt64(curmr->start);
594 else
595 *(uint32_t *)buf =
596 cpu_to_fdt32(curmr->start);

--- 12 unchanged lines hidden (view full) ---

609
610 /* Set property */
611 if ((err = fdt_setprop(fdtp, memory, "reg", sb, len)) < 0)
612 sprintf(command_errbuf, "Could not fixup '/memory' node.\n");
613
614 free(sb);
615}
616
685static void
686fixup_stdout(const char *env)
617void
618fdt_fixup_stdout(const char *str)
687{
619{
688 const char *str;
689 char *ptr;
690 int serialno;
691 int len, no, sero;
692 const struct fdt_property *prop;
693 char *tmp[10];
694
620 char *ptr;
621 int serialno;
622 int len, no, sero;
623 const struct fdt_property *prop;
624 char *tmp[10];
625
695 str = ub_env_get(env);
696 ptr = (char *)str + strlen(str) - 1;
697 while (ptr > str && isdigit(*(str - 1)))
698 str--;
699
700 if (ptr == str)
701 return;
702
703 serialno = (int)strtol(ptr, NULL, 0);

--- 29 unchanged lines hidden (view full) ---

733}
734
735/*
736 * Locate the blob, fix it up and return its location.
737 */
738static int
739fdt_fixup(void)
740{
626 ptr = (char *)str + strlen(str) - 1;
627 while (ptr > str && isdigit(*(str - 1)))
628 str--;
629
630 if (ptr == str)
631 return;
632
633 serialno = (int)strtol(ptr, NULL, 0);

--- 29 unchanged lines hidden (view full) ---

663}
664
665/*
666 * Locate the blob, fix it up and return its location.
667 */
668static int
669fdt_fixup(void)
670{
741 const char *env;
742 char *ethstr;
743 int chosen, eth_no, len;
744 struct sys_info *si;
671 int chosen, len;
745
672
746 env = NULL;
747 eth_no = 0;
748 ethstr = NULL;
749 len = 0;
750
751 debugf("fdt_fixup()\n");
752
753 if (fdtp == NULL && fdt_setup_fdtp() != 0)
754 return (0);
755
756 /* Create /chosen node (if not exists) */
757 if ((chosen = fdt_subnode_offset(fdtp, 0, "chosen")) ==
758 -FDT_ERR_NOTFOUND)
759 chosen = fdt_add_subnode(fdtp, 0, "chosen");
760
761 /* Value assigned to fixup-applied does not matter. */
762 if (fdt_getprop(fdtp, chosen, "fixup-applied", NULL))
763 return (1);
764
673 len = 0;
674
675 debugf("fdt_fixup()\n");
676
677 if (fdtp == NULL && fdt_setup_fdtp() != 0)
678 return (0);
679
680 /* Create /chosen node (if not exists) */
681 if ((chosen = fdt_subnode_offset(fdtp, 0, "chosen")) ==
682 -FDT_ERR_NOTFOUND)
683 chosen = fdt_add_subnode(fdtp, 0, "chosen");
684
685 /* Value assigned to fixup-applied does not matter. */
686 if (fdt_getprop(fdtp, chosen, "fixup-applied", NULL))
687 return (1);
688
765 /* Acquire sys_info */
766 si = ub_get_sys_info();
689 fdt_platform_fixups();
767
690
768 while ((env = ub_env_enum(env)) != NULL) {
769 if (strncmp(env, "eth", 3) == 0 &&
770 strncmp(env + (strlen(env) - 4), "addr", 4) == 0) {
771 /*
772 * Handle Ethernet addrs: parse uboot env eth%daddr
773 */
774
775 if (!eth_no) {
776 /*
777 * Check how many chars we will need to store
778 * maximal eth iface number.
779 */
780 len = strlen(STRINGIFY(TMP_MAX_ETH)) +
781 strlen("ethernet");
782
783 /*
784 * Reserve mem for string "ethernet" and len
785 * chars for iface no.
786 */
787 ethstr = (char *)malloc(len * sizeof(char));
788 bzero(ethstr, len * sizeof(char));
789 strcpy(ethstr, "ethernet0");
790 }
791
792 /* Modify blob */
793 fixup_ethernet(env, ethstr, &eth_no, len);
794
795 } else if (strcmp(env, "consoledev") == 0)
796 fixup_stdout(env);
797 }
798
799 /* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */
800 fixup_cpubusfreqs(si->clk_cpu, si->clk_bus);
801
802 /* Fixup memory regions */
803 fixup_memory(si);
804
805 fdt_setprop(fdtp, chosen, "fixup-applied", NULL, 0);
806 return (1);
807}
808
809/*
810 * Copy DTB blob to specified location and return size
811 */
812int

--- 890 unchanged lines hidden ---
691 fdt_setprop(fdtp, chosen, "fixup-applied", NULL, 0);
692 return (1);
693}
694
695/*
696 * Copy DTB blob to specified location and return size
697 */
698int

--- 890 unchanged lines hidden ---