1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/promif.h>
29 #include <sys/bootconf.h>
30 #include <sys/salib.h>
31 #include <sys/boot.h>
32 #include "boot_plat.h"
33
34 char *v2path, *kernname, *systype;
35 char *my_own_name = "boot";
36 char v2args_buf[V2ARGS_BUF_SZ];
37 char *v2args = v2args_buf;
38 extern char *mfg_name;
39 char *impl_arch_name;
40 char *bootp_response;
41 char *module_path;
42 extern int cache_state;
43 uint64_t memlistextent; /* replacement for old member of bootops */
44
45 /* These are the various memory lists */
46 struct memlist *pfreelistp, /* physmem available */
47 *vfreelistp, /* virtmem available */
48 *pinstalledp; /* physmem installed */
49
50 char *boot_message;
51
52 char *netdev_path;
53
54 /*
55 * Support new boot properties "boot-start" and "boot-end" for
56 * Freeze/Thaw project.
57 */
58 caddr_t start_addr, end_addr;
59
60 #define BOOT_BADPROP -1
61 #define BOOT_SUCCESS 0
62 #define BOOT_FAILURE -1
63 #define NIL 0
64
65 #define strequal(p, q) (strcmp((p), (q)) == 0)
66
67
68 /*
69 * This routine is used by stand/lib/$PROC/libnfs.a in case it comes up with a
70 * default filename, and by bootflags() if a default filename is specified in
71 * the boot arguments.
72 */
73 void
set_default_filename(char * filename)74 set_default_filename(char *filename)
75 {
76 kernname = filename;
77 }
78
79
80 static const struct bplist {
81 char *name;
82 void *val;
83 uint_t size;
84 } bprop_tab[] = {
85 "boot-args", &v2args, 0,
86 "boot-path", &v2path, 0,
87 "fstype", &systype, 0,
88 "whoami", &my_own_name, 0,
89 "mfg-name", &mfg_name, 0,
90 "impl-arch-name", &impl_arch_name, 0,
91 "module-path", &module_path, 0,
92 "virt-avail", &vfreelistp, 0,
93 "phys-avail", &pfreelistp, 0,
94 "phys-installed", &pinstalledp, 0,
95 "default-name", &kernname, 0,
96 "extent", &memlistextent, sizeof (memlistextent),
97 "vac", &vac, sizeof (vac),
98 "cache-on?", &cache_state, sizeof (int),
99 "memory-update", 0, 0,
100 "boot-start", &start_addr, sizeof (start_addr),
101 "boot-end", &scratchmemp, sizeof (scratchmemp),
102 "boot-message", &boot_message, 0,
103 "bootp-response", &bootp_response, 0,
104 "netdev-path", &netdev_path, 0,
105 0, 0, 0
106 };
107
108 /*
109 * These routines implement the boot getprop interface.
110 * They are designed to mimic the corresponding devr_{getprop,getproplen}
111 * functions.
112 * The assumptions is that the basic property is an unsigned int. Other
113 * types (including lists) are special cases.
114 */
115
116 /*ARGSUSED*/
117 int
bgetproplen(struct bootops * bop,char * name)118 bgetproplen(struct bootops *bop, char *name)
119 {
120 int size = 0;
121 struct bplist *p;
122 struct memlist *ml;
123
124 /* this prop has side effects only. No length. */
125 if (strequal(name, "memory-update"))
126 return (BOOT_SUCCESS);
127
128 for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) {
129
130 /* got a linked list? */
131 if ((strequal(name, "virt-avail") && strequal(name, p->name)) ||
132 (strequal(name, "phys-avail") && strequal(name, p->name)) ||
133 (strequal(name, "phys-installed") &&
134 strequal(name, p->name))) {
135
136 for (ml = *((struct memlist **)p->val);
137 ml != NIL;
138 ml = ml->ml_next)
139
140 /*
141 * subtract out the ptrs for our local
142 * linked list. The application will
143 * only see an array.
144 */
145 size += (int)(sizeof (struct memlist) -
146 2*sizeof (struct memlist *));
147 return (size);
148
149 } else if (strequal(name, p->name)) {
150
151 /* if we already know the size, return it */
152 if (p->size != 0)
153 return (p->size);
154 else {
155 if (*((char **)p->val) == NIL)
156 return (0); /* NULL is allowed */
157
158 /* don't forget the null termination */
159 return (strlen(*((char **)p->val)) + 1);
160 }
161 }
162 }
163 return (BOOT_BADPROP);
164 }
165
166 /*ARGSUSED*/
167 int
bgetprop(struct bootops * bop,char * name,void * buf)168 bgetprop(struct bootops *bop, char *name, void *buf)
169 {
170 struct bplist *p;
171 struct memlist *ml;
172
173 if (strequal(name, "memory-update")) {
174 /*
175 * dprintf("bgetprop: updating memlists.\n");
176 */
177 update_memlist("virtual-memory", "available", &vfreelistp);
178 update_memlist("memory", "available", &pfreelistp);
179 return (BOOT_SUCCESS);
180 }
181
182 if (strequal(name, "boot-start")) {
183 start_addr = (caddr_t)_start;
184 bcopy((char *)(&start_addr), buf, sizeof (start_addr));
185 return (BOOT_SUCCESS);
186 }
187
188 if (strequal(name, "boot-end")) {
189 /*
190 * The true end of boot should be scratchmemp,
191 * boot gets its dynamic memory from the scratchmem
192 * which is the first 4M of the physical memory,
193 * and they are mapped 1:1.
194 */
195 end_addr = scratchmemp;
196 bcopy((char *)(&end_addr), buf, sizeof (scratchmemp));
197 return (BOOT_SUCCESS);
198 }
199
200 for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) {
201
202 /* gotta linked list? */
203 if ((strequal(name, "virt-avail") && strequal(name, p->name)) ||
204 (strequal(name, "phys-avail") && strequal(name, p->name)) ||
205 (strequal(name, "phys-installed") &&
206 strequal(name, p->name))) {
207
208 u_longlong_t *t = buf;
209
210 for (ml = *((struct memlist **)p->val);
211 ml != NIL;
212 ml = ml->ml_next) {
213
214 /* copy out into an array */
215 *t++ = ml->ml_address;
216 *t++ = ml->ml_size;
217 }
218 return (BOOT_SUCCESS);
219 } else if (strequal(name, p->name)) {
220 if (p->size != 0) {
221 bcopy(p->val, buf, p->size);
222 } else {
223 (void) strcpy((char *)buf, *((char **)p->val));
224 }
225 return (BOOT_SUCCESS);
226 }
227 }
228 return (BOOT_FAILURE);
229 }
230
231 /*
232 * If the user wants the first property in the list, they pass in a
233 * null string. The routine will always return a ptr to the name of the
234 * next prop, except when there are no more props. In that case, it will
235 * return a null string.
236 */
237
238 /*ARGSUSED*/
239 char *
bnextprop(struct bootops * bop,char * prev)240 bnextprop(struct bootops *bop, char *prev)
241 {
242 struct bplist *p;
243
244 /* user wants the firstprop */
245 if (*prev == 0)
246 return (bprop_tab->name);
247
248 for (p = (struct bplist *)bprop_tab; p->name != (char *)0; p++) {
249
250 if (strequal(prev, p->name))
251 /*
252 * if prev is the last valid prop,
253 * we will return our terminator (0).
254 */
255 return ((++p)->name);
256
257
258 }
259 return ((char *)0);
260 }
261