962a6c7d59
return packet was wrong (port descriptor instead of VM area descriptor), thus leading to SIGSEGV when calling IOKit's IOFBCreateSharedCursor(). Now this is fixed we can move forward again on graphic mode.
863 lines
27 KiB
C
863 lines
27 KiB
C
/* $NetBSD: mach_iokit.c,v 1.15 2003/05/13 20:48:16 manu Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by Emmanuel Dreyfus.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the NetBSD
|
|
* Foundation, Inc. and its contributors.
|
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "opt_compat_darwin.h"
|
|
#include <sys/cdefs.h>
|
|
__KERNEL_RCSID(0, "$NetBSD: mach_iokit.c,v 1.15 2003/05/13 20:48:16 manu Exp $");
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/signal.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/device.h>
|
|
|
|
#include <uvm/uvm_extern.h>
|
|
#include <uvm/uvm_map.h>
|
|
|
|
#include <compat/mach/mach_types.h>
|
|
#include <compat/mach/mach_message.h>
|
|
#include <compat/mach/mach_port.h>
|
|
#include <compat/mach/mach_errno.h>
|
|
#include <compat/mach/mach_iokit.h>
|
|
|
|
#ifdef COMPAT_DARWIN
|
|
#include <compat/darwin/darwin_iokit.h>
|
|
#endif
|
|
|
|
struct mach_iokit_devclass *mach_iokit_devclasses[] = {
|
|
#ifdef COMPAT_DARWIN
|
|
DARWIN_IOKIT_DEVCLASSES
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
int
|
|
mach_io_service_get_matching_services(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_service_get_matching_services_request_t *req = args->smsg;
|
|
mach_io_service_get_matching_services_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
struct mach_iokit_devclass *mid;
|
|
int i;
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
i = 0;
|
|
while ((mid = mach_iokit_devclasses[i++]) != NULL) {
|
|
if (memcmp(req->req_string, mid->mid_string,
|
|
strlen(mid->mid_string)) == 0) {
|
|
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
|
|
mp->mp_data = mid;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_match.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_match.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_iterator_next(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_iterator_next_request_t *req = args->smsg;
|
|
mach_io_iterator_next_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
struct device *dev;
|
|
struct mach_device_iterator *mdi;
|
|
mach_port_t mn;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
switch (mr->mr_port->mp_datatype) {
|
|
case MACH_MP_IOKIT_DEVCLASS:
|
|
/* Do not come here again */
|
|
mr->mr_port->mp_datatype = MACH_MP_IOKIT_DEVCLASS_DONE;
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
|
|
mp->mp_data = mr->mr_port->mp_data;
|
|
|
|
break;
|
|
|
|
case MACH_MP_DEVICE_ITERATOR:
|
|
mdi = mr->mr_port->mp_data;
|
|
|
|
/* XXX No lock for the device list? */
|
|
/* Check that mdi->mdi_parent still exists, else give up */
|
|
TAILQ_FOREACH(dev, &alldevs, dv_list)
|
|
if (dev == mdi->mdi_parent)
|
|
break;
|
|
if (dev == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
|
|
|
|
/* Check that mdi->mdi_current still exists, else reset it */
|
|
TAILQ_FOREACH(dev, &alldevs, dv_list)
|
|
if (dev == mdi->mdi_current)
|
|
break;
|
|
if (dev == NULL)
|
|
mdi->mdi_current = TAILQ_FIRST(&alldevs);
|
|
|
|
/* And now, find the next child of mdi->mdi_parent. */
|
|
do {
|
|
if (dev->dv_parent == mdi->mdi_parent) {
|
|
mdi->mdi_current = dev;
|
|
break;
|
|
}
|
|
} while ((dev = TAILQ_NEXT(dev, dv_list)) != NULL);
|
|
|
|
if (dev == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
mp->mp_datatype = MACH_MP_DEVICE;
|
|
mp->mp_data = mdi->mdi_current;
|
|
mdi->mdi_current = TAILQ_NEXT(mdi->mdi_current, dv_list);
|
|
break;
|
|
|
|
default:
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
break;
|
|
}
|
|
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_object.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_object.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_service_open(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_service_open_request_t *req = args->smsg;
|
|
mach_io_service_open_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
mach_port_t mn;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
|
|
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
|
|
mp->mp_data = mr->mr_port->mp_data;
|
|
}
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_connect.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_connect.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_connect_method_scalari_scalaro(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg;
|
|
mach_io_connect_method_scalari_scalaro_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
mach_port_t mn;
|
|
struct mach_right *mr;
|
|
struct mach_iokit_devclass *mid;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
|
|
mid = mr->mr_port->mp_data;
|
|
if (mid->mid_connect_method_scalari_scalaro == NULL)
|
|
printf("no connect_method_scalari_scalaro method "
|
|
"for darwin_iokit_class %s\n", mid->mid_name);
|
|
else
|
|
return (mid->mid_connect_method_scalari_scalaro)(args);
|
|
}
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_outcount = 0;
|
|
rep->rep_out[rep->rep_outcount + 1] = 8; /* XXX Trailer */
|
|
|
|
*msglen = sizeof(*rep) - ((4096 + rep->rep_outcount) * sizeof(int));
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_connect_get_service(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_connect_get_service_request_t *req = args->smsg;
|
|
mach_io_connect_get_service_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
mach_port_t mn;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
|
|
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
|
|
mp->mp_data = mr->mr_port->mp_data;
|
|
}
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
/*
|
|
* XXX Bump the refcount to workaround an emulation bug
|
|
* that causes Windowserver to release the port too early.
|
|
*/
|
|
mr->mr_refcount++;
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_service.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_service.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_create_iterator(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_create_iterator_request_t *req = args->smsg;
|
|
mach_io_registry_entry_create_iterator_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_iterator.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_iterator.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_object_conforms_to(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_object_conforms_to_request_t *req = args->smsg;
|
|
mach_io_object_conforms_to_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_conforms = 1; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_service_add_interest_notification(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_service_add_interest_notification_request_t *req = args->smsg;
|
|
mach_io_service_add_interest_notification_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_notification.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_notification.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_connect_set_notification_port(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_connect_set_notification_port_request_t *req = args->smsg;
|
|
mach_io_connect_set_notification_port_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_get_root_entry(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_get_root_entry_request_t *req = args->smsg;
|
|
mach_io_registry_get_root_entry_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= MACH_MP_INKERNEL;
|
|
mp->mp_datatype = MACH_MP_DEVICE;
|
|
mp->mp_data = TAILQ_FIRST(&alldevs);
|
|
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_root.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_root.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_get_child_iterator(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_get_child_iterator_request_t *req = args->smsg;
|
|
mach_io_registry_entry_get_child_iterator_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_port *mp;
|
|
struct mach_right *mr;
|
|
mach_port_t mn;
|
|
struct mach_device_iterator *mdi;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
if (mr->mr_port->mp_datatype != MACH_MP_DEVICE)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
|
|
mp = mach_port_get();
|
|
mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
|
|
mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
|
|
|
|
mdi = malloc(sizeof(*mdi), M_EMULDATA, M_WAITOK);
|
|
mdi->mdi_parent = mr->mr_port->mp_data;
|
|
mdi->mdi_current = TAILQ_FIRST(&alldevs);
|
|
mp->mp_data = mdi;
|
|
|
|
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_iterator.name = (mach_port_t)mr->mr_name;
|
|
rep->rep_iterator.disposition = 0x11; /* XXX */
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_get_name_in_plane(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_get_name_in_plane_request_t *req = args->smsg;
|
|
mach_io_registry_entry_get_name_in_plane_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
struct mach_right *mr;
|
|
mach_port_t mn;
|
|
struct device *dev;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
if (mr->mr_port->mp_datatype != MACH_MP_DEVICE)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
dev = mr->mr_port->mp_data;
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
/* XXX Just return a dummy name for now */
|
|
rep->rep_namecount = sizeof(dev->dv_xname);
|
|
memcpy(&rep->rep_name, dev->dv_xname, sizeof(dev->dv_xname));
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_object_get_class(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_object_get_class_request_t *req = args->smsg;
|
|
mach_io_object_get_class_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
char classname[] = "unknownClass";
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
/* XXX Just return a dummy name for now */
|
|
rep->rep_namecount = sizeof(classname);
|
|
memcpy(&rep->rep_name, classname, sizeof(classname));
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_get_location_in_plane(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_get_location_in_plane_request_t *req =
|
|
args->smsg;
|
|
mach_io_registry_entry_get_location_in_plane_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
char location[] = "";
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
/* XXX Just return a dummy name for now */
|
|
rep->rep_locationcount = sizeof(location);
|
|
memcpy(&rep->rep_location, location, sizeof(location));
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_get_properties(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_get_properties_request_t *req = args->smsg;
|
|
mach_io_registry_entry_get_properties_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
int error;
|
|
vaddr_t va;
|
|
size_t size;
|
|
mach_port_t mn;
|
|
struct mach_right *mr;
|
|
struct mach_iokit_devclass *mid;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
|
|
mid = mr->mr_port->mp_data;
|
|
if (mid->mid_properties == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
size = strlen(mid->mid_properties);
|
|
|
|
va = vm_map_min(&l->l_proc->p_vmspace->vm_map);
|
|
if ((error = uvm_map(&l->l_proc->p_vmspace->vm_map, &va,
|
|
round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0,
|
|
UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL,
|
|
UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0)
|
|
return mach_msg_error(args, error);
|
|
|
|
#ifdef DEBUG_MACH
|
|
printf("pid %d.%d: copyout iokit properties at %p\n",
|
|
l->l_proc->p_pid, l->l_lid, (void *)va);
|
|
#endif
|
|
if ((error = copyout(mid->mid_properties, (void *)va, size)) != 0) {
|
|
#ifdef DEBUG_MACH
|
|
printf("pid %d.%d: copyout iokit properties failed\n",
|
|
l->l_proc->p_pid, l->l_lid);
|
|
#endif
|
|
}
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_properties.address = (void *)va;
|
|
rep->rep_properties.size = size;
|
|
rep->rep_properties.deallocate = 0; /* XXX */
|
|
rep->rep_properties.copy = 2; /* XXX */
|
|
rep->rep_properties.pad1 = 1; /* XXX */
|
|
rep->rep_properties.type = 1; /* XXX */
|
|
rep->rep_count = size;
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_get_property(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_get_property_request_t *req = args->smsg;
|
|
mach_io_registry_entry_get_property_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
int error;
|
|
vaddr_t va;
|
|
size_t size;
|
|
size_t len;
|
|
mach_port_t mn;
|
|
struct mach_right *mr;
|
|
struct mach_iokit_devclass *mid;
|
|
struct mach_iokit_property *mip;
|
|
|
|
/* We do not handle non zero offset and multiple names yet */
|
|
if (req->req_property_nameoffset != 0) {
|
|
printf("pid %d.%d: mach_io_registry_entry_get_property "
|
|
"offset = %d\n", l->l_proc->p_pid, l->l_lid,
|
|
req->req_property_nameoffset);
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
}
|
|
if (req->req_property_namecount != 1) {
|
|
printf("pid %d.%d: mach_io_registry_entry_get_property "
|
|
"count = %d\n", l->l_proc->p_pid, l->l_lid,
|
|
req->req_property_namecount);
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
}
|
|
|
|
/* Find the port */
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
/* Find the devclass information */
|
|
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
|
|
mid = mr->mr_port->mp_data;
|
|
if (mid->mid_properties_array == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
|
|
/* Lookup the property name */
|
|
for (mip = mid->mid_properties_array; mip->mip_name; mip++) {
|
|
len = strlen(mip->mip_name);
|
|
if (memcmp(mip->mip_name, req->req_propery_name, len) == 0)
|
|
break;
|
|
}
|
|
if (mip->mip_value == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_ENOENT);
|
|
|
|
/* And copyout its associated value */
|
|
va = vm_map_min(&l->l_proc->p_vmspace->vm_map);
|
|
size = strlen(mip->mip_value);
|
|
|
|
if ((error = uvm_map(&l->l_proc->p_vmspace->vm_map, &va,
|
|
round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0,
|
|
UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL,
|
|
UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0)
|
|
return mach_msg_error(args, error);
|
|
|
|
#ifdef DEBUG_MACH
|
|
printf("pid %d.%d: copyout iokit property at %p\n",
|
|
l->l_proc->p_pid, l->l_lid, (void *)va);
|
|
#endif
|
|
if ((error = copyout(mip->mip_value, (void *)va, size)) != 0) {
|
|
#ifdef DEBUG_MACH
|
|
printf("pid %d.%d: copyout iokit property failed\n",
|
|
l->l_proc->p_pid, l->l_lid);
|
|
#endif
|
|
}
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
|
|
MACH_MSGH_BITS_COMPLEX;
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_body.msgh_descriptor_count = 1;
|
|
rep->rep_properties.address = (void *)va;
|
|
rep->rep_properties.size = size;
|
|
rep->rep_properties.deallocate = 0; /* XXX */
|
|
rep->rep_properties.copy = 2; /* XXX */
|
|
rep->rep_properties.pad1 = 0; /* XXX */
|
|
rep->rep_properties.type = 0; /* XXX */
|
|
rep->rep_properties_count = 1;
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_registry_entry_get_path(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_registry_entry_get_path_request_t *req = args->smsg;
|
|
mach_io_registry_entry_get_path_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
char location[] = ":/GossamerPE/pci@80000000/AppleGracklePCI/"
|
|
"ATY,264LT-G@11/.Display_Video_ATI_mach64-01018002/"
|
|
"display0/AppleBacklightDisplay";
|
|
char *cp;
|
|
size_t len, plen;
|
|
|
|
/* XXX Just return a dummy name for now */
|
|
len = req->req_count + strlen(location) - 1;
|
|
if (len > 512)
|
|
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
|
|
plen = (len & ~0x3UL) + 4; /* Round to an int */
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) +
|
|
(plen - 512) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_retval = 0;
|
|
rep->rep_count = len;
|
|
|
|
cp = &rep->rep_path[0];
|
|
memcpy(cp, &req->req_plane, req->req_count);
|
|
cp += (req->req_count - 1); /* overwrite trailing \0 */
|
|
memcpy(cp, location, strlen(location));
|
|
cp += strlen(location);
|
|
*cp = '\0';
|
|
|
|
rep->rep_path[plen + 7] = 8; /* Trailer */
|
|
|
|
*msglen = sizeof(*rep) + (plen - 512);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_connect_map_memory(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_connect_map_memory_request_t *req = args->smsg;
|
|
mach_io_connect_map_memory_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
mach_port_t mn;
|
|
struct mach_right *mr;
|
|
struct mach_iokit_devclass *mid;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
|
|
mid = mr->mr_port->mp_data;
|
|
if (mid->mid_connect_map_memory == NULL)
|
|
printf("no connect_map_memory method "
|
|
"for darwin_iokit_class %s\n", mid->mid_name);
|
|
else
|
|
return (mid->mid_connect_map_memory)(args);
|
|
}
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_retval = native_to_mach_errno[EINVAL];
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mach_io_iterator_reset(args)
|
|
struct mach_trap_args *args;
|
|
{
|
|
mach_io_iterator_reset_request_t *req = args->smsg;
|
|
mach_io_iterator_reset_reply_t *rep = args->rmsg;
|
|
size_t *msglen = args->rsize;
|
|
struct lwp *l = args->l;
|
|
mach_port_t mn;
|
|
struct mach_right *mr;
|
|
struct mach_device_iterator *mdi;
|
|
|
|
mn = req->req_msgh.msgh_remote_port;
|
|
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
|
|
return mach_iokit_error(args, MACH_IOKIT_EPERM);
|
|
|
|
switch(mr->mr_port->mp_datatype) {
|
|
case MACH_MP_DEVICE_ITERATOR:
|
|
mdi = mr->mr_port->mp_data;
|
|
mdi->mdi_parent = mr->mr_port->mp_data;
|
|
mdi->mdi_current = TAILQ_FIRST(&alldevs);
|
|
break;
|
|
|
|
case MACH_MP_IOKIT_DEVCLASS_DONE:
|
|
mr->mr_port->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
|
|
break;
|
|
|
|
case MACH_MP_IOKIT_DEVCLASS:
|
|
default:
|
|
printf("mach_io_iterator_reset: unknown type\n");
|
|
}
|
|
|
|
rep->rep_msgh.msgh_bits =
|
|
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
|
|
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
|
|
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
|
|
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
|
|
rep->rep_retval = 0;
|
|
rep->rep_trailer.msgh_trailer_size = 8;
|
|
|
|
*msglen = sizeof(*rep);
|
|
|
|
return 0;
|
|
}
|
|
|