No empty .Rs/.Re
[netbsd-mini2440.git] / common / lib / libprop / prop_kern.c
blobc1bf4e2ce0fd3e1944a9ab102052ddc59e7f59d8
1 /* $NetBSD: prop_kern.c,v 1.12 2009/10/10 21:27:46 christos Exp $ */
3 /*-
4 * Copyright (c) 2006, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if defined(__NetBSD__)
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
37 #include <prop/proplib.h>
39 #if !defined(_KERNEL) && !defined(_STANDALONE)
40 #include <sys/mman.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stdio.h>
46 static int
47 _prop_object_externalize_to_pref(prop_object_t obj, struct plistref *pref, char **bufp)
49 char *buf;
51 switch (prop_object_type(obj)) {
52 case PROP_TYPE_DICTIONARY:
53 buf = prop_dictionary_externalize(obj);
54 break;
55 case PROP_TYPE_ARRAY:
56 buf = prop_array_externalize(obj);
57 break;
58 default:
59 return (ENOTSUP);
61 if (buf == NULL) {
62 /* Assume we ran out of memory. */
63 return (ENOMEM);
65 pref->pref_plist = buf;
66 pref->pref_len = strlen(buf) + 1;
68 *bufp = buf;
70 return (0);
74 * prop_array_externalize_to_pref --
75 * Externalize an array into a plistref for sending to the kernel.
77 bool
78 prop_array_externalize_to_pref(prop_array_t array, struct plistref *prefp)
80 char *buf;
81 int rv;
83 rv = _prop_object_externalize_to_pref(array, prefp, &buf);
84 if (rv != 0)
85 errno = rv; /* pass up error value in errno */
86 return (rv == 0);
90 * prop_dictionary_externalize_to_pref --
91 * Externalize an dictionary into a plistref for sending to the kernel.
93 bool
94 prop_dictionary_externalize_to_pref(prop_dictionary_t dict, struct plistref *prefp)
96 char *buf;
97 int rv;
99 rv = _prop_object_externalize_to_pref(dict, prefp, &buf);
100 if (rv != 0)
101 errno = rv; /* pass up error value in errno */
102 return (rv == 0);
105 static int
106 _prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
108 struct plistref pref;
109 char *buf;
110 int error;
112 error = _prop_object_externalize_to_pref(obj, &pref, &buf);
113 if (error)
114 return (error);
116 if (ioctl(fd, cmd, &pref) == -1)
117 error = errno;
118 else
119 error = 0;
121 free(buf);
123 return (error);
127 * prop_array_send_ioctl --
128 * Send an array to the kernel using the specified ioctl.
131 prop_array_send_ioctl(prop_array_t array, int fd, unsigned long cmd)
134 return (_prop_object_send_ioctl(array, fd, cmd));
138 * prop_dictionary_send_ioctl --
139 * Send a dictionary to the kernel using the specified ioctl.
142 prop_dictionary_send_ioctl(prop_dictionary_t dict, int fd, unsigned long cmd)
145 return (_prop_object_send_ioctl(dict, fd, cmd));
148 static int
149 _prop_object_internalize_from_pref(const struct plistref *pref, prop_type_t type,
150 prop_object_t *objp)
152 prop_object_t obj = NULL;
153 char *buf;
154 int error = 0;
156 if (pref->pref_len == 0) {
158 * This should never happen; we should always get the XML
159 * for an empty dictionary if it's really empty.
161 error = EIO;
162 goto out;
163 } else {
164 buf = pref->pref_plist;
165 buf[pref->pref_len - 1] = '\0'; /* extra insurance */
166 switch (type) {
167 case PROP_TYPE_DICTIONARY:
168 obj = prop_dictionary_internalize(buf);
169 break;
170 case PROP_TYPE_ARRAY:
171 obj = prop_array_internalize(buf);
172 break;
173 default:
174 error = ENOTSUP;
176 (void) munmap(buf, pref->pref_len);
177 if (obj == NULL && error == 0)
178 error = EIO;
181 out:
182 if (error == 0)
183 *objp = obj;
184 return (error);
188 * prop_array_recv_ioctl --
189 * Receive an array from the kernel using the specified ioctl.
192 prop_array_recv_ioctl(int fd, unsigned long cmd, prop_array_t *arrayp)
194 struct plistref pref;
196 if (ioctl(fd, cmd, &pref) == -1)
197 return (errno);
199 return (_prop_object_internalize_from_pref(&pref, PROP_TYPE_ARRAY,
200 (prop_object_t *)arrayp));
204 * prop_dictionary_recv_ioctl --
205 * Receive a dictionary from the kernel using the specified ioctl.
208 prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
210 struct plistref pref;
212 if (ioctl(fd, cmd, &pref) == -1)
213 return (errno);
215 return (_prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
216 (prop_object_t *)dictp));
220 * prop_dictionary_sendrecv_ioctl --
221 * Combination send/receive a dictionary to/from the kernel using
222 * the specified ioctl.
225 prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict, int fd,
226 unsigned long cmd, prop_dictionary_t *dictp)
228 struct plistref pref;
229 char *buf;
230 int error;
232 error = _prop_object_externalize_to_pref(dict, &pref, &buf);
233 if (error)
234 return (error);
236 if (ioctl(fd, cmd, &pref) == -1)
237 error = errno;
238 else
239 error = 0;
241 free(buf);
243 if (error)
244 return (error);
246 return (_prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
247 (prop_object_t *)dictp));
249 #endif /* !_KERNEL && !_STANDALONE */
251 #if defined(_KERNEL)
252 #include <sys/param.h>
253 #include <sys/mman.h>
254 #include <sys/errno.h>
255 #include <sys/malloc.h>
256 #include <sys/systm.h>
257 #include <sys/proc.h>
258 #include <sys/resource.h>
259 #include <sys/pool.h>
261 #include <uvm/uvm.h>
263 #include "prop_object_impl.h"
265 /* Arbitrary limit ioctl input to 64KB */
266 unsigned int prop_object_copyin_limit = 65536;
268 /* initialize proplib for use in the kernel */
269 void
270 prop_kern_init(void)
272 __link_set_decl(prop_linkpools, struct prop_pool_init);
273 struct prop_pool_init * const *pi;
275 __link_set_foreach(pi, prop_linkpools)
276 pool_init((*pi)->pp, (*pi)->size, 0, 0, 0, (*pi)->wchan,
277 &pool_allocator_nointr, IPL_NONE);
280 static int
281 _prop_object_copyin(const struct plistref *pref, const prop_type_t type,
282 prop_object_t *objp)
284 prop_object_t obj = NULL;
285 char *buf;
286 int error;
289 * Allocate an extra byte so we can guarantee NUL-termination.
291 * Allow malloc to fail in case pmap would be exhausted.
293 buf = malloc(pref->pref_len + 1, M_TEMP, M_WAITOK | M_CANFAIL);
294 if (buf == NULL)
295 return (ENOMEM);
296 error = copyin(pref->pref_plist, buf, pref->pref_len);
297 if (error) {
298 free(buf, M_TEMP);
299 return (error);
301 buf[pref->pref_len] = '\0';
303 switch (type) {
304 case PROP_TYPE_ARRAY:
305 obj = prop_array_internalize(buf);
306 break;
307 case PROP_TYPE_DICTIONARY:
308 obj = prop_dictionary_internalize(buf);
309 break;
310 default:
311 error = ENOTSUP;
314 free(buf, M_TEMP);
315 if (obj == NULL) {
316 if (error == 0)
317 error = EIO;
318 } else {
319 *objp = obj;
321 return (error);
325 static int
326 _prop_object_copyin_ioctl(const struct plistref *pref, const prop_type_t type,
327 const u_long cmd, prop_object_t *objp)
329 if ((cmd & IOC_IN) == 0)
330 return (EFAULT);
332 return _prop_object_copyin(pref, type, objp);
336 * prop_array_copyin --
337 * Copy in an array passed as a syscall arg.
340 prop_array_copyin(const struct plistref *pref, prop_array_t *arrayp)
342 return (_prop_object_copyin(pref, PROP_TYPE_ARRAY,
343 (prop_object_t *)arrayp));
347 * prop_dictionary_copyin --
348 * Copy in a dictionary passed as a syscall arg.
351 prop_dictionary_copyin(const struct plistref *pref, prop_dictionary_t *dictp)
353 return (_prop_object_copyin(pref, PROP_TYPE_DICTIONARY,
354 (prop_object_t *)dictp));
359 * prop_array_copyin_ioctl --
360 * Copy in an array send with an ioctl.
363 prop_array_copyin_ioctl(const struct plistref *pref, const u_long cmd,
364 prop_array_t *arrayp)
366 return (_prop_object_copyin_ioctl(pref, PROP_TYPE_ARRAY,
367 cmd, (prop_object_t *)arrayp));
371 * prop_dictionary_copyin_ioctl --
372 * Copy in a dictionary sent with an ioctl.
375 prop_dictionary_copyin_ioctl(const struct plistref *pref, const u_long cmd,
376 prop_dictionary_t *dictp)
378 return (_prop_object_copyin_ioctl(pref, PROP_TYPE_DICTIONARY,
379 cmd, (prop_object_t *)dictp));
382 static int
383 _prop_object_copyout_ioctl(struct plistref *pref, const u_long cmd,
384 prop_object_t obj)
386 struct lwp *l = curlwp; /* XXX */
387 struct proc *p = l->l_proc;
388 char *buf;
389 size_t len, rlen;
390 int error = 0;
391 vaddr_t uaddr;
393 if ((cmd & IOC_OUT) == 0)
394 return (EFAULT);
396 switch (prop_object_type(obj)) {
397 case PROP_TYPE_ARRAY:
398 buf = prop_array_externalize(obj);
399 break;
400 case PROP_TYPE_DICTIONARY:
401 buf = prop_dictionary_externalize(obj);
402 break;
403 default:
404 return (ENOTSUP);
406 if (buf == NULL)
407 return (ENOMEM);
409 len = strlen(buf) + 1;
410 rlen = round_page(len);
413 * See sys_mmap() in sys/uvm/uvm_mmap.c.
414 * Let's act as if we were calling mmap(0, ...)
416 uaddr = p->p_emul->e_vm_default_addr(p,
417 (vaddr_t)p->p_vmspace->vm_daddr, rlen);
419 error = uvm_mmap(&p->p_vmspace->vm_map,
420 &uaddr, rlen,
421 VM_PROT_READ|VM_PROT_WRITE,
422 VM_PROT_READ|VM_PROT_WRITE,
423 MAP_PRIVATE|MAP_ANON,
424 NULL, 0,
425 p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
427 if (error == 0) {
428 error = copyout(buf, (char *)uaddr, len);
429 if (error == 0) {
430 pref->pref_plist = (char *)uaddr;
431 pref->pref_len = len;
435 free(buf, M_TEMP);
437 return (error);
441 * prop_array_copyout_ioctl --
442 * Copy out an array being received with an ioctl.
445 prop_array_copyout_ioctl(struct plistref *pref, const u_long cmd,
446 prop_array_t array)
448 return (_prop_object_copyout_ioctl(pref, cmd, array));
452 * prop_dictionary_copyout_ioctl --
453 * Copy out a dictionary being received with an ioctl.
456 prop_dictionary_copyout_ioctl(struct plistref *pref, const u_long cmd,
457 prop_dictionary_t dict)
459 return (_prop_object_copyout_ioctl(pref, cmd, dict));
461 #endif /* _KERNEL */
463 #endif /* __NetBSD__ */