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