Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / compat / mach / mach_iokit.c
blob500a824d142cc866b977fee211fce39b9f8c4edd
1 /* $NetBSD: mach_iokit.c,v 1.35 2007/12/08 18:36:14 dsl Exp $ */
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
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 #include "opt_compat_darwin.h"
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: mach_iokit.c,v 1.35 2007/12/08 18:36:14 dsl Exp $");
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/signal.h>
41 #include <sys/mount.h>
42 #include <sys/proc.h>
43 #include <sys/ktrace.h>
44 #include <sys/device.h>
45 #include <compat/mach/mach_types.h>
46 #include <compat/mach/mach_message.h>
47 #include <compat/mach/mach_port.h>
48 #include <compat/mach/mach_errno.h>
49 #include <compat/mach/mach_iokit.h>
50 #include <compat/mach/mach_services.h>
52 #ifdef COMPAT_DARWIN
53 #include <compat/darwin/darwin_iokit.h>
54 #endif
56 struct mach_iokit_devclass mach_ioroot_devclass = {
57 "(unknwon)",
58 { NULL },
59 "<dict ID=\"0\"></dict>",
60 NULL,
61 NULL,
62 NULL,
63 NULL,
64 NULL,
65 NULL,
66 "Root",
67 NULL,
70 struct mach_iokit_devclass *mach_iokit_devclasses[] = {
71 &mach_ioroot_devclass,
72 #ifdef COMPAT_DARWIN
73 DARWIN_IOKIT_DEVCLASSES
74 #endif
75 NULL,
79 static int mach_fill_child_iterator(struct mach_device_iterator *, int, int,
80 struct mach_iokit_devclass *);
81 static int mach_fill_parent_iterator(struct mach_device_iterator *, int, int,
82 struct mach_iokit_devclass *);
84 int
85 mach_io_service_get_matching_services(struct mach_trap_args *args)
87 mach_io_service_get_matching_services_request_t *req = args->smsg;
88 mach_io_service_get_matching_services_reply_t *rep = args->rmsg;
89 size_t *msglen = args->rsize;
90 struct lwp *l = args->l;
91 struct mach_port *mp;
92 struct mach_right *mr;
93 struct mach_iokit_devclass *mid;
94 struct mach_device_iterator *mdi;
95 size_t size;
96 int end_offset;
97 int i;
99 /* Sanity check req_size */
100 end_offset = req->req_size;
101 if (MACH_REQMSG_OVERFLOW(args, req->req_string[end_offset]))
102 return mach_msg_error(args, EINVAL);
104 mp = mach_port_get();
105 mp->mp_flags |= MACH_MP_INKERNEL;
106 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
108 mp->mp_data = NULL;
109 i = 0;
110 while ((mid = mach_iokit_devclasses[i++]) != NULL) {
111 if (memcmp(req->req_string, mid->mid_string,
112 req->req_size) == 0) {
113 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
115 size = sizeof(*mdi)
116 + sizeof(struct mach_device_iterator *);
117 mdi = malloc(size, M_EMULDATA, M_WAITOK);
118 mdi->mdi_devices[0] = mid;
119 mdi->mdi_devices[1] = NULL;
120 mdi->mdi_current = 0;
122 mp->mp_data = mdi;
123 break;
127 if (mp->mp_data == NULL)
128 return mach_iokit_error(args, MACH_IOKIT_ENOENT);
130 *msglen = sizeof(*rep);
131 mach_set_header(rep, req, *msglen);
132 mach_add_port_desc(rep, mr->mr_name);
133 mach_set_trailer(rep, *msglen);
135 return 0;
139 mach_io_iterator_next(struct mach_trap_args *args)
141 mach_io_iterator_next_request_t *req = args->smsg;
142 mach_io_iterator_next_reply_t *rep = args->rmsg;
143 size_t *msglen = args->rsize;
144 struct lwp *l = args->l;
145 struct mach_port *mp;
146 struct mach_right *mr;
147 struct mach_device_iterator *mdi;
148 mach_port_t mn;
150 mn = req->req_msgh.msgh_remote_port;
151 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
152 return mach_iokit_error(args, MACH_IOKIT_EPERM);
154 if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR)
155 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
157 mdi = mr->mr_port->mp_data;
159 /* Is there something coming next? */
160 if (mdi->mdi_devices[mdi->mdi_current] == NULL)
161 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
163 mp = mach_port_get();
164 mp->mp_flags |= MACH_MP_INKERNEL;
165 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
166 mp->mp_data = mdi->mdi_devices[mdi->mdi_current++];
168 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
170 *msglen = sizeof(*rep);
171 mach_set_header(rep, req, *msglen);
172 mach_add_port_desc(rep, mr->mr_name);
173 mach_set_trailer(rep, *msglen);
175 return 0;
179 mach_io_service_open(struct mach_trap_args *args)
181 mach_io_service_open_request_t *req = args->smsg;
182 mach_io_service_open_reply_t *rep = args->rmsg;
183 size_t *msglen = args->rsize;
184 struct lwp *l = args->l;
185 struct mach_port *mp;
186 struct mach_right *mr;
187 mach_port_t mn;
189 mn = req->req_msgh.msgh_remote_port;
190 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
191 return mach_iokit_error(args, MACH_IOKIT_EPERM);
193 mp = mach_port_get();
194 mp->mp_flags |= MACH_MP_INKERNEL;
195 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
196 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
197 mp->mp_data = mr->mr_port->mp_data;
199 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
201 *msglen = sizeof(*rep);
202 mach_set_header(rep, req, *msglen);
203 mach_add_port_desc(rep, mr->mr_name);
204 mach_set_trailer(rep, *msglen);
206 return 0;
210 mach_io_connect_method_scalari_scalaro(struct mach_trap_args *args)
212 mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg;
213 struct lwp *l = args->l;
214 mach_port_t mn;
215 struct mach_right *mr;
216 struct mach_iokit_devclass *mid;
217 int end_offset, outcount;
220 * Sanity check req_incount
221 * the +1 gives us the last field of the message, req_outcount
223 end_offset = req->req_incount +
224 (sizeof(req->req_outcount) / sizeof(req->req_in[0]));
225 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
226 return mach_msg_error(args, EINVAL);
228 /* Sanity check req->req_outcount */
229 outcount = req->req_in[req->req_incount];
230 if (outcount > 16)
231 return mach_msg_error(args, EINVAL);
233 mn = req->req_msgh.msgh_remote_port;
234 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
235 return mach_iokit_error(args, MACH_IOKIT_EPERM);
237 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
238 mid = mr->mr_port->mp_data;
239 if (mid->mid_connect_method_scalari_scalaro == NULL)
240 printf("no connect_method_scalari_scalaro method "
241 "for darwin_iokit_class %s\n", mid->mid_name);
242 else
243 return (mid->mid_connect_method_scalari_scalaro)(args);
246 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
250 mach_io_connect_get_service(struct mach_trap_args *args)
252 mach_io_connect_get_service_request_t *req = args->smsg;
253 mach_io_connect_get_service_reply_t *rep = args->rmsg;
254 size_t *msglen = args->rsize;
255 struct lwp *l = args->l;
256 struct mach_port *mp;
257 struct mach_right *mr;
258 mach_port_t mn;
260 mn = req->req_msgh.msgh_remote_port;
261 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
262 return mach_iokit_error(args, MACH_IOKIT_EPERM);
264 mp = mach_port_get();
265 mp->mp_flags |= MACH_MP_INKERNEL;
266 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
267 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
268 mp->mp_data = mr->mr_port->mp_data;
270 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
273 * XXX Bump the refcount to workaround an emulation bug
274 * that causes Windowserver to release the port too early.
276 mr->mr_refcount++;
278 *msglen = sizeof(*rep);
279 mach_set_header(rep, req, *msglen);
280 mach_add_port_desc(rep, mr->mr_name);
281 mach_set_trailer(rep, *msglen);
283 return 0;
287 mach_io_registry_entry_create_iterator(struct mach_trap_args *args)
289 mach_io_registry_entry_create_iterator_request_t *req = args->smsg;
290 mach_io_registry_entry_create_iterator_reply_t *rep = args->rmsg;
291 size_t *msglen = args->rsize;
292 struct lwp *l = args->l;
293 struct mach_port *mp;
294 mach_port_t mn;
295 struct mach_right *mr;
296 struct mach_iokit_devclass *mid;
297 struct mach_device_iterator *mdi;
298 struct mach_iokit_devclass **midp;
299 int maxdev, index;
300 size_t size;
301 int end_offset;
304 * req_planeoffset is not used.
305 * Sanity check req_planecount
307 end_offset = req->req_planecount +
308 (sizeof(req->req_options) / sizeof(req->req_plane[0]));
309 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
310 return mach_msg_error(args, EINVAL);
312 mn = req->req_msgh.msgh_remote_port;
313 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
314 return mach_iokit_error(args, MACH_IOKIT_EPERM);
315 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
316 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
317 mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
319 mp = mach_port_get();
320 mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
321 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
323 maxdev = sizeof(mach_iokit_devclasses);
324 size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
325 mdi = malloc(size, M_EMULDATA, M_WAITOK);
326 mp->mp_data = mdi;
328 if (req->req_options & MACH_IOKIT_PARENT_ITERATOR)
329 index = mach_fill_parent_iterator(mdi, maxdev, 0, mid);
330 else
331 index = mach_fill_child_iterator(mdi, maxdev, 0, mid);
333 /* XXX This is untested */
334 if (req->req_options & MACH_IOKIT_RECURSIVE_ITERATOR) {
335 for (midp = mdi->mdi_devices; *midp != NULL; midp++) {
336 if (req->req_options & MACH_IOKIT_PARENT_ITERATOR)
337 index = mach_fill_parent_iterator(mdi,
338 maxdev, index, *midp);
339 else
340 index = mach_fill_child_iterator(mdi,
341 maxdev, index, *midp);
345 mdi->mdi_current = 0;
347 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
349 #ifdef DEBUG_MACH
350 printf("io_registry_entry_create_iterator\n");
351 #endif
353 *msglen = sizeof(*rep);
354 mach_set_header(rep, req, *msglen);
355 mach_add_port_desc(rep, mr->mr_name);
356 mach_set_trailer(rep, *msglen);
358 return 0;
362 mach_io_object_conforms_to(struct mach_trap_args *args)
364 mach_io_object_conforms_to_request_t *req = args->smsg;
365 mach_io_object_conforms_to_reply_t *rep = args->rmsg;
366 size_t *msglen = args->rsize;
367 int end_offset;
370 * req_classnameoffset is not used.
371 * Sanity check req_classnamecount.
373 end_offset = req->req_classnamecount;
374 if (MACH_REQMSG_OVERFLOW(args, req->req_classname[end_offset]))
375 return mach_msg_error(args, EINVAL);
377 #ifdef DEBUG_DARWIN
378 uprintf("Unimplemented mach_io_object_conforms_to\n");
379 #endif
381 *msglen = sizeof(*rep);
382 mach_set_header(rep, req, *msglen);
384 rep->rep_conforms = 1; /* XXX */
386 mach_set_trailer(rep, *msglen);
388 return 0;
392 mach_io_service_add_interest_notification(struct mach_trap_args *args)
394 mach_io_service_add_interest_notification_request_t *req = args->smsg;
395 mach_io_service_add_interest_notification_reply_t *rep = args->rmsg;
396 size_t *msglen = args->rsize;
397 struct lwp *l = args->l;
398 struct mach_port *mp;
399 struct mach_right *mr;
400 int end_offset, refcount_offset;
401 int item_size, refitem_size, refcount;
404 * req_typeofinterestoffset is not used.
405 * Sanity checks: first check refcount is not
406 * outside the message. NB: it is word aligned
408 refcount_offset = (req->req_typeofinterestcount & ~0x3UL) + 4;
409 if (MACH_REQMSG_OVERFLOW(args,
410 req->req_typeofinterest[refcount_offset]))
411 return mach_msg_error(args, EINVAL);
412 refcount = req->req_typeofinterest[refcount_offset];
415 * Sanity check typeofinterestcount and refcount
417 item_size = sizeof(req->req_typeofinterest[0]);
418 refitem_size = sizeof(req->req_ref[0]);
419 end_offset = req->req_typeofinterestcount +
420 (sizeof(refcount) / item_size) +
421 (refcount * refitem_size / item_size);
422 if (MACH_REQMSG_OVERFLOW(args, req->req_typeofinterest[end_offset]))
423 return mach_msg_error(args, EINVAL);
425 mp = mach_port_get();
426 mp->mp_flags |= MACH_MP_INKERNEL;
427 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
429 #ifdef DEBUG_DARWIN
430 uprintf("Unimplemented mach_io_service_add_interest_notification\n");
431 #endif
432 *msglen = sizeof(*rep);
433 mach_set_header(rep, req, *msglen);
434 mach_add_port_desc(rep, mr->mr_name);
435 mach_set_trailer(rep, *msglen);
437 return 0;
441 mach_io_connect_set_notification_port(struct mach_trap_args *args)
443 mach_io_connect_set_notification_port_request_t *req = args->smsg;
444 mach_io_connect_set_notification_port_reply_t *rep = args->rmsg;
445 struct lwp *l = args->l;
446 size_t *msglen = args->rsize;
447 mach_port_t mnn, mn;
448 struct mach_right *mrn;
449 struct mach_right *mr;
450 struct mach_iokit_devclass *mid;
452 #ifdef DEBUG_DARWIN
453 printf("mach_io_connect_set_notification_port\n");
454 #endif
455 mnn = req->req_port.name;
456 if ((mrn = mach_right_check(mnn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
457 return mach_msg_error(args, EINVAL);
459 mn = req->req_msgh.msgh_remote_port;
460 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
461 return mach_msg_error(args, EINVAL);
463 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
464 return mach_msg_error(args, EINVAL);
466 #ifdef DEBUG_DARWIN
467 printf("notification on right %p, name %x\n", mrn, mrn->mr_name);
468 #endif
469 mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
470 mid->mid_notify = mrn;
472 *msglen = sizeof(*rep);
473 mach_set_header(rep, req, *msglen);
475 rep->rep_retval = 0;
477 mach_set_trailer(rep, *msglen);
479 return 0;
483 mach_io_registry_get_root_entry(struct mach_trap_args *args)
485 mach_io_registry_get_root_entry_request_t *req = args->smsg;
486 mach_io_registry_get_root_entry_reply_t *rep = args->rmsg;
487 size_t *msglen = args->rsize;
488 struct lwp *l = args->l;
489 struct mach_port *mp;
490 struct mach_right *mr;
492 mp = mach_port_get();
493 mp->mp_flags |= MACH_MP_INKERNEL;
494 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
495 mp->mp_data = &mach_ioroot_devclass;
497 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
499 *msglen = sizeof(*rep);
500 mach_set_header(rep, req, *msglen);
501 mach_add_port_desc(rep, mr->mr_name);
502 mach_set_trailer(rep, *msglen);
504 return 0;
508 mach_io_registry_entry_get_child_iterator(struct mach_trap_args *args)
510 mach_io_registry_entry_get_child_iterator_request_t *req = args->smsg;
511 mach_io_registry_entry_get_child_iterator_reply_t *rep = args->rmsg;
512 size_t *msglen = args->rsize;
513 struct lwp *l = args->l;
514 struct mach_port *mp;
515 struct mach_right *mr;
516 mach_port_t mn;
517 struct mach_iokit_devclass *mid;
518 struct mach_device_iterator *mdi;
519 int maxdev;
520 size_t size;
521 int end_offset;
524 * req_planeoffset is not used.
525 * Sanity check req_planecount.
527 end_offset = req->req_planecount;
528 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
529 return mach_msg_error(args, EINVAL);
531 mn = req->req_msgh.msgh_remote_port;
532 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
533 return mach_iokit_error(args, MACH_IOKIT_EPERM);
534 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
535 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
536 mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
538 mp = mach_port_get();
539 mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
540 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
542 maxdev = sizeof(mach_iokit_devclasses);
543 size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
544 mdi = malloc(size, M_EMULDATA, M_WAITOK);
545 mp->mp_data = mdi;
547 (void)mach_fill_child_iterator(mdi, maxdev, 0, mid);
548 mdi->mdi_current = 0;
550 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
552 *msglen = sizeof(*rep);
553 mach_set_header(rep, req, *msglen);
554 mach_add_port_desc(rep, mr->mr_name);
555 mach_set_trailer(rep, *msglen);
557 return 0;
561 mach_io_registry_entry_get_name_in_plane(struct mach_trap_args *args)
563 mach_io_registry_entry_get_name_in_plane_request_t *req = args->smsg;
564 mach_io_registry_entry_get_name_in_plane_reply_t *rep = args->rmsg;
565 size_t *msglen = args->rsize;
566 struct lwp *l = args->l;
567 struct mach_right *mr;
568 mach_port_t mn;
569 struct mach_iokit_devclass *mid;
570 int end_offset;
573 * req_planeoffset is not used.
574 * Sanity check req_planecount.
576 end_offset = req->req_planecount;
577 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
578 return mach_msg_error(args, EINVAL);
580 mn = req->req_msgh.msgh_remote_port;
581 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
582 return mach_iokit_error(args, MACH_IOKIT_EPERM);
583 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
584 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
585 mid = mr->mr_port->mp_data;
587 *msglen = sizeof(*rep);
588 mach_set_header(rep, req, *msglen);
590 rep->rep_namecount = strlen(mid->mid_name);
591 if (rep->rep_namecount >= 128)
592 rep->rep_namecount = 128;
593 memcpy(&rep->rep_name, mid->mid_name, rep->rep_namecount);
595 mach_set_trailer(rep, *msglen);
597 return 0;
601 mach_io_object_get_class(struct mach_trap_args *args)
603 mach_io_object_get_class_request_t *req = args->smsg;
604 mach_io_object_get_class_reply_t *rep = args->rmsg;
605 size_t *msglen = args->rsize;
606 char classname[] = "unknownClass";
608 *msglen = sizeof(*rep);
609 mach_set_header(rep, req, *msglen);
611 /* XXX Just return a dummy name for now */
612 rep->rep_namecount = strlen(classname);
613 if (rep->rep_namecount >= 128)
614 rep->rep_namecount = 128;
615 memcpy(&rep->rep_name, classname, rep->rep_namecount);
617 mach_set_trailer(rep, *msglen);
619 return 0;
623 mach_io_registry_entry_get_location_in_plane(struct mach_trap_args *args)
625 mach_io_registry_entry_get_location_in_plane_request_t *req =
626 args->smsg;
627 mach_io_registry_entry_get_location_in_plane_reply_t *rep = args->rmsg;
628 size_t *msglen = args->rsize;
629 char location[] = "";
630 int end_offset;
633 * req_nameoffset is not used.
634 * Sanity check req_namecount.
636 end_offset = req->req_namecount;
637 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
638 return mach_msg_error(args, EINVAL);
640 *msglen = sizeof(*rep);
641 mach_set_header(rep, req, *msglen);
643 /* XXX Just return a dummy name for now */
644 rep->rep_locationcount = sizeof(location);
645 memcpy(&rep->rep_location, location, sizeof(location));
647 mach_set_trailer(rep, *msglen);
649 return 0;
653 mach_io_registry_entry_get_properties(struct mach_trap_args *args)
655 mach_io_registry_entry_get_properties_request_t *req = args->smsg;
656 mach_io_registry_entry_get_properties_reply_t *rep = args->rmsg;
657 size_t *msglen = args->rsize;
658 struct lwp *l = args->l;
659 int error;
660 void *uaddr;
661 size_t size;
662 mach_port_t mn;
663 struct mach_right *mr;
664 struct mach_iokit_devclass *mid;
666 mn = req->req_msgh.msgh_remote_port;
667 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
668 return mach_iokit_error(args, MACH_IOKIT_EPERM);
670 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
671 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
673 mid = mr->mr_port->mp_data;
674 if (mid->mid_properties == NULL)
675 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
676 size = strlen(mid->mid_properties) + 1; /* Include trailing zero */
678 if ((error = mach_ool_copyout(l,
679 mid->mid_properties, &uaddr, size, MACH_OOL_TRACE)) != 0) {
680 #ifdef DEBUG_MACH
681 printf("pid %d.%d: copyout iokit properties failed\n",
682 l->l_proc->p_pid, l->l_lid);
683 #endif
686 *msglen = sizeof(*rep);
687 mach_set_header(rep, req, *msglen);
688 mach_add_ool_desc(rep, uaddr, size);
690 rep->rep_count = size;
692 mach_set_trailer(rep, *msglen);
694 return 0;
698 mach_io_registry_entry_get_property(struct mach_trap_args *args)
700 mach_io_registry_entry_get_property_request_t *req = args->smsg;
701 mach_io_registry_entry_get_property_reply_t *rep = args->rmsg;
702 size_t *msglen = args->rsize;
703 struct lwp *l = args->l;
704 int error;
705 void *uaddr;
706 size_t size;
707 mach_port_t mn;
708 struct mach_right *mr;
709 struct mach_iokit_devclass *mid;
710 struct mach_iokit_property *mip;
711 int end_offset;
714 * req_property_nameoffset is not used.
715 * Sanity check req_property_namecount.
717 end_offset = req->req_property_namecount;
718 if (MACH_REQMSG_OVERFLOW(args, req->req_property_name[end_offset]))
719 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
721 /* Find the port */
722 mn = req->req_msgh.msgh_remote_port;
723 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
724 return mach_iokit_error(args, MACH_IOKIT_EPERM);
726 /* Find the devclass information */
727 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
728 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
730 mid = mr->mr_port->mp_data;
731 if (mid->mid_properties_array == NULL)
732 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
734 /* Lookup the property name */
735 for (mip = mid->mid_properties_array; mip->mip_name; mip++)
736 if (memcmp(mip->mip_name, req->req_property_name,
737 req->req_property_namecount) == 0)
738 break;
740 if (mip->mip_value == NULL)
741 return mach_iokit_error(args, MACH_IOKIT_ENOENT);
742 size = strlen(mip->mip_value) + 1; /* Include trailing zero */
744 /* And copyout its associated value */
745 if ((error = mach_ool_copyout(l,
746 mip->mip_value, &uaddr, size, MACH_OOL_TRACE)) != 0) {
747 #ifdef DEBUG_MACH
748 printf("pid %d.%d: copyout iokit property failed\n",
749 l->l_proc->p_pid, l->l_lid);
750 #endif
753 *msglen = sizeof(*rep);
754 mach_set_header(rep, req, *msglen);
755 mach_add_ool_desc(rep, uaddr, size);
757 rep->rep_properties_count = size;
759 mach_set_trailer(rep, *msglen);
761 return 0;
765 mach_io_registry_entry_get_path(struct mach_trap_args *args)
767 mach_io_registry_entry_get_path_request_t *req = args->smsg;
768 mach_io_registry_entry_get_path_reply_t *rep = args->rmsg;
769 size_t *msglen = args->rsize;
770 char location[] = ":/GossamerPE/pci@80000000/AppleGracklePCI/"
771 "ATY,264LT-G@11/.Display_Video_ATI_mach64-01018002/"
772 "display0/AppleBacklightDisplay";
773 char *cp;
774 size_t len, plen;
775 int end_offset;
778 * req_offset is not used.
779 * Sanity check req_count.
781 end_offset = req->req_count;
782 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
783 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
785 /* XXX Just return a dummy name for now */
786 len = req->req_count + strlen(location) - 1;
788 /* Sanity check for len */
789 if (len > 512)
790 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
791 plen = (len & ~0x3UL) + 4; /* Round to an int */
793 *msglen = sizeof(*rep) + (plen - 512);
794 mach_set_header(rep, req, *msglen);
796 rep->rep_retval = 0;
797 rep->rep_count = len;
799 cp = &rep->rep_path[0];
800 memcpy(cp, &req->req_plane, req->req_count);
801 cp += (req->req_count - 1); /* overwrite trailing \0 */
802 memcpy(cp, location, strlen(location));
803 cp += strlen(location);
804 *cp = '\0';
806 mach_set_trailer(rep, *msglen);
808 return 0;
812 mach_io_connect_map_memory(struct mach_trap_args *args)
814 mach_io_connect_map_memory_request_t *req = args->smsg;
815 struct lwp *l = args->l;
816 mach_port_t mn;
817 struct mach_right *mr;
818 struct mach_iokit_devclass *mid;
820 mn = req->req_msgh.msgh_remote_port;
821 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
822 return mach_iokit_error(args, MACH_IOKIT_EPERM);
824 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
825 mid = mr->mr_port->mp_data;
826 if (mid->mid_connect_map_memory == NULL)
827 printf("no connect_map_memory method "
828 "for darwin_iokit_class %s\n", mid->mid_name);
829 else
830 return (mid->mid_connect_map_memory)(args);
833 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
837 mach_io_iterator_reset(struct mach_trap_args *args)
839 mach_io_iterator_reset_request_t *req = args->smsg;
840 mach_io_iterator_reset_reply_t *rep = args->rmsg;
841 size_t *msglen = args->rsize;
842 struct lwp *l = args->l;
843 mach_port_t mn;
844 struct mach_right *mr;
845 struct mach_device_iterator *mdi;
847 mn = req->req_msgh.msgh_remote_port;
848 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
849 return mach_iokit_error(args, MACH_IOKIT_EPERM);
851 if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR)
852 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
854 mdi = mr->mr_port->mp_data;
855 mdi->mdi_current = 0;
857 *msglen = sizeof(*rep);
858 mach_set_header(rep, req, *msglen);
860 rep->rep_retval = 0;
862 mach_set_trailer(rep, *msglen);
864 return 0;
868 mach_io_connect_method_scalari_structo(struct mach_trap_args *args)
870 mach_io_connect_method_scalari_structo_request_t *req = args->smsg;
871 struct lwp *l = args->l;
872 mach_port_t mn;
873 struct mach_right *mr;
874 struct mach_iokit_devclass *mid;
875 int end_offset;
877 /* Sanity check req_incount */
878 end_offset = req->req_incount +
879 (sizeof(req->req_outcount) / sizeof(req->req_in[0]));
880 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
881 return mach_msg_error(args, EINVAL);
883 /* Sanity check req_outcount */
884 if (req->req_outcount > 4096)
885 return mach_msg_error(args, EINVAL);
887 mn = req->req_msgh.msgh_remote_port;
888 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
889 return mach_iokit_error(args, MACH_IOKIT_EPERM);
891 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
892 mid = mr->mr_port->mp_data;
893 if (mid->mid_connect_method_scalari_structo == NULL)
894 printf("no connect_method_scalari_structo method "
895 "for darwin_iokit_class %s\n", mid->mid_name);
896 else
897 return (mid->mid_connect_method_scalari_structo)(args);
900 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
904 mach_io_connect_method_structi_structo(struct mach_trap_args *args)
906 mach_io_connect_method_structi_structo_request_t *req = args->smsg;
907 struct lwp *l = args->l;
908 mach_port_t mn;
909 struct mach_right *mr;
910 struct mach_iokit_devclass *mid;
911 int end_offset;
912 int outcount;
914 /* Sanity check req_incount */
915 end_offset = req->req_incount +
916 (sizeof(req->req_outcount) / sizeof(req->req_in[0]));
917 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
918 return mach_msg_error(args, EINVAL);
920 /* Sanity check outcount. It is word aligned */
921 outcount = req->req_in[(req->req_incount & ~0x3UL) + 4];
922 if (outcount > 4096)
923 return mach_msg_error(args, EINVAL);
925 mn = req->req_msgh.msgh_remote_port;
926 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
927 return mach_iokit_error(args, MACH_IOKIT_EPERM);
929 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
930 mid = mr->mr_port->mp_data;
931 if (mid->mid_connect_method_structi_structo == NULL)
932 printf("no connect_method_structi_structo method "
933 "for darwin_iokit_class %s\n", mid->mid_name);
934 else
935 return (mid->mid_connect_method_structi_structo)(args);
938 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
942 mach_io_connect_set_properties(struct mach_trap_args *args)
944 mach_io_connect_set_properties_request_t *req = args->smsg;
945 mach_io_connect_set_properties_reply_t *rep = args->rmsg;
946 size_t *msglen = args->rsize;
948 #ifdef DEBUG_MACH
949 uprintf("Unimplemented mach_io_connect_set_properties\n");
950 #endif
952 *msglen = sizeof(*rep);
953 mach_set_header(rep, req, *msglen);
955 mach_set_trailer(rep, *msglen);
957 return 0;
961 mach_io_service_close(struct mach_trap_args *args)
963 mach_io_service_close_request_t *req = args->smsg;
964 mach_io_service_close_reply_t *rep = args->rmsg;
965 size_t *msglen = args->rsize;
967 #ifdef DEBUG_MACH
968 uprintf("Unimplemented mach_io_service_close\n");
969 #endif
971 *msglen = sizeof(*rep);
972 mach_set_header(rep, req, *msglen);
974 rep->rep_retval = 0;
976 mach_set_trailer(rep, *msglen);
978 return 0;
982 mach_io_connect_add_client(struct mach_trap_args *args)
984 mach_io_connect_add_client_request_t *req = args->smsg;
985 mach_io_connect_add_client_reply_t *rep = args->rmsg;
986 size_t *msglen = args->rsize;
988 #ifdef DEBUG_MACH
989 uprintf("Unimplemented mach_io_connect_add_client\n");
990 #endif
992 *msglen = sizeof(*rep);
993 mach_set_header(rep, req, *msglen);
995 rep->rep_retval = 0;
997 mach_set_trailer(rep, *msglen);
999 return 0;
1003 mach_io_connect_method_scalari_structi(struct mach_trap_args *args)
1005 mach_io_connect_method_scalari_structi_request_t *req = args->smsg;
1006 struct lwp *l = args->l;
1007 mach_port_t mn;
1008 struct mach_right *mr;
1009 struct mach_iokit_devclass *mid;
1010 int end_offset;
1011 int scalar_size, struct_size, instructcount;
1013 /* Sanity check req_incount and get instructcount */
1014 if (MACH_REQMSG_OVERFLOW(args, req->req_in[req->req_incount]))
1015 return mach_msg_error(args, EINVAL);
1016 instructcount = req->req_in[req->req_incount];
1018 /* Sanity check instructcount */
1019 scalar_size = sizeof(req->req_in[0]);
1020 struct_size = sizeof(req->req_instruct[0]);
1021 end_offset = req->req_incount +
1022 (sizeof(instructcount) / scalar_size) +
1023 (instructcount * struct_size / scalar_size);
1024 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
1025 return mach_msg_error(args, EINVAL);
1027 mn = req->req_msgh.msgh_remote_port;
1028 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
1029 return mach_iokit_error(args, MACH_IOKIT_EPERM);
1031 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
1032 mid = mr->mr_port->mp_data;
1033 if (mid->mid_connect_method_scalari_structi == NULL)
1034 printf("no connect_method_scalari_structi method "
1035 "for darwin_iokit_class %s\n", mid->mid_name);
1036 else
1037 return (mid->mid_connect_method_scalari_structi)(args);
1040 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
1044 mach_io_registry_entry_from_path(struct mach_trap_args *args)
1046 mach_io_registry_entry_from_path_request_t *req = args->smsg;
1047 mach_io_registry_entry_from_path_reply_t *rep = args->rmsg;
1048 size_t *msglen = args->rsize;
1049 struct lwp *l = args->l;
1050 struct mach_port *mp;
1051 struct mach_right *mr;
1052 struct mach_iokit_devclass *mid;
1053 int i, len;
1054 int end_offset;
1057 * req_pathoffset is not used.
1058 * Sanity check req_pathcount.
1060 end_offset = req->req_pathcount;
1061 if (MACH_REQMSG_OVERFLOW(args, req->req_path[end_offset]))
1062 return mach_msg_error(args, EINVAL);
1064 #ifdef DEBUG_MACH
1065 printf("mach_io_registry_entry_from_path: path = %s\n", req->req_path);
1066 #endif
1068 mp = mach_port_get();
1069 mp->mp_flags |= MACH_MP_INKERNEL;
1070 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
1072 i = 0;
1073 while ((mid = mach_iokit_devclasses[i++]) != NULL) {
1074 len = strlen(mid->mid_name);
1075 #ifdef DEBUG_MACH
1076 printf("trying \"%s\" vs \"%s\"\n",
1077 &req->req_path[req->req_pathcount - 1 - len],
1078 mid->mid_name);
1079 #endif
1080 if (memcmp(&req->req_path[req->req_pathcount - 1 - len],
1081 mid->mid_name, len) == 0) {
1082 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
1083 mp->mp_data = mid;
1084 break;
1088 *msglen = sizeof(*rep);
1089 mach_set_header(rep, req, *msglen);
1090 mach_add_port_desc(rep, mr->mr_name);
1091 mach_set_trailer(rep, *msglen);
1093 return 0;
1097 mach_io_registry_entry_get_parent_iterator(struct mach_trap_args *args)
1099 mach_io_registry_entry_get_parent_iterator_request_t *req = args->smsg;
1100 mach_io_registry_entry_get_parent_iterator_reply_t *rep = args->rmsg;
1101 size_t *msglen = args->rsize;
1102 struct lwp *l = args->l;
1103 struct mach_port *mp;
1104 struct mach_right *mr;
1105 struct mach_iokit_devclass *mid;
1106 struct mach_device_iterator *mdi;
1107 mach_port_t mn;
1108 int maxdev;
1109 size_t size;
1110 int end_offset;
1113 * req_offset is unused
1114 * Sanity check req_count
1116 end_offset = req->req_count;
1117 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
1118 return mach_msg_error(args, EINVAL);
1120 #ifdef DEBUG_MACH
1121 printf("mach_io_registry_entry_get_parent_iterator: plane = %s\n",
1122 req->req_plane);
1123 #endif
1125 mn = req->req_msgh.msgh_remote_port;
1126 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
1127 return mach_iokit_error(args, MACH_IOKIT_EPERM);
1129 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
1130 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
1131 mid = mr->mr_port->mp_data;
1133 mp = mach_port_get();
1134 mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
1135 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
1137 maxdev = sizeof(mach_iokit_devclasses);
1138 size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
1139 mdi = malloc(size, M_EMULDATA, M_WAITOK);
1140 mp->mp_data = mdi;
1142 (void)mach_fill_parent_iterator(mdi, maxdev, 0, mid);
1143 mdi->mdi_current = 0;
1145 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
1147 *msglen = sizeof(*rep);
1148 mach_set_header(rep, req, *msglen);
1149 mach_add_port_desc(rep, mr->mr_name);
1150 mach_set_trailer(rep, *msglen);
1152 return 0;
1155 void
1156 mach_iokit_cleanup_notify(struct mach_right *mr)
1158 int i;
1159 struct mach_iokit_devclass *mid;
1161 i = 0;
1162 while ((mid = mach_iokit_devclasses[i++]) != NULL)
1163 if (mid->mid_notify == mr)
1164 mid->mid_notify = NULL;
1166 return;
1169 static int
1170 mach_fill_child_iterator(struct mach_device_iterator *mdi, int size, int index, struct mach_iokit_devclass *mid)
1172 struct mach_iokit_devclass **midp;
1173 struct mach_iokit_devclass **midq;
1175 for (midp = mach_iokit_devclasses; *midp != NULL; midp++) {
1176 for (midq = (*midp)->mid_parent; *midq != NULL; midq++) {
1177 if (*midq == mid) {
1178 mdi->mdi_devices[index++] = *midp;
1179 break;
1182 #ifdef DIAGNOSTIC
1183 if (index >= size) {
1184 printf("mach_device_iterator overflow\n");
1185 break;
1187 #endif
1189 mdi->mdi_devices[index] = NULL;
1191 return index;
1194 static int
1195 mach_fill_parent_iterator(struct mach_device_iterator *mdi, int size, int index, struct mach_iokit_devclass *mid)
1197 struct mach_iokit_devclass **midp;
1199 for (midp = mid->mid_parent; *midp != NULL; midp++) {
1200 mdi->mdi_devices[index++] = *midp;
1201 #ifdef DIAGNOSTIC
1202 if (index >= size) {
1203 printf("mach_device_iterator overflow\n");
1204 break;
1206 #endif
1208 mdi->mdi_devices[index] = NULL;
1210 return index;