1 /* $NetBSD: mach_iokit.c,v 1.34 2006/03/07 03:32:06 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
9 *
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.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "opt_compat_darwin.h"
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: mach_iokit.c,v 1.34 2006/03/07 03:32:06 thorpej Exp $");
42
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/malloc.h>
47 #include <sys/signal.h>
48 #include <sys/mount.h>
49 #include <sys/proc.h>
50 #include <sys/ktrace.h>
51 #include <sys/device.h>
52 #include <compat/mach/mach_types.h>
53 #include <compat/mach/mach_message.h>
54 #include <compat/mach/mach_port.h>
55 #include <compat/mach/mach_errno.h>
56 #include <compat/mach/mach_iokit.h>
57 #include <compat/mach/mach_services.h>
58
59 #ifdef COMPAT_DARWIN
60 #include <compat/darwin/darwin_iokit.h>
61 #endif
62
63 struct mach_iokit_devclass mach_ioroot_devclass = {
64 "(unknwon)",
65 { NULL },
66 "<dict ID=\"\"></dict>",
67 NULL,
68 NULL,
69 NULL,
70 NULL,
71 NULL,
72 NULL,
73 "Root",
74 NULL,
75 };
76
77 struct mach_iokit_devclass *mach_iokit_devclasses[] = {
78 &mach_ioroot_devclass,
79 #ifdef COMPAT_DARWIN
80 DARWIN_IOKIT_DEVCLASSES
81 #endif
82 NULL,
83 };
84
85
86 static int mach_fill_child_iterator(struct mach_device_iterator *, int, int,
87 struct mach_iokit_devclass *);
88 static int mach_fill_parent_iterator(struct mach_device_iterator *, int, int,
89 struct mach_iokit_devclass *);
90
91 int
92 mach_io_service_get_matching_services(args)
93 struct mach_trap_args *args;
94 {
95 mach_io_service_get_matching_services_request_t *req = args->smsg;
96 mach_io_service_get_matching_services_reply_t *rep = args->rmsg;
97 size_t *msglen = args->rsize;
98 struct lwp *l = args->l;
99 struct mach_port *mp;
100 struct mach_right *mr;
101 struct mach_iokit_devclass *mid;
102 struct mach_device_iterator *mdi;
103 size_t size;
104 int end_offset;
105 int i;
106
107 /* Sanity check req_size */
108 end_offset = req->req_size;
109 if (MACH_REQMSG_OVERFLOW(args, req->req_string[end_offset]))
110 return mach_msg_error(args, EINVAL);
111
112 mp = mach_port_get();
113 mp->mp_flags |= MACH_MP_INKERNEL;
114 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
115
116 mp->mp_data = NULL;
117 i = 0;
118 while ((mid = mach_iokit_devclasses[i++]) != NULL) {
119 if (memcmp(req->req_string, mid->mid_string,
120 req->req_size) == 0) {
121 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
122
123 size = sizeof(*mdi)
124 + sizeof(struct mach_device_iterator *);
125 mdi = malloc(size, M_EMULDATA, M_WAITOK);
126 mdi->mdi_devices[0] = mid;
127 mdi->mdi_devices[1] = NULL;
128 mdi->mdi_current = 0;
129
130 mp->mp_data = mdi;
131 break;
132 }
133 }
134
135 if (mp->mp_data == NULL)
136 return mach_iokit_error(args, MACH_IOKIT_ENOENT);
137
138 *msglen = sizeof(*rep);
139 mach_set_header(rep, req, *msglen);
140 mach_add_port_desc(rep, mr->mr_name);
141 mach_set_trailer(rep, *msglen);
142
143 return 0;
144 }
145
146 int
147 mach_io_iterator_next(args)
148 struct mach_trap_args *args;
149 {
150 mach_io_iterator_next_request_t *req = args->smsg;
151 mach_io_iterator_next_reply_t *rep = args->rmsg;
152 size_t *msglen = args->rsize;
153 struct lwp *l = args->l;
154 struct mach_port *mp;
155 struct mach_right *mr;
156 struct mach_device_iterator *mdi;
157 mach_port_t mn;
158
159 mn = req->req_msgh.msgh_remote_port;
160 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
161 return mach_iokit_error(args, MACH_IOKIT_EPERM);
162
163 if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR)
164 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
165
166 mdi = mr->mr_port->mp_data;
167
168 /* Is there something coming next? */
169 if (mdi->mdi_devices[mdi->mdi_current] == NULL)
170 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
171
172 mp = mach_port_get();
173 mp->mp_flags |= MACH_MP_INKERNEL;
174 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
175 mp->mp_data = mdi->mdi_devices[mdi->mdi_current++];
176
177 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
178
179 *msglen = sizeof(*rep);
180 mach_set_header(rep, req, *msglen);
181 mach_add_port_desc(rep, mr->mr_name);
182 mach_set_trailer(rep, *msglen);
183
184 return 0;
185 }
186
187 int
188 mach_io_service_open(args)
189 struct mach_trap_args *args;
190 {
191 mach_io_service_open_request_t *req = args->smsg;
192 mach_io_service_open_reply_t *rep = args->rmsg;
193 size_t *msglen = args->rsize;
194 struct lwp *l = args->l;
195 struct mach_port *mp;
196 struct mach_right *mr;
197 mach_port_t mn;
198
199 mn = req->req_msgh.msgh_remote_port;
200 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
201 return mach_iokit_error(args, MACH_IOKIT_EPERM);
202
203 mp = mach_port_get();
204 mp->mp_flags |= MACH_MP_INKERNEL;
205 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
206 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
207 mp->mp_data = mr->mr_port->mp_data;
208 }
209 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
210
211 *msglen = sizeof(*rep);
212 mach_set_header(rep, req, *msglen);
213 mach_add_port_desc(rep, mr->mr_name);
214 mach_set_trailer(rep, *msglen);
215
216 return 0;
217 }
218
219 int
220 mach_io_connect_method_scalari_scalaro(args)
221 struct mach_trap_args *args;
222 {
223 mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg;
224 struct lwp *l = args->l;
225 mach_port_t mn;
226 struct mach_right *mr;
227 struct mach_iokit_devclass *mid;
228 int end_offset, outcount;
229
230 /*
231 * Sanity check req_incount
232 * the +1 gives us the last field of the message, req_outcount
233 */
234 end_offset = req->req_incount +
235 (sizeof(req->req_outcount) / sizeof(req->req_in[0]));
236 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
237 return mach_msg_error(args, EINVAL);
238
239 /* Sanity check req->req_outcount */
240 outcount = req->req_in[req->req_incount];
241 if (outcount > 16)
242 return mach_msg_error(args, EINVAL);
243
244 mn = req->req_msgh.msgh_remote_port;
245 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
246 return mach_iokit_error(args, MACH_IOKIT_EPERM);
247
248 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
249 mid = mr->mr_port->mp_data;
250 if (mid->mid_connect_method_scalari_scalaro == NULL)
251 printf("no connect_method_scalari_scalaro method "
252 "for darwin_iokit_class %s\n", mid->mid_name);
253 else
254 return (mid->mid_connect_method_scalari_scalaro)(args);
255 }
256
257 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
258 }
259
260 int
261 mach_io_connect_get_service(args)
262 struct mach_trap_args *args;
263 {
264 mach_io_connect_get_service_request_t *req = args->smsg;
265 mach_io_connect_get_service_reply_t *rep = args->rmsg;
266 size_t *msglen = args->rsize;
267 struct lwp *l = args->l;
268 struct mach_port *mp;
269 struct mach_right *mr;
270 mach_port_t mn;
271
272 mn = req->req_msgh.msgh_remote_port;
273 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
274 return mach_iokit_error(args, MACH_IOKIT_EPERM);
275
276 mp = mach_port_get();
277 mp->mp_flags |= MACH_MP_INKERNEL;
278 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
279 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
280 mp->mp_data = mr->mr_port->mp_data;
281 }
282 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
283
284 /*
285 * XXX Bump the refcount to workaround an emulation bug
286 * that causes Windowserver to release the port too early.
287 */
288 mr->mr_refcount++;
289
290 *msglen = sizeof(*rep);
291 mach_set_header(rep, req, *msglen);
292 mach_add_port_desc(rep, mr->mr_name);
293 mach_set_trailer(rep, *msglen);
294
295 return 0;
296 }
297
298 int
299 mach_io_registry_entry_create_iterator(args)
300 struct mach_trap_args *args;
301 {
302 mach_io_registry_entry_create_iterator_request_t *req = args->smsg;
303 mach_io_registry_entry_create_iterator_reply_t *rep = args->rmsg;
304 size_t *msglen = args->rsize;
305 struct lwp *l = args->l;
306 struct mach_port *mp;
307 mach_port_t mn;
308 struct mach_right *mr;
309 struct mach_iokit_devclass *mid;
310 struct mach_device_iterator *mdi;
311 struct mach_iokit_devclass **midp;
312 int maxdev, index;
313 size_t size;
314 int end_offset;
315
316 /*
317 * req_planeoffset is not used.
318 * Sanity check req_planecount
319 */
320 end_offset = req->req_planecount +
321 (sizeof(req->req_options) / sizeof(req->req_plane[0]));
322 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
323 return mach_msg_error(args, EINVAL);
324
325 mn = req->req_msgh.msgh_remote_port;
326 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
327 return mach_iokit_error(args, MACH_IOKIT_EPERM);
328 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
329 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
330 mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
331
332 mp = mach_port_get();
333 mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
334 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
335
336 maxdev = sizeof(mach_iokit_devclasses);
337 size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
338 mdi = malloc(size, M_EMULDATA, M_WAITOK);
339 mp->mp_data = mdi;
340
341 if (req->req_options & MACH_IOKIT_PARENT_ITERATOR)
342 index = mach_fill_parent_iterator(mdi, maxdev, 0, mid);
343 else
344 index = mach_fill_child_iterator(mdi, maxdev, 0, mid);
345
346 /* XXX This is untested */
347 if (req->req_options & MACH_IOKIT_RECURSIVE_ITERATOR) {
348 for (midp = mdi->mdi_devices; *midp != NULL; midp++) {
349 if (req->req_options & MACH_IOKIT_PARENT_ITERATOR)
350 index = mach_fill_parent_iterator(mdi,
351 maxdev, index, *midp);
352 else
353 index = mach_fill_child_iterator(mdi,
354 maxdev, index, *midp);
355 }
356 }
357
358 mdi->mdi_current = 0;
359
360 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
361
362 #ifdef DEBUG_MACH
363 printf("io_registry_entry_create_iterator\n");
364 #endif
365
366 *msglen = sizeof(*rep);
367 mach_set_header(rep, req, *msglen);
368 mach_add_port_desc(rep, mr->mr_name);
369 mach_set_trailer(rep, *msglen);
370
371 return 0;
372 }
373
374 int
375 mach_io_object_conforms_to(args)
376 struct mach_trap_args *args;
377 {
378 mach_io_object_conforms_to_request_t *req = args->smsg;
379 mach_io_object_conforms_to_reply_t *rep = args->rmsg;
380 size_t *msglen = args->rsize;
381 int end_offset;
382
383 /*
384 * req_classnameoffset is not used.
385 * Sanity check req_classnamecount.
386 */
387 end_offset = req->req_classnamecount;
388 if (MACH_REQMSG_OVERFLOW(args, req->req_classname[end_offset]))
389 return mach_msg_error(args, EINVAL);
390
391 #ifdef DEBUG_DARWIN
392 uprintf("Unimplemented mach_io_object_conforms_to\n");
393 #endif
394
395 *msglen = sizeof(*rep);
396 mach_set_header(rep, req, *msglen);
397
398 rep->rep_conforms = 1; /* XXX */
399
400 mach_set_trailer(rep, *msglen);
401
402 return 0;
403 }
404
405 int
406 mach_io_service_add_interest_notification(args)
407 struct mach_trap_args *args;
408 {
409 mach_io_service_add_interest_notification_request_t *req = args->smsg;
410 mach_io_service_add_interest_notification_reply_t *rep = args->rmsg;
411 size_t *msglen = args->rsize;
412 struct lwp *l = args->l;
413 struct mach_port *mp;
414 struct mach_right *mr;
415 int end_offset, refcount_offset;
416 int item_size, refitem_size, refcount;
417
418 /*
419 * req_typeofinterestoffset is not used.
420 * Sanity checks: first check refcount is not
421 * outside the message. NB: it is word aligned
422 */
423 refcount_offset = (req->req_typeofinterestcount & ~0x3UL) + 4;
424 if (MACH_REQMSG_OVERFLOW(args,
425 req->req_typeofinterest[refcount_offset]))
426 return mach_msg_error(args, EINVAL);
427 refcount = req->req_typeofinterest[refcount_offset];
428
429 /*
430 * Sanity check typeofinterestcount and refcount
431 */
432 item_size = sizeof(req->req_typeofinterest[0]);
433 refitem_size = sizeof(req->req_ref[0]);
434 end_offset = req->req_typeofinterestcount +
435 (sizeof(refcount) / item_size) +
436 (refcount * refitem_size / item_size);
437 if (MACH_REQMSG_OVERFLOW(args, req->req_typeofinterest[end_offset]))
438 return mach_msg_error(args, EINVAL);
439
440 mp = mach_port_get();
441 mp->mp_flags |= MACH_MP_INKERNEL;
442 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
443
444 #ifdef DEBUG_DARWIN
445 uprintf("Unimplemented mach_io_service_add_interest_notification\n");
446 #endif
447 *msglen = sizeof(*rep);
448 mach_set_header(rep, req, *msglen);
449 mach_add_port_desc(rep, mr->mr_name);
450 mach_set_trailer(rep, *msglen);
451
452 return 0;
453 }
454
455 int
456 mach_io_connect_set_notification_port(args)
457 struct mach_trap_args *args;
458 {
459 mach_io_connect_set_notification_port_request_t *req = args->smsg;
460 mach_io_connect_set_notification_port_reply_t *rep = args->rmsg;
461 struct lwp *l = args->l;
462 size_t *msglen = args->rsize;
463 mach_port_t mnn, mn;
464 struct mach_right *mrn;
465 struct mach_right *mr;
466 struct mach_iokit_devclass *mid;
467
468 #ifdef DEBUG_DARWIN
469 printf("mach_io_connect_set_notification_port\n");
470 #endif
471 mnn = req->req_port.name;
472 if ((mrn = mach_right_check(mnn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
473 return mach_msg_error(args, EINVAL);
474
475 mn = req->req_msgh.msgh_remote_port;
476 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
477 return mach_msg_error(args, EINVAL);
478
479 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
480 return mach_msg_error(args, EINVAL);
481
482 #ifdef DEBUG_DARWIN
483 printf("notification on right %p, name %x\n", mrn, mrn->mr_name);
484 #endif
485 mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
486 mid->mid_notify = mrn;
487
488 *msglen = sizeof(*rep);
489 mach_set_header(rep, req, *msglen);
490
491 rep->rep_retval = 0;
492
493 mach_set_trailer(rep, *msglen);
494
495 return 0;
496 }
497
498 int
499 mach_io_registry_get_root_entry(args)
500 struct mach_trap_args *args;
501 {
502 mach_io_registry_get_root_entry_request_t *req = args->smsg;
503 mach_io_registry_get_root_entry_reply_t *rep = args->rmsg;
504 size_t *msglen = args->rsize;
505 struct lwp *l = args->l;
506 struct mach_port *mp;
507 struct mach_right *mr;
508
509 mp = mach_port_get();
510 mp->mp_flags |= MACH_MP_INKERNEL;
511 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
512 mp->mp_data = &mach_ioroot_devclass;
513
514 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
515
516 *msglen = sizeof(*rep);
517 mach_set_header(rep, req, *msglen);
518 mach_add_port_desc(rep, mr->mr_name);
519 mach_set_trailer(rep, *msglen);
520
521 return 0;
522 }
523
524 int
525 mach_io_registry_entry_get_child_iterator(args)
526 struct mach_trap_args *args;
527 {
528 mach_io_registry_entry_get_child_iterator_request_t *req = args->smsg;
529 mach_io_registry_entry_get_child_iterator_reply_t *rep = args->rmsg;
530 size_t *msglen = args->rsize;
531 struct lwp *l = args->l;
532 struct mach_port *mp;
533 struct mach_right *mr;
534 mach_port_t mn;
535 struct mach_iokit_devclass *mid;
536 struct mach_device_iterator *mdi;
537 int maxdev;
538 size_t size;
539 int end_offset;
540
541 /*
542 * req_planeoffset is not used.
543 * Sanity check req_planecount.
544 */
545 end_offset = req->req_planecount;
546 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
547 return mach_msg_error(args, EINVAL);
548
549 mn = req->req_msgh.msgh_remote_port;
550 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
551 return mach_iokit_error(args, MACH_IOKIT_EPERM);
552 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
553 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
554 mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
555
556 mp = mach_port_get();
557 mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
558 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
559
560 maxdev = sizeof(mach_iokit_devclasses);
561 size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
562 mdi = malloc(size, M_EMULDATA, M_WAITOK);
563 mp->mp_data = mdi;
564
565 (void)mach_fill_child_iterator(mdi, maxdev, 0, mid);
566 mdi->mdi_current = 0;
567
568 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
569
570 *msglen = sizeof(*rep);
571 mach_set_header(rep, req, *msglen);
572 mach_add_port_desc(rep, mr->mr_name);
573 mach_set_trailer(rep, *msglen);
574
575 return 0;
576 }
577
578 int
579 mach_io_registry_entry_get_name_in_plane(args)
580 struct mach_trap_args *args;
581 {
582 mach_io_registry_entry_get_name_in_plane_request_t *req = args->smsg;
583 mach_io_registry_entry_get_name_in_plane_reply_t *rep = args->rmsg;
584 size_t *msglen = args->rsize;
585 struct lwp *l = args->l;
586 struct mach_right *mr;
587 mach_port_t mn;
588 struct mach_iokit_devclass *mid;
589 int end_offset;
590
591 /*
592 * req_planeoffset is not used.
593 * Sanity check req_planecount.
594 */
595 end_offset = req->req_planecount;
596 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
597 return mach_msg_error(args, EINVAL);
598
599 mn = req->req_msgh.msgh_remote_port;
600 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
601 return mach_iokit_error(args, MACH_IOKIT_EPERM);
602 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
603 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
604 mid = mr->mr_port->mp_data;
605
606 *msglen = sizeof(*rep);
607 mach_set_header(rep, req, *msglen);
608
609 rep->rep_namecount = strlen(mid->mid_name);
610 if (rep->rep_namecount >= 128)
611 rep->rep_namecount = 128;
612 memcpy(&rep->rep_name, mid->mid_name, rep->rep_namecount);
613
614 mach_set_trailer(rep, *msglen);
615
616 return 0;
617 }
618
619 int
620 mach_io_object_get_class(args)
621 struct mach_trap_args *args;
622 {
623 mach_io_object_get_class_request_t *req = args->smsg;
624 mach_io_object_get_class_reply_t *rep = args->rmsg;
625 size_t *msglen = args->rsize;
626 char classname[] = "unknownClass";
627
628 *msglen = sizeof(*rep);
629 mach_set_header(rep, req, *msglen);
630
631 /* XXX Just return a dummy name for now */
632 rep->rep_namecount = strlen(classname);
633 if (rep->rep_namecount >= 128)
634 rep->rep_namecount = 128;
635 memcpy(&rep->rep_name, classname, rep->rep_namecount);
636
637 mach_set_trailer(rep, *msglen);
638
639 return 0;
640 }
641
642 int
643 mach_io_registry_entry_get_location_in_plane(args)
644 struct mach_trap_args *args;
645 {
646 mach_io_registry_entry_get_location_in_plane_request_t *req =
647 args->smsg;
648 mach_io_registry_entry_get_location_in_plane_reply_t *rep = args->rmsg;
649 size_t *msglen = args->rsize;
650 char location[] = "";
651 int end_offset;
652
653 /*
654 * req_nameoffset is not used.
655 * Sanity check req_namecount.
656 */
657 end_offset = req->req_namecount;
658 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
659 return mach_msg_error(args, EINVAL);
660
661 *msglen = sizeof(*rep);
662 mach_set_header(rep, req, *msglen);
663
664 /* XXX Just return a dummy name for now */
665 rep->rep_locationcount = sizeof(location);
666 memcpy(&rep->rep_location, location, sizeof(location));
667
668 mach_set_trailer(rep, *msglen);
669
670 return 0;
671 }
672
673 int
674 mach_io_registry_entry_get_properties(args)
675 struct mach_trap_args *args;
676 {
677 mach_io_registry_entry_get_properties_request_t *req = args->smsg;
678 mach_io_registry_entry_get_properties_reply_t *rep = args->rmsg;
679 size_t *msglen = args->rsize;
680 struct lwp *l = args->l;
681 int error;
682 void *uaddr;
683 size_t size;
684 mach_port_t mn;
685 struct mach_right *mr;
686 struct mach_iokit_devclass *mid;
687
688 mn = req->req_msgh.msgh_remote_port;
689 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
690 return mach_iokit_error(args, MACH_IOKIT_EPERM);
691
692 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
693 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
694
695 mid = mr->mr_port->mp_data;
696 if (mid->mid_properties == NULL)
697 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
698 size = strlen(mid->mid_properties) + 1; /* Include trailing zero */
699
700 if ((error = mach_ool_copyout(l,
701 mid->mid_properties, &uaddr, size, MACH_OOL_TRACE)) != 0) {
702 #ifdef DEBUG_MACH
703 printf("pid %d.%d: copyout iokit properties failed\n",
704 l->l_proc->p_pid, l->l_lid);
705 #endif
706 }
707
708 *msglen = sizeof(*rep);
709 mach_set_header(rep, req, *msglen);
710 mach_add_ool_desc(rep, uaddr, size);
711
712 rep->rep_count = size;
713
714 mach_set_trailer(rep, *msglen);
715
716 return 0;
717 }
718
719 int
720 mach_io_registry_entry_get_property(args)
721 struct mach_trap_args *args;
722 {
723 mach_io_registry_entry_get_property_request_t *req = args->smsg;
724 mach_io_registry_entry_get_property_reply_t *rep = args->rmsg;
725 size_t *msglen = args->rsize;
726 struct lwp *l = args->l;
727 int error;
728 void *uaddr;
729 size_t size;
730 mach_port_t mn;
731 struct mach_right *mr;
732 struct mach_iokit_devclass *mid;
733 struct mach_iokit_property *mip;
734 int end_offset;
735
736 /*
737 * req_property_nameoffset is not used.
738 * Sanity check req_property_namecount.
739 */
740 end_offset = req->req_property_namecount;
741 if (MACH_REQMSG_OVERFLOW(args, req->req_property_name[end_offset]))
742 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
743
744 /* Find the port */
745 mn = req->req_msgh.msgh_remote_port;
746 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
747 return mach_iokit_error(args, MACH_IOKIT_EPERM);
748
749 /* Find the devclass information */
750 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
751 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
752
753 mid = mr->mr_port->mp_data;
754 if (mid->mid_properties_array == NULL)
755 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
756
757 /* Lookup the property name */
758 for (mip = mid->mid_properties_array; mip->mip_name; mip++)
759 if (memcmp(mip->mip_name, req->req_property_name,
760 req->req_property_namecount) == 0)
761 break;
762
763 if (mip->mip_value == NULL)
764 return mach_iokit_error(args, MACH_IOKIT_ENOENT);
765 size = strlen(mip->mip_value) + 1; /* Include trailing zero */
766
767 /* And copyout its associated value */
768 if ((error = mach_ool_copyout(l,
769 mip->mip_value, &uaddr, size, MACH_OOL_TRACE)) != 0) {
770 #ifdef DEBUG_MACH
771 printf("pid %d.%d: copyout iokit property failed\n",
772 l->l_proc->p_pid, l->l_lid);
773 #endif
774 }
775
776 *msglen = sizeof(*rep);
777 mach_set_header(rep, req, *msglen);
778 mach_add_ool_desc(rep, uaddr, size);
779
780 rep->rep_properties_count = size;
781
782 mach_set_trailer(rep, *msglen);
783
784 return 0;
785 }
786
787 int
788 mach_io_registry_entry_get_path(args)
789 struct mach_trap_args *args;
790 {
791 mach_io_registry_entry_get_path_request_t *req = args->smsg;
792 mach_io_registry_entry_get_path_reply_t *rep = args->rmsg;
793 size_t *msglen = args->rsize;
794 char location[] = ":/GossamerPE/pci@80000000/AppleGracklePCI/"
795 "ATY,264LT-G@11/.Display_Video_ATI_mach64-01018002/"
796 "display0/AppleBacklightDisplay";
797 char *cp;
798 size_t len, plen;
799 int end_offset;
800
801 /*
802 * req_offset is not used.
803 * Sanity check req_count.
804 */
805 end_offset = req->req_count;
806 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
807 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
808
809 /* XXX Just return a dummy name for now */
810 len = req->req_count + strlen(location) - 1;
811
812 /* Sanity check for len */
813 if (len > 512)
814 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
815 plen = (len & ~0x3UL) + 4; /* Round to an int */
816
817 *msglen = sizeof(*rep) + (plen - 512);
818 mach_set_header(rep, req, *msglen);
819
820 rep->rep_retval = 0;
821 rep->rep_count = len;
822
823 cp = &rep->rep_path[0];
824 memcpy(cp, &req->req_plane, req->req_count);
825 cp += (req->req_count - 1); /* overwrite trailing \0 */
826 memcpy(cp, location, strlen(location));
827 cp += strlen(location);
828 *cp = '\0';
829
830 mach_set_trailer(rep, *msglen);
831
832 return 0;
833 }
834
835 int
836 mach_io_connect_map_memory(args)
837 struct mach_trap_args *args;
838 {
839 mach_io_connect_map_memory_request_t *req = args->smsg;
840 struct lwp *l = args->l;
841 mach_port_t mn;
842 struct mach_right *mr;
843 struct mach_iokit_devclass *mid;
844
845 mn = req->req_msgh.msgh_remote_port;
846 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
847 return mach_iokit_error(args, MACH_IOKIT_EPERM);
848
849 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
850 mid = mr->mr_port->mp_data;
851 if (mid->mid_connect_map_memory == NULL)
852 printf("no connect_map_memory method "
853 "for darwin_iokit_class %s\n", mid->mid_name);
854 else
855 return (mid->mid_connect_map_memory)(args);
856 }
857
858 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
859 }
860
861 int
862 mach_io_iterator_reset(args)
863 struct mach_trap_args *args;
864 {
865 mach_io_iterator_reset_request_t *req = args->smsg;
866 mach_io_iterator_reset_reply_t *rep = args->rmsg;
867 size_t *msglen = args->rsize;
868 struct lwp *l = args->l;
869 mach_port_t mn;
870 struct mach_right *mr;
871 struct mach_device_iterator *mdi;
872
873 mn = req->req_msgh.msgh_remote_port;
874 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
875 return mach_iokit_error(args, MACH_IOKIT_EPERM);
876
877 if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR)
878 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
879
880 mdi = mr->mr_port->mp_data;
881 mdi->mdi_current = 0;
882
883 *msglen = sizeof(*rep);
884 mach_set_header(rep, req, *msglen);
885
886 rep->rep_retval = 0;
887
888 mach_set_trailer(rep, *msglen);
889
890 return 0;
891 }
892
893 int
894 mach_io_connect_method_scalari_structo(args)
895 struct mach_trap_args *args;
896 {
897 mach_io_connect_method_scalari_structo_request_t *req = args->smsg;
898 struct lwp *l = args->l;
899 mach_port_t mn;
900 struct mach_right *mr;
901 struct mach_iokit_devclass *mid;
902 int end_offset;
903
904 /* Sanity check req_incount */
905 end_offset = req->req_incount +
906 (sizeof(req->req_outcount) / sizeof(req->req_in[0]));
907 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
908 return mach_msg_error(args, EINVAL);
909
910 /* Sanity check req_outcount */
911 if (req->req_outcount > 4096)
912 return mach_msg_error(args, EINVAL);
913
914 mn = req->req_msgh.msgh_remote_port;
915 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
916 return mach_iokit_error(args, MACH_IOKIT_EPERM);
917
918 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
919 mid = mr->mr_port->mp_data;
920 if (mid->mid_connect_method_scalari_structo == NULL)
921 printf("no connect_method_scalari_structo method "
922 "for darwin_iokit_class %s\n", mid->mid_name);
923 else
924 return (mid->mid_connect_method_scalari_structo)(args);
925 }
926
927 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
928 }
929
930 int
931 mach_io_connect_method_structi_structo(args)
932 struct mach_trap_args *args;
933 {
934 mach_io_connect_method_structi_structo_request_t *req = args->smsg;
935 struct lwp *l = args->l;
936 mach_port_t mn;
937 struct mach_right *mr;
938 struct mach_iokit_devclass *mid;
939 int end_offset;
940 int outcount;
941
942 /* Sanity check req_incount */
943 end_offset = req->req_incount +
944 (sizeof(req->req_outcount) / sizeof(req->req_in[0]));
945 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
946 return mach_msg_error(args, EINVAL);
947
948 /* Sanity check outcount. It is word aligned */
949 outcount = req->req_in[(req->req_incount & ~0x3UL) + 4];
950 if (outcount > 4096)
951 return mach_msg_error(args, EINVAL);
952
953 mn = req->req_msgh.msgh_remote_port;
954 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
955 return mach_iokit_error(args, MACH_IOKIT_EPERM);
956
957 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
958 mid = mr->mr_port->mp_data;
959 if (mid->mid_connect_method_structi_structo == NULL)
960 printf("no connect_method_structi_structo method "
961 "for darwin_iokit_class %s\n", mid->mid_name);
962 else
963 return (mid->mid_connect_method_structi_structo)(args);
964 }
965
966 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
967 }
968
969 int
970 mach_io_connect_set_properties(args)
971 struct mach_trap_args *args;
972 {
973 mach_io_connect_set_properties_request_t *req = args->smsg;
974 mach_io_connect_set_properties_reply_t *rep = args->rmsg;
975 size_t *msglen = args->rsize;
976
977 #ifdef DEBUG_MACH
978 uprintf("Unimplemented mach_io_connect_set_properties\n");
979 #endif
980
981 *msglen = sizeof(*rep);
982 mach_set_header(rep, req, *msglen);
983
984 mach_set_trailer(rep, *msglen);
985
986 return 0;
987 }
988
989 int
990 mach_io_service_close(args)
991 struct mach_trap_args *args;
992 {
993 mach_io_service_close_request_t *req = args->smsg;
994 mach_io_service_close_reply_t *rep = args->rmsg;
995 size_t *msglen = args->rsize;
996
997 #ifdef DEBUG_MACH
998 uprintf("Unimplemented mach_io_service_close\n");
999 #endif
1000
1001 *msglen = sizeof(*rep);
1002 mach_set_header(rep, req, *msglen);
1003
1004 rep->rep_retval = 0;
1005
1006 mach_set_trailer(rep, *msglen);
1007
1008 return 0;
1009 }
1010
1011 int
1012 mach_io_connect_add_client(args)
1013 struct mach_trap_args *args;
1014 {
1015 mach_io_connect_add_client_request_t *req = args->smsg;
1016 mach_io_connect_add_client_reply_t *rep = args->rmsg;
1017 size_t *msglen = args->rsize;
1018
1019 #ifdef DEBUG_MACH
1020 uprintf("Unimplemented mach_io_connect_add_client\n");
1021 #endif
1022
1023 *msglen = sizeof(*rep);
1024 mach_set_header(rep, req, *msglen);
1025
1026 rep->rep_retval = 0;
1027
1028 mach_set_trailer(rep, *msglen);
1029
1030 return 0;
1031 }
1032
1033 int
1034 mach_io_connect_method_scalari_structi(args)
1035 struct mach_trap_args *args;
1036 {
1037 mach_io_connect_method_scalari_structi_request_t *req = args->smsg;
1038 struct lwp *l = args->l;
1039 mach_port_t mn;
1040 struct mach_right *mr;
1041 struct mach_iokit_devclass *mid;
1042 int end_offset;
1043 int scalar_size, struct_size, instructcount;
1044
1045 /* Sanity check req_incount and get instructcount */
1046 if (MACH_REQMSG_OVERFLOW(args, req->req_in[req->req_incount]))
1047 return mach_msg_error(args, EINVAL);
1048 instructcount = req->req_in[req->req_incount];
1049
1050 /* Sanity check instructcount */
1051 scalar_size = sizeof(req->req_in[0]);
1052 struct_size = sizeof(req->req_instruct[0]);
1053 end_offset = req->req_incount +
1054 (sizeof(instructcount) / scalar_size) +
1055 (instructcount * struct_size / scalar_size);
1056 if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset]))
1057 return mach_msg_error(args, EINVAL);
1058
1059 mn = req->req_msgh.msgh_remote_port;
1060 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
1061 return mach_iokit_error(args, MACH_IOKIT_EPERM);
1062
1063 if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
1064 mid = mr->mr_port->mp_data;
1065 if (mid->mid_connect_method_scalari_structi == NULL)
1066 printf("no connect_method_scalari_structi method "
1067 "for darwin_iokit_class %s\n", mid->mid_name);
1068 else
1069 return (mid->mid_connect_method_scalari_structi)(args);
1070 }
1071
1072 return mach_iokit_error(args, MACH_IOKIT_ENODEV);
1073 }
1074
1075 int
1076 mach_io_registry_entry_from_path(args)
1077 struct mach_trap_args *args;
1078 {
1079 mach_io_registry_entry_from_path_request_t *req = args->smsg;
1080 mach_io_registry_entry_from_path_reply_t *rep = args->rmsg;
1081 size_t *msglen = args->rsize;
1082 struct lwp *l = args->l;
1083 struct mach_port *mp;
1084 struct mach_right *mr;
1085 struct mach_iokit_devclass *mid;
1086 int i, len;
1087 int end_offset;
1088
1089 /*
1090 * req_pathoffset is not used.
1091 * Sanity check req_pathcount.
1092 */
1093 end_offset = req->req_pathcount;
1094 if (MACH_REQMSG_OVERFLOW(args, req->req_path[end_offset]))
1095 return mach_msg_error(args, EINVAL);
1096
1097 #ifdef DEBUG_MACH
1098 printf("mach_io_registry_entry_from_path: path = %s\n", req->req_path);
1099 #endif
1100
1101 mp = mach_port_get();
1102 mp->mp_flags |= MACH_MP_INKERNEL;
1103 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
1104
1105 i = 0;
1106 while ((mid = mach_iokit_devclasses[i++]) != NULL) {
1107 len = strlen(mid->mid_name);
1108 #ifdef DEBUG_MACH
1109 printf("trying \"%s\" vs \"%s\"\n",
1110 &req->req_path[req->req_pathcount - 1 - len],
1111 mid->mid_name);
1112 #endif
1113 if (memcmp(&req->req_path[req->req_pathcount - 1 - len],
1114 mid->mid_name, len) == 0) {
1115 mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
1116 mp->mp_data = mid;
1117 break;
1118 }
1119 }
1120
1121 *msglen = sizeof(*rep);
1122 mach_set_header(rep, req, *msglen);
1123 mach_add_port_desc(rep, mr->mr_name);
1124 mach_set_trailer(rep, *msglen);
1125
1126 return 0;
1127 }
1128
1129 int
1130 mach_io_registry_entry_get_parent_iterator(args)
1131 struct mach_trap_args *args;
1132 {
1133 mach_io_registry_entry_get_parent_iterator_request_t *req = args->smsg;
1134 mach_io_registry_entry_get_parent_iterator_reply_t *rep = args->rmsg;
1135 size_t *msglen = args->rsize;
1136 struct lwp *l = args->l;
1137 struct mach_port *mp;
1138 struct mach_right *mr;
1139 struct mach_iokit_devclass *mid;
1140 struct mach_device_iterator *mdi;
1141 mach_port_t mn;
1142 int maxdev;
1143 size_t size;
1144 int end_offset;
1145
1146 /*
1147 * req_offset is unused
1148 * Sanity check req_count
1149 */
1150 end_offset = req->req_count;
1151 if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset]))
1152 return mach_msg_error(args, EINVAL);
1153
1154 #ifdef DEBUG_MACH
1155 printf("mach_io_registry_entry_get_parent_iterator: plane = %s\n",
1156 req->req_plane);
1157 #endif
1158
1159 mn = req->req_msgh.msgh_remote_port;
1160 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
1161 return mach_iokit_error(args, MACH_IOKIT_EPERM);
1162
1163 if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
1164 return mach_iokit_error(args, MACH_IOKIT_EINVAL);
1165 mid = mr->mr_port->mp_data;
1166
1167 mp = mach_port_get();
1168 mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
1169 mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
1170
1171 maxdev = sizeof(mach_iokit_devclasses);
1172 size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
1173 mdi = malloc(size, M_EMULDATA, M_WAITOK);
1174 mp->mp_data = mdi;
1175
1176 (void)mach_fill_parent_iterator(mdi, maxdev, 0, mid);
1177 mdi->mdi_current = 0;
1178
1179 mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
1180
1181 *msglen = sizeof(*rep);
1182 mach_set_header(rep, req, *msglen);
1183 mach_add_port_desc(rep, mr->mr_name);
1184 mach_set_trailer(rep, *msglen);
1185
1186 return 0;
1187 }
1188
1189 void
1190 mach_iokit_cleanup_notify(mr)
1191 struct mach_right *mr;
1192 {
1193 int i;
1194 struct mach_iokit_devclass *mid;
1195
1196 i = 0;
1197 while ((mid = mach_iokit_devclasses[i++]) != NULL)
1198 if (mid->mid_notify == mr)
1199 mid->mid_notify = NULL;
1200
1201 return;
1202 }
1203
1204 static int
1205 mach_fill_child_iterator(mdi, size, index, mid)
1206 struct mach_device_iterator *mdi;
1207 int size;
1208 int index;
1209 struct mach_iokit_devclass *mid;
1210 {
1211 struct mach_iokit_devclass **midp;
1212 struct mach_iokit_devclass **midq;
1213
1214 for (midp = mach_iokit_devclasses; *midp != NULL; midp++) {
1215 for (midq = (*midp)->mid_parent; *midq != NULL; midq++) {
1216 if (*midq == mid) {
1217 mdi->mdi_devices[index++] = *midp;
1218 break;
1219 }
1220 }
1221 #ifdef DIAGNOSTIC
1222 if (index >= size) {
1223 printf("mach_device_iterator overflow\n");
1224 break;
1225 }
1226 #endif
1227 }
1228 mdi->mdi_devices[index] = NULL;
1229
1230 return index;
1231 }
1232
1233 static int
1234 mach_fill_parent_iterator(mdi, size, index, mid)
1235 struct mach_device_iterator *mdi;
1236 int size;
1237 int index;
1238 struct mach_iokit_devclass *mid;
1239 {
1240 struct mach_iokit_devclass **midp;
1241
1242 for (midp = mid->mid_parent; *midp != NULL; midp++) {
1243 mdi->mdi_devices[index++] = *midp;
1244 #ifdef DIAGNOSTIC
1245 if (index >= size) {
1246 printf("mach_device_iterator overflow\n");
1247 break;
1248 }
1249 #endif
1250 }
1251 mdi->mdi_devices[index] = NULL;
1252
1253 return index;
1254 }
Cache object: f6925a0e3836493148de051e64a9273a
|