Print this page
11927 Log, or optionally panic, on zero-length kmem allocations
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/intel/promif/prom_emul.c
+++ new/usr/src/uts/intel/promif/prom_emul.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
27 +/*
28 + * Copyright (c) 2015 Joyent, Inc. All rights reserved.
29 + */
28 30
29 31 #include <sys/promif.h>
30 32 #include <sys/promimpl.h>
31 33 #include <sys/prom_emul.h>
32 34 #include <sys/obpdefs.h>
33 35 #include <sys/sunddi.h>
34 36
35 37 static prom_node_t *promif_top;
36 38
37 39 static prom_node_t *promif_find_node(pnode_t nodeid);
38 40 static int getproplen(prom_node_t *pnp, char *name);
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
39 41 static void *getprop(prom_node_t *pnp, char *name);
40 42
41 43 static void
42 44 promif_create_prop(prom_node_t *pnp, char *name, void *val, int len, int flags)
43 45 {
44 46 struct prom_prop *p, *q;
45 47
46 48 q = kmem_zalloc(sizeof (*q), KM_SLEEP);
47 49 q->pp_name = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
48 50 (void) strcpy(q->pp_name, name);
49 - q->pp_val = kmem_alloc(len, KM_SLEEP);
51 + q->pp_val = len > 0 ? kmem_alloc(len, KM_SLEEP) : NULL;
50 52 q->pp_len = len;
51 53 switch (flags) {
52 54 case DDI_PROP_TYPE_INT:
53 55 case DDI_PROP_TYPE_INT64:
54 56 /*
55 57 * Technically, we need byte-swapping to conform to 1275.
56 58 * However, the old x86 prom simulator used little endian
57 59 * representation, so we don't swap here either.
58 60 *
59 61 * NOTE: this is inconsistent with ddi_prop_lookup_*()
60 62 * which does byte-swapping when looking up prom properties.
61 63 * Since all kernel nodes are SID nodes, drivers no longer
62 64 * access PROM properties on x86.
63 65 */
64 66 default: /* no byte swapping */
65 67 (void) bcopy(val, q->pp_val, len);
66 68 break;
67 69 }
68 70
69 71 if (pnp->pn_propp == NULL) {
70 72 pnp->pn_propp = q;
71 73 return;
72 74 }
73 75
74 76 for (p = pnp->pn_propp; p->pp_next != NULL; p = p->pp_next)
75 77 /* empty */;
76 78
77 79 p->pp_next = q;
78 80 }
79 81
80 82 static prom_node_t *
81 83 promif_create_node(dev_info_t *dip)
82 84 {
83 85 prom_node_t *pnp;
84 86 ddi_prop_t *hwprop;
85 87 char *nodename;
86 88
87 89 pnp = kmem_zalloc(sizeof (prom_node_t), KM_SLEEP);
88 90 pnp->pn_nodeid = DEVI(dip)->devi_nodeid;
89 91
90 92 hwprop = DEVI(dip)->devi_hw_prop_ptr;
91 93 while (hwprop != NULL) {
92 94 /* need to encode to proper endianness */
93 95 promif_create_prop(pnp, hwprop->prop_name, hwprop->prop_val,
94 96 hwprop->prop_len, hwprop->prop_flags & DDI_PROP_TYPE_MASK);
95 97 hwprop = hwprop->prop_next;
96 98 }
97 99 nodename = ddi_node_name(dip);
98 100 promif_create_prop(pnp, "name", nodename, strlen(nodename) + 1,
99 101 DDI_PROP_TYPE_STRING);
100 102
101 103 return (pnp);
102 104 }
103 105
104 106 static void promif_create_children(prom_node_t *, dev_info_t *);
105 107
106 108 static void
107 109 promif_create_peers(prom_node_t *pnp, dev_info_t *dip)
108 110 {
109 111 dev_info_t *ndip = ddi_get_next_sibling(dip);
110 112
111 113 while (ndip) {
112 114 pnp->pn_sibling = promif_create_node(ndip);
113 115 promif_create_children(pnp->pn_sibling, ndip);
114 116 pnp = pnp->pn_sibling;
115 117 ndip = ddi_get_next_sibling(ndip);
116 118 }
117 119 }
118 120
119 121 static void
120 122 promif_create_children(prom_node_t *pnp, dev_info_t *dip)
121 123 {
122 124 dev_info_t *cdip = ddi_get_child(dip);
123 125
124 126 while (cdip) {
125 127 pnp->pn_child = promif_create_node(cdip);
126 128 promif_create_peers(pnp->pn_child, cdip);
127 129 pnp = pnp->pn_child;
128 130 cdip = ddi_get_child(cdip);
129 131 }
130 132 }
131 133
132 134 void
133 135 promif_create_device_tree(void)
134 136 {
135 137 promif_top = promif_create_node(ddi_root_node());
136 138 promif_create_children(promif_top, ddi_root_node());
137 139 }
138 140
139 141 static prom_node_t *
140 142 find_node_work(prom_node_t *pnp, pnode_t n)
141 143 {
142 144 prom_node_t *qnp;
143 145
144 146 if (pnp->pn_nodeid == n)
145 147 return (pnp);
146 148
147 149 if (pnp->pn_child)
148 150 if ((qnp = find_node_work(pnp->pn_child, n)) != NULL)
149 151 return (qnp);
150 152
151 153 if (pnp->pn_sibling)
152 154 if ((qnp = find_node_work(pnp->pn_sibling, n)) != NULL)
153 155 return (qnp);
154 156
155 157 return (NULL);
156 158 }
157 159
158 160 static prom_node_t *
159 161 promif_find_node(pnode_t nodeid)
160 162 {
161 163 if (nodeid == OBP_NONODE)
162 164 return (promif_top);
163 165
164 166 if (promif_top == NULL)
165 167 return (NULL);
166 168
167 169 return (find_node_work(promif_top, nodeid));
168 170 }
169 171
170 172 pnode_t
171 173 promif_nextnode(pnode_t nodeid)
172 174 {
173 175 prom_node_t *pnp;
174 176
175 177 /*
176 178 * Note: next(0) returns the root node
177 179 */
178 180 pnp = promif_find_node(nodeid);
179 181 if (pnp && (nodeid == OBP_NONODE))
180 182 return (pnp->pn_nodeid);
181 183 if (pnp && pnp->pn_sibling)
182 184 return (pnp->pn_sibling->pn_nodeid);
183 185
184 186 return (OBP_NONODE);
185 187 }
186 188
187 189 pnode_t
188 190 promif_childnode(pnode_t nodeid)
189 191 {
190 192 prom_node_t *pnp;
191 193
192 194 pnp = promif_find_node(nodeid);
193 195 if (pnp && pnp->pn_child)
194 196 return (pnp->pn_child->pn_nodeid);
195 197
196 198 return (OBP_NONODE);
197 199 }
198 200
199 201 /*
200 202 * Retrieve a PROM property (len and value)
201 203 */
202 204
203 205 static int
204 206 getproplen(prom_node_t *pnp, char *name)
205 207 {
206 208 struct prom_prop *propp;
207 209
208 210 for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
209 211 if (strcmp(propp->pp_name, name) == 0)
210 212 return (propp->pp_len);
211 213
212 214 return (-1);
213 215 }
214 216
215 217 int
216 218 promif_getproplen(pnode_t nodeid, char *name)
217 219 {
218 220 prom_node_t *pnp;
219 221
220 222 pnp = promif_find_node(nodeid);
221 223 if (pnp == NULL)
222 224 return (-1);
223 225
224 226 return (getproplen(pnp, name));
225 227 }
226 228
227 229 static void *
228 230 getprop(prom_node_t *pnp, char *name)
229 231 {
230 232 struct prom_prop *propp;
231 233
232 234 for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
233 235 if (strcmp(propp->pp_name, name) == 0)
234 236 return (propp->pp_val);
235 237
236 238 return (NULL);
237 239 }
238 240
239 241 int
240 242 promif_getprop(pnode_t nodeid, char *name, void *value)
241 243 {
242 244 prom_node_t *pnp;
243 245 void *v;
244 246 int len;
245 247
246 248 pnp = promif_find_node(nodeid);
247 249 if (pnp == NULL)
248 250 return (-1);
249 251
250 252 len = getproplen(pnp, name);
251 253 if (len > 0) {
252 254 v = getprop(pnp, name);
253 255 bcopy(v, value, len);
254 256 }
255 257 return (len);
256 258 }
257 259
258 260 static char *
259 261 nextprop(prom_node_t *pnp, char *name)
260 262 {
261 263 struct prom_prop *propp;
262 264
263 265 /*
264 266 * getting next of NULL or a null string returns the first prop name
265 267 */
266 268 if (name == NULL || *name == '\0')
267 269 if (pnp->pn_propp)
268 270 return (pnp->pn_propp->pp_name);
269 271
270 272 for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
271 273 if (strcmp(propp->pp_name, name) == 0)
272 274 if (propp->pp_next)
273 275 return (propp->pp_next->pp_name);
274 276
275 277 return (NULL);
276 278 }
277 279
278 280 char *
279 281 promif_nextprop(pnode_t nodeid, char *name, char *next)
280 282 {
281 283 prom_node_t *pnp;
282 284 char *s;
283 285
284 286 next[0] = '\0';
285 287
286 288 pnp = promif_find_node(nodeid);
287 289 if (pnp == NULL)
288 290 return (NULL);
289 291
290 292 s = nextprop(pnp, name);
291 293 if (s == NULL)
292 294 return (next);
293 295
294 296 (void) strcpy(next, s);
295 297 return (next);
296 298 }
|
↓ open down ↓ |
237 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX