2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2003 Jake Burkholder.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/errno.h>
37 #include <sys/fcntl.h>
38 #include <sys/ioccom.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
43 #include <dev/ofw/openfirm.h>
44 #include <dev/ofw/openpromio.h>
47 * This provides a Solaris compatible character device interface to
48 * Open Firmware. It exists entirely for compatibility with software
49 * like X11, and only the features that are actually needed for that
50 * are implemented. The interface sucks too much to actually use,
51 * new code should use the /dev/openfirm device.
54 static d_open_t openprom_open;
55 static d_close_t openprom_close;
56 static d_ioctl_t openprom_ioctl;
58 static int openprom_modevent(module_t mode, int type, void *data);
59 static int openprom_node_valid(phandle_t node);
60 static int openprom_node_search(phandle_t root, phandle_t node);
62 static struct cdevsw openprom_cdevsw = {
63 .d_version = D_VERSION,
64 .d_flags = D_NEEDGIANT,
65 .d_open = openprom_open,
66 .d_close = openprom_close,
67 .d_ioctl = openprom_ioctl,
71 static int openprom_is_open;
72 static struct cdev *openprom_dev;
73 static phandle_t openprom_node;
76 openprom_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
79 if (openprom_is_open != 0)
86 openprom_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
94 openprom_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
97 struct openpromio *oprom;
106 if ((flags & FREAD) == 0)
114 if (data == NULL || *(void **)data == NULL)
116 oprom = *(void **)data;
117 error = copyin(&oprom->oprom_size, &len, sizeof(len));
120 if (len != sizeof(node)) {
124 error = copyin(&oprom->oprom_array, &node, sizeof(node));
127 error = openprom_node_valid(node);
132 node = OF_child(node);
135 node = OF_peer(node);
138 error = copyout(&node, &oprom->oprom_array, sizeof(node));
141 openprom_node = node;
145 if (data == NULL || *(void **)data == NULL)
147 oprom = *(void **)data;
148 error = copyin(&oprom->oprom_size, &len, sizeof(len));
151 if (len > OPROMMAXPARAM) {
155 prop = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
156 error = copyinstr(&oprom->oprom_array, prop, len, &done);
159 buf = malloc(OPROMMAXPARAM, M_TEMP, M_WAITOK | M_ZERO);
160 node = openprom_node;
163 proplen = OF_getproplen(node, prop);
164 if (proplen > OPROMMAXPARAM) {
168 error = OF_getprop(node, prop, buf, proplen);
171 error = OF_nextprop(node, prop, buf, OPROMMAXPARAM);
172 proplen = strlen(buf);
176 error = copyout(&proplen, &oprom->oprom_size,
179 error = copyout(buf, &oprom->oprom_array,
198 openprom_node_valid(phandle_t node)
203 return (openprom_node_search(OF_peer(0), node));
207 openprom_node_search(phandle_t root, phandle_t node)
213 for (child = OF_child(root); child != 0 && child != -1;
214 child = OF_peer(child))
215 if (openprom_node_search(child, node) == 0)
221 openprom_modevent(module_t mode, int type, void *data)
226 openprom_dev = make_dev(&openprom_cdevsw, 0, UID_ROOT,
227 GID_WHEEL, 0600, "openprom");
230 destroy_dev(openprom_dev);
237 DEV_MODULE(openprom, openprom_modevent, NULL);