Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/uboot/uboot_fdt.c
34680 views
1
/*-
2
* Copyright (c) 2009-2010 The FreeBSD Foundation
3
*
4
* This software was developed by Semihalf under sponsorship from
5
* the FreeBSD Foundation.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <stand.h>
31
#include <fdt_platform.h>
32
33
#include "glue.h"
34
35
#define STR(number) #number
36
#define STRINGIFY(number) STR(number)
37
38
static int
39
fdt_platform_load_from_ubenv(const char *var)
40
{
41
struct fdt_header *hdr;
42
const char *s;
43
char *p;
44
45
s = ub_env_get(var);
46
if (s == NULL || *s == '\0')
47
return (1);
48
49
hdr = (struct fdt_header *)strtoul(s, &p, 16);
50
if (*p != '\0')
51
return (1);
52
53
if (fdt_load_dtb_addr(hdr) == 0) {
54
printf("Using DTB provided by U-Boot at "
55
"address %p.\n", hdr);
56
return (0);
57
}
58
59
return (1);
60
}
61
62
#define FDT_DTB_PADSZ 1024
63
64
int
65
fdt_platform_load_dtb(void)
66
{
67
struct fdt_header *hdr;
68
const char *s;
69
char *p;
70
int rv;
71
72
/*
73
* If the U-boot environment contains a variable giving the address of a
74
* valid blob in memory, use it. The U-boot README says the right
75
* variable for fdt data loaded into ram is fdt_addr_r, so try that
76
* first. Board vendors also use both fdtaddr and fdt_addr names.
77
*/
78
if ((rv = fdt_platform_load_from_ubenv("fdt_addr_r")) == 0)
79
goto exit;
80
if ((rv = fdt_platform_load_from_ubenv("fdt_addr")) == 0)
81
goto exit;
82
if ((rv = fdt_platform_load_from_ubenv("fdtaddr")) == 0)
83
goto exit;
84
85
rv = 1;
86
87
/*
88
* Try to get FDT filename first from loader env and then from u-boot env
89
*/
90
s = getenv("fdt_file");
91
if (s == NULL)
92
s = ub_env_get("fdtfile");
93
if (s == NULL)
94
s = ub_env_get("fdt_file");
95
if (s != NULL && *s != '\0') {
96
if (fdt_load_dtb_file(s) == 0) {
97
printf("Loaded DTB from file '%s'.\n", s);
98
rv = 0;
99
goto exit;
100
}
101
}
102
103
exit:
104
return (rv);
105
}
106
107
void
108
fdt_platform_load_overlays(void)
109
{
110
111
fdt_load_dtb_overlays(ub_env_get("fdt_overlays"));
112
}
113
114
void
115
fdt_platform_fixups(void)
116
{
117
static struct fdt_mem_region regions[UB_MAX_MR];
118
const char *env, *str;
119
char *end, *ethstr;
120
int eth_no, i, len, n;
121
struct sys_info *si;
122
123
env = NULL;
124
eth_no = 0;
125
ethstr = NULL;
126
127
/* Apply overlays before anything else */
128
if (fdt_apply_overlays() > 0)
129
fdt_pad_dtb(FDT_DTB_PADSZ);
130
131
/* Acquire sys_info */
132
si = ub_get_sys_info();
133
134
while ((env = ub_env_enum(env)) != NULL) {
135
if (strncmp(env, "eth", 3) == 0 &&
136
strncmp(env + (strlen(env) - 4), "addr", 4) == 0) {
137
/*
138
* Handle Ethernet addrs: parse uboot env eth%daddr
139
*/
140
141
if (!eth_no) {
142
/*
143
* Check how many chars we will need to store
144
* maximal eth iface number.
145
*/
146
len = strlen(STRINGIFY(TMP_MAX_ETH)) +
147
strlen("ethernet") + 1;
148
149
/*
150
* Reserve mem for string "ethernet" and len
151
* chars for iface no.
152
*/
153
ethstr = (char *)malloc(len * sizeof(char));
154
bzero(ethstr, len * sizeof(char));
155
strcpy(ethstr, "ethernet0");
156
}
157
158
/* Extract interface number */
159
i = strtol(env + 3, &end, 10);
160
if (end == (env + 3))
161
/* 'ethaddr' means interface 0 address */
162
n = 0;
163
else
164
n = i;
165
166
if (n > TMP_MAX_ETH)
167
continue;
168
169
str = ub_env_get(env);
170
171
if (n != 0) {
172
/*
173
* Find the length of the interface id by
174
* taking in to account the first 3 and
175
* last 4 characters.
176
*/
177
i = strlen(env) - 7;
178
strncpy(ethstr + 8, env + 3, i);
179
}
180
181
/* Modify blob */
182
fdt_fixup_ethernet(str, ethstr, len);
183
184
/* Clear ethernet..XXXX.. string */
185
bzero(ethstr + 8, len - 8);
186
187
if (n + 1 > eth_no)
188
eth_no = n + 1;
189
} else if (strcmp(env, "consoledev") == 0) {
190
str = ub_env_get(env);
191
fdt_fixup_stdout(str);
192
}
193
}
194
195
/* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */
196
fdt_fixup_cpubusfreqs(si->clk_cpu, si->clk_bus);
197
198
/* Extract the DRAM regions into fdt_mem_region format. */
199
for (i = 0, n = 0; i < si->mr_no && n < nitems(regions); i++) {
200
if (si->mr[i].flags == MR_ATTR_DRAM) {
201
regions[n].start = si->mr[i].start;
202
regions[n].size = si->mr[i].size;
203
n++;
204
}
205
}
206
207
/* Fixup memory regions */
208
fdt_fixup_memory(regions, n);
209
}
210
211