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