1 /* $NetBSD: mach_iokit.c,v 1.35 2007/12/08 18:36:14 dsl Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
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>
53 #include <compat/darwin/darwin_iokit.h>
56 struct mach_iokit_devclass mach_ioroot_devclass
= {
59 "<dict ID=\"0\"></dict>",
70 struct mach_iokit_devclass
*mach_iokit_devclasses
[] = {
71 &mach_ioroot_devclass
,
73 DARWIN_IOKIT_DEVCLASSES
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
*);
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
;
92 struct mach_right
*mr
;
93 struct mach_iokit_devclass
*mid
;
94 struct mach_device_iterator
*mdi
;
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);
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
;
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;
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
);
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
;
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
);
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
;
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
);
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
;
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
];
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
);
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
;
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.
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
);
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
;
295 struct mach_right
*mr
;
296 struct mach_iokit_devclass
*mid
;
297 struct mach_device_iterator
*mdi
;
298 struct mach_iokit_devclass
**midp
;
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
);
328 if (req
->req_options
& MACH_IOKIT_PARENT_ITERATOR
)
329 index
= mach_fill_parent_iterator(mdi
, maxdev
, 0, mid
);
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
);
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);
350 printf("io_registry_entry_create_iterator\n");
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
);
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
;
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
);
378 uprintf("Unimplemented mach_io_object_conforms_to\n");
381 *msglen
= sizeof(*rep
);
382 mach_set_header(rep
, req
, *msglen
);
384 rep
->rep_conforms
= 1; /* XXX */
386 mach_set_trailer(rep
, *msglen
);
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);
430 uprintf("Unimplemented mach_io_service_add_interest_notification\n");
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
);
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
;
448 struct mach_right
*mrn
;
449 struct mach_right
*mr
;
450 struct mach_iokit_devclass
*mid
;
453 printf("mach_io_connect_set_notification_port\n");
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
);
467 printf("notification on right %p, name %x\n", mrn
, mrn
->mr_name
);
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
);
477 mach_set_trailer(rep
, *msglen
);
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
);
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
;
517 struct mach_iokit_devclass
*mid
;
518 struct mach_device_iterator
*mdi
;
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
);
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
);
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
;
569 struct mach_iokit_devclass
*mid
;
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
);
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
);
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
=
627 mach_io_registry_entry_get_location_in_plane_reply_t
*rep
= args
->rmsg
;
628 size_t *msglen
= args
->rsize
;
629 char location
[] = "";
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
);
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
;
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) {
681 printf("pid %d.%d: copyout iokit properties failed\n",
682 l
->l_proc
->p_pid
, l
->l_lid
);
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
);
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
;
708 struct mach_right
*mr
;
709 struct mach_iokit_devclass
*mid
;
710 struct mach_iokit_property
*mip
;
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
);
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)
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) {
748 printf("pid %d.%d: copyout iokit property failed\n",
749 l
->l_proc
->p_pid
, l
->l_lid
);
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
);
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";
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 */
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
);
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
);
806 mach_set_trailer(rep
, *msglen
);
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
;
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
);
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
;
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
);
862 mach_set_trailer(rep
, *msglen
);
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
;
873 struct mach_right
*mr
;
874 struct mach_iokit_devclass
*mid
;
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
);
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
;
909 struct mach_right
*mr
;
910 struct mach_iokit_devclass
*mid
;
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];
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
);
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
;
949 uprintf("Unimplemented mach_io_connect_set_properties\n");
952 *msglen
= sizeof(*rep
);
953 mach_set_header(rep
, req
, *msglen
);
955 mach_set_trailer(rep
, *msglen
);
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
;
968 uprintf("Unimplemented mach_io_service_close\n");
971 *msglen
= sizeof(*rep
);
972 mach_set_header(rep
, req
, *msglen
);
976 mach_set_trailer(rep
, *msglen
);
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
;
989 uprintf("Unimplemented mach_io_connect_add_client\n");
992 *msglen
= sizeof(*rep
);
993 mach_set_header(rep
, req
, *msglen
);
997 mach_set_trailer(rep
, *msglen
);
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
;
1008 struct mach_right
*mr
;
1009 struct mach_iokit_devclass
*mid
;
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
);
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
;
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
);
1065 printf("mach_io_registry_entry_from_path: path = %s\n", req
->req_path
);
1068 mp
= mach_port_get();
1069 mp
->mp_flags
|= MACH_MP_INKERNEL
;
1070 mr
= mach_right_get(mp
, l
, MACH_PORT_TYPE_SEND
, 0);
1073 while ((mid
= mach_iokit_devclasses
[i
++]) != NULL
) {
1074 len
= strlen(mid
->mid_name
);
1076 printf("trying \"%s\" vs \"%s\"\n",
1077 &req
->req_path
[req
->req_pathcount
- 1 - len
],
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
;
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
);
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
;
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
);
1121 printf("mach_io_registry_entry_get_parent_iterator: plane = %s\n",
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
);
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
);
1156 mach_iokit_cleanup_notify(struct mach_right
*mr
)
1159 struct mach_iokit_devclass
*mid
;
1162 while ((mid
= mach_iokit_devclasses
[i
++]) != NULL
)
1163 if (mid
->mid_notify
== mr
)
1164 mid
->mid_notify
= NULL
;
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
++) {
1178 mdi
->mdi_devices
[index
++] = *midp
;
1183 if (index
>= size
) {
1184 printf("mach_device_iterator overflow\n");
1189 mdi
->mdi_devices
[index
] = NULL
;
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
;
1202 if (index
>= size
) {
1203 printf("mach_device_iterator overflow\n");
1208 mdi
->mdi_devices
[index
] = NULL
;