d02239a3af
layer, but with a twist. The twist has to do with the fact that Microsoft supports structured exception handling in kernel mode. On the i386 arch, exception handling is implemented by hanging an exception registration list off the Thread Environment Block (TEB), and the TEB is accessed via the %fs register. The problem is, we use %fs as a pointer to the pcpu stucture, which means any driver that tries to write through %fs:0 will overwrite the curthread pointer and make a serious mess of things. To get around this, Project Evil now creates a special entry in the GDT on each processor. When we call into Windows code, a context switch routine will fix up %fs so it points to our new descriptor, which in turn points to a fake TEB. When the Windows code returns, or calls out to an external routine, we swap %fs back again. Currently, Project Evil makes use of GDT slot 7, which is all 0s by default. I fully expect someone to jump up and say I can't do that, but I couldn't find any code that makes use of this entry anywhere. Sadly, this was the only method I could come up with that worked on both UP and SMP. (Modifying the LDT works on UP, but becomes incredibly complicated on SMP.) If necessary, the context switching stuff can be yanked out while preserving the convention calling wrappers. (Fortunately, it looks like Microsoft uses some special epilog/prolog code on amd64 to implement exception handling, so the same nastiness won't be necessary on that arch.) The advantages are: - Any driver that uses %fs as though it were a TEB pointer won't clobber pcpu. - All the __stdcall/__fastcall/__regparm stuff that's specific to gcc goes away. Also, while I'm here, switch NdisGetSystemUpTime() back to using nanouptime() again. It turns out nanouptime() is way more accurate than just using ticks(). On slower machines, the Atheros drivers I tested seem to take a long time to associate due to the loss in accuracy.
159 lines
4.2 KiB
C
159 lines
4.2 KiB
C
/*-
|
|
* Copyright (c) 2005
|
|
* Bill Paul <wpaul@windriver.com>. All rights reserved.
|
|
*
|
|
* 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 Bill Paul.
|
|
* 4. Neither the name of the author nor the names of any co-contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
|
|
* 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 <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/unistd.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/lock.h>
|
|
#include <sys/mutex.h>
|
|
#include <sys/module.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <compat/ndis/pe_var.h>
|
|
#include <compat/ndis/cfg_var.h>
|
|
#include <compat/ndis/resource_var.h>
|
|
#include <compat/ndis/ntoskrnl_var.h>
|
|
#include <compat/ndis/ndis_var.h>
|
|
#include <compat/ndis/hal_var.h>
|
|
#include <compat/ndis/usbd_var.h>
|
|
|
|
static driver_object usbd_driver;
|
|
|
|
static uint32_t usbd_iodispatch(device_object *, irp *);
|
|
|
|
static void USBD_GetUSBDIVersion(usbd_version_info *);
|
|
static void dummy(void);
|
|
|
|
int
|
|
usbd_libinit(void)
|
|
{
|
|
image_patch_table *patch;
|
|
|
|
patch = usbd_functbl;
|
|
while (patch->ipt_func != NULL) {
|
|
windrv_wrap((funcptr)patch->ipt_func,
|
|
(funcptr *)&patch->ipt_wrap,
|
|
patch->ipt_argcnt, patch->ipt_ftype);
|
|
patch++;
|
|
}
|
|
|
|
/* Create a fake USB driver instance. */
|
|
|
|
windrv_bus_attach(&usbd_driver, "USB Bus");
|
|
|
|
/* Set up our dipatch routine. */
|
|
|
|
usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
|
|
(driver_dispatch)usbd_iodispatch;
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
usbd_libfini(void)
|
|
{
|
|
image_patch_table *patch;
|
|
|
|
patch = usbd_functbl;
|
|
while (patch->ipt_func != NULL) {
|
|
windrv_unwrap(patch->ipt_wrap);
|
|
patch++;
|
|
}
|
|
|
|
free(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static uint32_t
|
|
usbd_iodispatch(dobj, ip)
|
|
device_object *dobj;
|
|
irp *ip;
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
static void
|
|
USBD_GetUSBDIVersion(ui)
|
|
usbd_version_info *ui;
|
|
{
|
|
/* Pretend to be Windows XP. */
|
|
|
|
ui->uvi_usbdi_vers = USBDI_VERSION;
|
|
ui->uvi_supported_vers = USB_VER_2_0;
|
|
|
|
return;
|
|
}
|
|
|
|
static void
|
|
dummy(void)
|
|
{
|
|
printf("USBD dummy called\n");
|
|
return;
|
|
}
|
|
|
|
image_patch_table usbd_functbl[] = {
|
|
IMPORT_SFUNC(USBD_GetUSBDIVersion, 0),
|
|
IMPORT_SFUNC(usbd_iodispatch, 2),
|
|
#ifdef notyet
|
|
IMPORT_FUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28,
|
|
USBD_ParseConfigurationDescriptorEx),
|
|
IMPORT_FUNC_MAP(_USBD_CreateConfigurationRequestEx@8,
|
|
USBD_CreateConfigurationRequestEx),
|
|
#endif
|
|
|
|
/*
|
|
* This last entry is a catch-all for any function we haven't
|
|
* implemented yet. The PE import list patching routine will
|
|
* use it for any function that doesn't have an explicit match
|
|
* in this table.
|
|
*/
|
|
|
|
{ NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_CDECL },
|
|
|
|
/* End of list. */
|
|
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|