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