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 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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$"); 32 33 #include <sys/param.h> 34 #include <stand.h> 35 #include <fdt_platform.h> 36 37 #include "glue.h" 38 39 #define STR(number) #number 40 #define STRINGIFY(number) STR(number) 41 42 int 43 fdt_platform_load_dtb(void) 44 { 45 struct fdt_header *hdr; 46 const char *s; 47 char *p; 48 49 /* 50 * If the U-boot environment contains a variable giving the address of a 51 * valid blob in memory, use it. The U-boot README says the right 52 * variable for fdt data loaded into ram is fdt_addr_r, so try that 53 * first. Board vendors also use both fdtaddr and fdt_addr names. 54 */ 55 s = ub_env_get("fdt_addr_r"); 56 if (s == NULL) 57 s = ub_env_get("fdtaddr"); 58 if (s == NULL) 59 s = ub_env_get("fdt_addr"); 60 if (s != NULL && *s != '\0') { 61 hdr = (struct fdt_header *)strtoul(s, &p, 16); 62 if (*p == '\0') { 63 if (fdt_load_dtb_addr(hdr) == 0) { 64 printf("Using DTB provided by U-Boot at " 65 "address %p.\n", hdr); 66 return (0); 67 } 68 } 69 } 70 71 /* 72 * Try to get FDT filename first from loader env and then from u-boot env 73 */ 74 s = getenv("fdt_file"); 75 if (s == NULL) 76 s = ub_env_get("fdtfile"); 77 if (s == NULL) 78 s = ub_env_get("fdt_file"); 79 if (s != NULL && *s != '\0') { 80 if (fdt_load_dtb_file(s) == 0) { 81 printf("Loaded DTB from file '%s'.\n", s); 82 return (0); 83 } 84 } 85 86 return (1); 87 } 88 89 void 90 fdt_platform_fixups(void) 91 { 92 static struct fdt_mem_region regions[UB_MAX_MR]; 93 const char *env, *str; 94 char *end, *ethstr; 95 int eth_no, i, len, n; 96 struct sys_info *si; 97 98 env = NULL; 99 eth_no = 0; 100 ethstr = NULL; 101 102 /* Acquire sys_info */ 103 si = ub_get_sys_info(); 104 105 while ((env = ub_env_enum(env)) != NULL) { 106 if (strncmp(env, "eth", 3) == 0 && 107 strncmp(env + (strlen(env) - 4), "addr", 4) == 0) { 108 /* 109 * Handle Ethernet addrs: parse uboot env eth%daddr 110 */ 111 112 if (!eth_no) { 113 /* 114 * Check how many chars we will need to store 115 * maximal eth iface number. 116 */ 117 len = strlen(STRINGIFY(TMP_MAX_ETH)) + 118 strlen("ethernet") + 1; 119 120 /* 121 * Reserve mem for string "ethernet" and len 122 * chars for iface no. 123 */ 124 ethstr = (char *)malloc(len * sizeof(char)); 125 bzero(ethstr, len * sizeof(char)); 126 strcpy(ethstr, "ethernet0"); 127 } 128 129 /* Extract interface number */ 130 i = strtol(env + 3, &end, 10); 131 if (end == (env + 3)) 132 /* 'ethaddr' means interface 0 address */ 133 n = 0; 134 else 135 n = i; 136 137 if (n > TMP_MAX_ETH) 138 continue; 139 140 str = ub_env_get(env); 141 142 if (n != 0) { 143 /* 144 * Find the length of the interface id by 145 * taking in to account the first 3 and 146 * last 4 characters. 147 */ 148 i = strlen(env) - 7; 149 strncpy(ethstr + 8, env + 3, i); 150 } 151 152 /* Modify blob */ 153 fdt_fixup_ethernet(str, ethstr, len); 154 155 /* Clear ethernet..XXXX.. string */ 156 bzero(ethstr + 8, len - 8); 157 158 if (n + 1 > eth_no) 159 eth_no = n + 1; 160 } else if (strcmp(env, "consoledev") == 0) { 161 str = ub_env_get(env); 162 fdt_fixup_stdout(str); 163 } 164 } 165 166 /* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */ 167 fdt_fixup_cpubusfreqs(si->clk_cpu, si->clk_bus); 168 169 /* Extract the DRAM regions into fdt_mem_region format. */ 170 for (i = 0, n = 0; i < si->mr_no && n < nitems(regions); i++) { 171 if (si->mr[i].flags == MR_ATTR_DRAM) { 172 regions[n].start = si->mr[i].start; 173 regions[n].size = si->mr[i].size; 174 n++; 175 } 176 } 177 178 /* Fixup memory regions */ 179 fdt_fixup_memory(regions, n); 180 } 181