uboot_fdt.c revision 283409
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: stable/10/sys/boot/uboot/fdt/uboot_fdt.c 283409 2015-05-24 15:29:56Z ian $"); 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 42int 43fdt_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 * If the U-boot environment contains a variable giving the name of a 73 * file, use it if we can load and validate it. 74 */ 75 s = ub_env_get("fdtfile"); 76 if (s == NULL) 77 s = ub_env_get("fdt_file"); 78 if (s != NULL && *s != '\0') { 79 if (fdt_load_dtb_file(s) == 0) { 80 printf("Loaded DTB from file '%s'.\n", s); 81 return (0); 82 } 83 } 84 85 return (1); 86} 87 88void 89fdt_platform_fixups(void) 90{ 91 static struct fdt_mem_region regions[UB_MAX_MR]; 92 const char *env, *str; 93 char *end, *ethstr; 94 int eth_no, i, len, n; 95 struct sys_info *si; 96 97 env = NULL; 98 eth_no = 0; 99 ethstr = NULL; 100 101 /* Acquire sys_info */ 102 si = ub_get_sys_info(); 103 104 while ((env = ub_env_enum(env)) != NULL) { 105 if (strncmp(env, "eth", 3) == 0 && 106 strncmp(env + (strlen(env) - 4), "addr", 4) == 0) { 107 /* 108 * Handle Ethernet addrs: parse uboot env eth%daddr 109 */ 110 111 if (!eth_no) { 112 /* 113 * Check how many chars we will need to store 114 * maximal eth iface number. 115 */ 116 len = strlen(STRINGIFY(TMP_MAX_ETH)) + 117 strlen("ethernet") + 1; 118 119 /* 120 * Reserve mem for string "ethernet" and len 121 * chars for iface no. 122 */ 123 ethstr = (char *)malloc(len * sizeof(char)); 124 bzero(ethstr, len * sizeof(char)); 125 strcpy(ethstr, "ethernet0"); 126 } 127 128 /* Extract interface number */ 129 i = strtol(env + 3, &end, 10); 130 if (end == (env + 3)) 131 /* 'ethaddr' means interface 0 address */ 132 n = 0; 133 else 134 n = i; 135 136 if (n > TMP_MAX_ETH) 137 continue; 138 139 str = ub_env_get(env); 140 141 if (n != 0) { 142 /* 143 * Find the lenght of the interface id by 144 * taking in to account the first 3 and 145 * last 4 characters. 146 */ 147 i = strlen(env) - 7; 148 strncpy(ethstr + 8, env + 3, i); 149 } 150 151 /* Modify blob */ 152 fdt_fixup_ethernet(str, ethstr, len); 153 154 /* Clear ethernet..XXXX.. string */ 155 bzero(ethstr + 8, len - 8); 156 157 if (n + 1 > eth_no) 158 eth_no = n + 1; 159 } else if (strcmp(env, "consoledev") == 0) { 160 str = ub_env_get(env); 161 fdt_fixup_stdout(str); 162 } 163 } 164 165 /* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */ 166 fdt_fixup_cpubusfreqs(si->clk_cpu, si->clk_bus); 167 168 /* Extract the DRAM regions into fdt_mem_region format. */ 169 for (i = 0, n = 0; i < si->mr_no && n < nitems(regions); i++) { 170 if (si->mr[i].flags == MR_ATTR_DRAM) { 171 regions[n].start = si->mr[i].start; 172 regions[n].size = si->mr[i].size; 173 n++; 174 } 175 } 176 177 /* Fixup memory regions */ 178 fdt_fixup_memory(regions, n); 179} 180