Added the original FreeBSD RELENG_54 files in sys/compat/ndis.
This commit is contained in:
parent
58cc83950f
commit
3d0ceda304
|
@ -0,0 +1,47 @@
|
|||
/*-
|
||||
* Copyright (c) 2003
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/compat/ndis/cfg_var.h,v 1.2.2.1 2005/01/30 00:59:19 imp Exp $
|
||||
*/
|
||||
|
||||
#ifndef _CFG_VAR_H_
|
||||
#define _CFG_VAR_H_
|
||||
|
||||
struct ndis_cfg {
|
||||
char *nc_cfgkey;
|
||||
char *nc_cfgdesc;
|
||||
char nc_val[256];
|
||||
int nc_idx;
|
||||
};
|
||||
|
||||
typedef struct ndis_cfg ndis_cfg;
|
||||
|
||||
#endif /* _CFG_VAR_H_ */
|
|
@ -0,0 +1,58 @@
|
|||
/*-
|
||||
* Copyright (c) 2003
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/compat/ndis/hal_var.h,v 1.4.2.2 2005/02/18 16:30:09 wpaul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _HAL_VAR_H_
|
||||
#define _HAL_VAR_H_
|
||||
|
||||
#ifdef __amd64__
|
||||
#define NDIS_BUS_SPACE_IO AMD64_BUS_SPACE_IO
|
||||
#define NDIS_BUS_SPACE_MEM AMD64_BUS_SPACE_MEM
|
||||
#else
|
||||
#define NDIS_BUS_SPACE_IO I386_BUS_SPACE_IO
|
||||
#define NDIS_BUS_SPACE_MEM I386_BUS_SPACE_MEM
|
||||
#endif
|
||||
|
||||
extern image_patch_table hal_functbl[];
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int hal_libinit(void);
|
||||
extern int hal_libfini(void);
|
||||
__fastcall extern uint8_t KfAcquireSpinLock(REGARGS1(kspin_lock *lock));
|
||||
__fastcall void KfReleaseSpinLock(REGARGS2(kspin_lock *lock, uint8_t newirql));
|
||||
__fastcall extern uint8_t KfRaiseIrql(REGARGS1(uint8_t irql));
|
||||
__fastcall extern void KfLowerIrql(REGARGS1(uint8_t oldirql));
|
||||
__stdcall extern uint8_t KeGetCurrentIrql(void);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _HAL_VAR_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,485 @@
|
|||
/*-
|
||||
* 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: src/sys/compat/ndis/kern_windrv.c,v 1.3.2.2 2005/03/31 04:24:35 wpaul Exp $");
|
||||
|
||||
#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>
|
||||
|
||||
struct windrv_type {
|
||||
uint16_t windrv_vid; /* for PCI or USB */
|
||||
uint16_t windrv_did; /* for PCI or USB */
|
||||
uint32_t windrv_subsys; /* for PCI */
|
||||
char *windrv_vname; /* for pccard */
|
||||
char *windrv_dname; /* for pccard */
|
||||
char *windrv_name; /* for pccard, PCI or USB */
|
||||
};
|
||||
|
||||
struct drvdb_ent {
|
||||
driver_object *windrv_object;
|
||||
struct windrv_type *windrv_devlist;
|
||||
ndis_cfg *windrv_regvals;
|
||||
STAILQ_ENTRY(drvdb_ent) link;
|
||||
};
|
||||
|
||||
struct mtx drvdb_mtx;
|
||||
static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head;
|
||||
|
||||
static driver_object fake_pci_driver; /* serves both PCI and cardbus */
|
||||
static driver_object fake_pccard_driver;
|
||||
|
||||
|
||||
#define DUMMY_REGISTRY_PATH "\\\\some\\bogus\\path"
|
||||
|
||||
int
|
||||
windrv_libinit(void)
|
||||
{
|
||||
STAILQ_INIT(&drvdb_head);
|
||||
mtx_init(&drvdb_mtx, "Windows driver DB lock",
|
||||
"Windows internal lock", MTX_DEF);
|
||||
|
||||
/*
|
||||
* PCI and pccard devices don't need to use IRPs to
|
||||
* interact with their bus drivers (usually), so our
|
||||
* emulated PCI and pccard drivers are just stubs.
|
||||
* USB devices, on the other hand, do all their I/O
|
||||
* by exchanging IRPs with the USB bus driver, so
|
||||
* for that we need to provide emulator dispatcher
|
||||
* routines, which are in a separate module.
|
||||
*/
|
||||
|
||||
windrv_bus_attach(&fake_pci_driver, "PCI Bus");
|
||||
windrv_bus_attach(&fake_pccard_driver, "PCCARD Bus");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
windrv_libfini(void)
|
||||
{
|
||||
struct drvdb_ent *d;
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
while(STAILQ_FIRST(&drvdb_head) != NULL) {
|
||||
d = STAILQ_FIRST(&drvdb_head);
|
||||
STAILQ_REMOVE_HEAD(&drvdb_head, link);
|
||||
free(d, M_DEVBUF);
|
||||
}
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
free(fake_pci_driver.dro_drivername.us_buf, M_DEVBUF);
|
||||
free(fake_pccard_driver.dro_drivername.us_buf, M_DEVBUF);
|
||||
|
||||
mtx_destroy(&drvdb_mtx);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the address of a driver image, find its corresponding
|
||||
* driver_object.
|
||||
*/
|
||||
|
||||
driver_object *
|
||||
windrv_lookup(img, name)
|
||||
vm_offset_t img;
|
||||
char *name;
|
||||
{
|
||||
struct drvdb_ent *d;
|
||||
unicode_string us;
|
||||
|
||||
/* Damn unicode. */
|
||||
|
||||
if (name != NULL) {
|
||||
us.us_len = strlen(name) * 2;
|
||||
us.us_maxlen = strlen(name) * 2;
|
||||
us.us_buf = NULL;
|
||||
ndis_ascii_to_unicode(name, &us.us_buf);
|
||||
}
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
STAILQ_FOREACH(d, &drvdb_head, link) {
|
||||
if (d->windrv_object->dro_driverstart == (void *)img ||
|
||||
bcmp((char *)d->windrv_object->dro_drivername.us_buf,
|
||||
(char *)us.us_buf, us.us_len) == 0) {
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
return(d->windrv_object);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
if (name != NULL)
|
||||
ExFreePool(us.us_buf);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a driver_object from our datatabase and destroy it. Throw
|
||||
* away any custom driver extension info that may have been added.
|
||||
*/
|
||||
|
||||
int
|
||||
windrv_unload(mod, img, len)
|
||||
module_t mod;
|
||||
vm_offset_t img;
|
||||
int len;
|
||||
{
|
||||
struct drvdb_ent *d, *r = NULL;
|
||||
driver_object *drv;
|
||||
list_entry *e, *c;
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
STAILQ_FOREACH(d, &drvdb_head, link) {
|
||||
if (d->windrv_object->dro_driverstart == (void *)img) {
|
||||
r = d;
|
||||
STAILQ_REMOVE(&drvdb_head, d, drvdb_ent, link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
if (r == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
/*
|
||||
* Destroy any custom extensions that may have been added.
|
||||
*/
|
||||
drv = r->windrv_object;
|
||||
e = drv->dro_driverext->dre_usrext.nle_flink;
|
||||
while (e != &drv->dro_driverext->dre_usrext) {
|
||||
c = e->nle_flink;
|
||||
REMOVE_LIST_ENTRY(e);
|
||||
ExFreePool(e);
|
||||
e = c;
|
||||
}
|
||||
|
||||
/* Free the driver extension */
|
||||
free(drv->dro_driverext, M_DEVBUF);
|
||||
|
||||
/* Free the driver name */
|
||||
free(drv->dro_drivername.us_buf, M_DEVBUF);
|
||||
|
||||
/* Free driver object */
|
||||
free(drv, M_DEVBUF);
|
||||
|
||||
/* Free our DB handle */
|
||||
free(r, M_DEVBUF);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loader routine for actual Windows driver modules, ultimately
|
||||
* calls the driver's DriverEntry() routine.
|
||||
*/
|
||||
|
||||
int
|
||||
windrv_load(mod, img, len)
|
||||
module_t mod;
|
||||
vm_offset_t img;
|
||||
int len;
|
||||
{
|
||||
image_import_descriptor imp_desc;
|
||||
image_optional_header opt_hdr;
|
||||
driver_entry entry;
|
||||
struct drvdb_ent *new;
|
||||
struct driver_object *drv;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* First step: try to relocate and dynalink the executable
|
||||
* driver image.
|
||||
*/
|
||||
|
||||
/* Perform text relocation */
|
||||
if (pe_relocate(img))
|
||||
return(ENOEXEC);
|
||||
|
||||
/* Dynamically link the NDIS.SYS routines -- required. */
|
||||
if (pe_patch_imports(img, "NDIS", ndis_functbl))
|
||||
return(ENOEXEC);
|
||||
|
||||
/* Dynamically link the HAL.dll routines -- also required. */
|
||||
if (pe_patch_imports(img, "HAL", hal_functbl))
|
||||
return(ENOEXEC);
|
||||
|
||||
/* Dynamically link ntoskrnl.exe -- optional. */
|
||||
if (pe_get_import_descriptor(img, &imp_desc, "ntoskrnl") == 0) {
|
||||
if (pe_patch_imports(img, "ntoskrnl", ntoskrnl_functbl))
|
||||
return(ENOEXEC);
|
||||
}
|
||||
|
||||
/* Dynamically link USBD.SYS -- optional */
|
||||
if (pe_get_import_descriptor(img, &imp_desc, "USBD") == 0) {
|
||||
if (pe_patch_imports(img, "USBD", usbd_functbl))
|
||||
return(ENOEXEC);
|
||||
}
|
||||
|
||||
/* Next step: find the driver entry point. */
|
||||
|
||||
pe_get_optional_header(img, &opt_hdr);
|
||||
entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr);
|
||||
|
||||
/* Next step: allocate and store a driver object. */
|
||||
|
||||
new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT);
|
||||
if (new == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
drv = malloc(sizeof(driver_object), M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
if (drv == NULL) {
|
||||
free (new, M_DEVBUF);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/* Allocate a driver extension structure too. */
|
||||
|
||||
drv->dro_driverext = malloc(sizeof(driver_extension),
|
||||
M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
|
||||
if (drv->dro_driverext == NULL) {
|
||||
free(new, M_DEVBUF);
|
||||
free(drv, M_DEVBUF);
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD((&drv->dro_driverext->dre_usrext));
|
||||
|
||||
drv->dro_driverstart = (void *)img;
|
||||
drv->dro_driversize = len;
|
||||
|
||||
drv->dro_drivername.us_len = strlen(DUMMY_REGISTRY_PATH) * 2;
|
||||
drv->dro_drivername.us_maxlen = strlen(DUMMY_REGISTRY_PATH) * 2;
|
||||
drv->dro_drivername.us_buf = NULL;
|
||||
ndis_ascii_to_unicode(DUMMY_REGISTRY_PATH,
|
||||
&drv->dro_drivername.us_buf);
|
||||
|
||||
new->windrv_object = drv;
|
||||
|
||||
/* Now call the DriverEntry() function. */
|
||||
|
||||
status = MSCALL2(entry, drv, &drv->dro_drivername);
|
||||
|
||||
if (status != STATUS_SUCCESS) {
|
||||
free(drv->dro_drivername.us_buf, M_DEVBUF);
|
||||
free(drv, M_DEVBUF);
|
||||
free(new, M_DEVBUF);
|
||||
return(ENODEV);
|
||||
}
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
STAILQ_INSERT_HEAD(&drvdb_head, new, link);
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a new Physical Device Object for a device that was
|
||||
* detected/plugged in. For us, the PDO is just a way to
|
||||
* get at the device_t.
|
||||
*/
|
||||
|
||||
int
|
||||
windrv_create_pdo(drv, bsddev)
|
||||
driver_object *drv;
|
||||
device_t bsddev;
|
||||
{
|
||||
device_object *dev;
|
||||
|
||||
/*
|
||||
* This is a new physical device object, which technically
|
||||
* is the "top of the stack." Consequently, we don't do
|
||||
* an IoAttachDeviceToDeviceStack() here.
|
||||
*/
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
IoCreateDevice(drv, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &dev);
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
/* Stash pointer to our BSD device handle. */
|
||||
|
||||
dev->do_devext = bsddev;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
windrv_destroy_pdo(drv, bsddev)
|
||||
driver_object *drv;
|
||||
device_t bsddev;
|
||||
{
|
||||
device_object *pdo;
|
||||
|
||||
pdo = windrv_find_pdo(drv, bsddev);
|
||||
|
||||
/* Remove reference to device_t */
|
||||
|
||||
pdo->do_devext = NULL;
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
IoDeleteDevice(pdo);
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a device_t, find the corresponding PDO in a driver's
|
||||
* device list.
|
||||
*/
|
||||
|
||||
device_object *
|
||||
windrv_find_pdo(drv, bsddev)
|
||||
driver_object *drv;
|
||||
device_t bsddev;
|
||||
{
|
||||
device_object *pdo;
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
pdo = drv->dro_devobj;
|
||||
if (pdo->do_devext != bsddev) {
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
panic("PDO wasn't first device in list");
|
||||
}
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
return(pdo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an internally emulated driver to the database. We need this
|
||||
* to set up an emulated bus driver so that it can receive IRPs.
|
||||
*/
|
||||
|
||||
int
|
||||
windrv_bus_attach(drv, name)
|
||||
driver_object *drv;
|
||||
char *name;
|
||||
{
|
||||
struct drvdb_ent *new;
|
||||
|
||||
new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT);
|
||||
if (new == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
drv->dro_drivername.us_len = strlen(name) * 2;
|
||||
drv->dro_drivername.us_maxlen = strlen(name) * 2;
|
||||
drv->dro_drivername.us_buf = NULL;
|
||||
ndis_ascii_to_unicode(name, &drv->dro_drivername.us_buf);
|
||||
|
||||
new->windrv_object = drv;
|
||||
new->windrv_devlist = NULL;
|
||||
new->windrv_regvals = NULL;
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
STAILQ_INSERT_HEAD(&drvdb_head, new, link);
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef __amd64__
|
||||
|
||||
extern void x86_64_wrap(void);
|
||||
extern void x86_64_wrap_call(void);
|
||||
extern void x86_64_wrap_end(void);
|
||||
|
||||
#endif /* __amd64__ */
|
||||
|
||||
int
|
||||
windrv_wrap(func, wrap)
|
||||
funcptr func;
|
||||
funcptr *wrap;
|
||||
{
|
||||
#ifdef __amd64__
|
||||
funcptr p;
|
||||
vm_offset_t *calladdr;
|
||||
vm_offset_t wrapstart, wrapend, wrapcall;
|
||||
|
||||
wrapstart = (vm_offset_t)&x86_64_wrap;
|
||||
wrapend = (vm_offset_t)&x86_64_wrap_end;
|
||||
wrapcall = (vm_offset_t)&x86_64_wrap_call;
|
||||
|
||||
/* Allocate a new wrapper instance. */
|
||||
|
||||
p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT);
|
||||
if (p == NULL)
|
||||
return(ENOMEM);
|
||||
|
||||
/* Copy over the code. */
|
||||
|
||||
bcopy((char *)wrapstart, p, (wrapend - wrapstart));
|
||||
|
||||
/* Insert the function address into the new wrapper instance. */
|
||||
|
||||
calladdr = (uint64_t *)((char *)p + (wrapcall - wrapstart) + 2);
|
||||
*calladdr = (vm_offset_t)func;
|
||||
|
||||
*wrap = p;
|
||||
#else /* __amd64__ */
|
||||
*wrap = func;
|
||||
#endif /* __amd64__ */
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
windrv_unwrap(func)
|
||||
funcptr func;
|
||||
{
|
||||
#ifdef __amd64__
|
||||
free(func, M_DEVBUF);
|
||||
#endif /* __amd64__ */
|
||||
return(0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,573 @@
|
|||
/*-
|
||||
* Copyright (c) 2003
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/compat/ndis/pe_var.h,v 1.8.2.2 2005/02/18 16:30:09 wpaul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PE_VAR_H_
|
||||
#define _PE_VAR_H_
|
||||
|
||||
/*
|
||||
* Image Format
|
||||
*/
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
|
||||
#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
|
||||
#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
|
||||
#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
|
||||
|
||||
/*
|
||||
* All PE files have one of these, just so if you attempt to
|
||||
* run them, they'll print out a message telling you they can
|
||||
* only be run in Windows.
|
||||
*/
|
||||
|
||||
struct image_dos_header {
|
||||
uint16_t idh_magic; /* Magic number */
|
||||
uint16_t idh_cblp; /* Bytes on last page of file */
|
||||
uint16_t idh_cp; /* Pages in file */
|
||||
uint16_t idh_crlc; /* Relocations */
|
||||
uint16_t idh_cparhdr; /* Size of header in paragraphs */
|
||||
uint16_t idh_minalloc; /* Minimum extra paragraphs needed */
|
||||
uint16_t idh_maxalloc; /* Maximum extra paragraphs needed */
|
||||
uint16_t idh_ss; /* Initial (relative) SS value */
|
||||
uint16_t idh_sp; /* Initial SP value */
|
||||
uint16_t idh_csum; /* Checksum */
|
||||
uint16_t idh_ip; /* Initial IP value */
|
||||
uint16_t idh_cs; /* Initial (relative) CS value */
|
||||
uint16_t idh_lfarlc; /* File address of relocation table */
|
||||
uint16_t idh_ovno; /* Overlay number */
|
||||
uint16_t idh_rsvd1[4]; /* Reserved words */
|
||||
uint16_t idh_oemid; /* OEM identifier (for idh_oeminfo) */
|
||||
uint16_t idh_oeminfo; /* OEM information; oemid specific */
|
||||
uint16_t idh_rsvd2[10]; /* Reserved words */
|
||||
uint32_t idh_lfanew; /* File address of new exe header */
|
||||
};
|
||||
|
||||
typedef struct image_dos_header image_dos_header;
|
||||
|
||||
/*
|
||||
* File header format.
|
||||
*/
|
||||
|
||||
struct image_file_header {
|
||||
uint16_t ifh_machine; /* Machine type */
|
||||
uint16_t ifh_numsections; /* # of sections */
|
||||
uint32_t ifh_timestamp; /* Date/time stamp */
|
||||
uint32_t ifh_symtblptr; /* Offset to symbol table */
|
||||
uint32_t ifh_numsyms; /* # of symbols */
|
||||
uint16_t ifh_optionalhdrlen; /* Size of optional header */
|
||||
uint16_t ifh_characteristics; /* Characteristics */
|
||||
};
|
||||
|
||||
typedef struct image_file_header image_file_header;
|
||||
|
||||
/* Machine types */
|
||||
|
||||
#define IMAGE_FILE_MACHINE_UNKNOWN 0
|
||||
#define IMAGE_FILE_MACHINE_I860 0x014d
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_MACHINE_R3000 0x0162
|
||||
#define IMAGE_FILE_MACHINE_R4000 0x0166
|
||||
#define IMAGE_FILE_MACHINE_R10000 0x0168
|
||||
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169
|
||||
#define IMAGE_FILE_MACHINE_ALPHA 0x0184
|
||||
#define IMAGE_FILE_MACHINE_SH3 0x01a2
|
||||
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
|
||||
#define IMAGE_FILE_MACHINE_SH3E 0x01a4
|
||||
#define IMAGE_FILE_MACHINE_SH4 0x01a6
|
||||
#define IMAGE_FILE_MACHINE_SH5 0x01a8
|
||||
#define IMAGE_FILE_MACHINE_ARM 0x01c0
|
||||
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
|
||||
#define IMAGE_FILE_MACHINE_AM33 0x01d3
|
||||
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
|
||||
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
|
||||
#define IMAGE_FILE_MACHINE_IA64 0x0200
|
||||
#define IMAGE_FILE_MACHINE_MIPS16 0x0266
|
||||
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284
|
||||
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366
|
||||
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466
|
||||
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
|
||||
#define IMAGE_FILE_MACHINE_TRICORE 0x0520
|
||||
#define IMAGE_FILE_MACHINE_CEF 0x0cef
|
||||
#define IMAGE_FILE_MACHINE_EBC 0x0ebc
|
||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
||||
#define IMAGE_FILE_MACHINE_M32R 0x9041
|
||||
#define IMAGE_FILE_MACHINE_CEE 0xc0ee
|
||||
|
||||
/* Characteristics */
|
||||
|
||||
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */
|
||||
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
|
||||
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
|
||||
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
|
||||
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010
|
||||
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
|
||||
#define IMAGE_FILE_16BIT_MACHINE 0x0040
|
||||
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
|
||||
#define IMAGE_FILE_32BIT_MACHINE 0x0100
|
||||
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
|
||||
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
|
||||
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
|
||||
#define IMAGE_FILE_SYSTEM 0x1000
|
||||
#define IMAGE_FILE_DLL 0x2000
|
||||
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
|
||||
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
|
||||
|
||||
#define IMAGE_SIZEOF_FILE_HEADER 20
|
||||
|
||||
/*
|
||||
* Directory format.
|
||||
*/
|
||||
|
||||
struct image_data_directory {
|
||||
uint32_t idd_vaddr; /* virtual address */
|
||||
uint32_t idd_size; /* size */
|
||||
};
|
||||
|
||||
typedef struct image_data_directory image_data_directory;
|
||||
|
||||
#define IMAGE_DIRECTORY_ENTRIES_MAX 16
|
||||
|
||||
/*
|
||||
* Optional header format.
|
||||
*/
|
||||
|
||||
struct image_optional_header {
|
||||
|
||||
/* Standard fields */
|
||||
|
||||
uint16_t ioh_magic;
|
||||
uint8_t ioh_linkerver_major;
|
||||
uint8_t ioh_linkerver_minor;
|
||||
uint32_t ioh_codesize;
|
||||
uint32_t ioh_datasize;
|
||||
uint32_t ioh_bsssize;
|
||||
uint32_t ioh_entryaddr;
|
||||
uint32_t ioh_codebaseaddr;
|
||||
#ifndef __amd64__
|
||||
uint32_t ioh_databaseaddr;
|
||||
#endif
|
||||
|
||||
/* NT-specific fields */
|
||||
|
||||
uintptr_t ioh_imagebase;
|
||||
uint32_t ioh_sectalign;
|
||||
uint32_t ioh_filealign;
|
||||
uint16_t ioh_osver_major;
|
||||
uint16_t ioh_osver_minor;
|
||||
uint16_t ioh_imagever_major;
|
||||
uint16_t ioh_imagever_minor;
|
||||
uint16_t ioh_subsys_major;
|
||||
uint16_t ioh_subsys_minor;
|
||||
uint32_t ioh_win32ver;
|
||||
uint32_t ioh_imagesize;
|
||||
uint32_t ioh_headersize;
|
||||
uint32_t ioh_csum;
|
||||
uint16_t ioh_subsys;
|
||||
uint16_t ioh_dll_characteristics;
|
||||
uintptr_t ioh_stackreservesize;
|
||||
uintptr_t ioh_stackcommitsize;
|
||||
uintptr_t ioh_heapreservesize;
|
||||
uintptr_t ioh_heapcommitsize;
|
||||
uint16_t ioh_loaderflags;
|
||||
uint32_t ioh_rva_size_cnt;
|
||||
image_data_directory ioh_datadir[IMAGE_DIRECTORY_ENTRIES_MAX];
|
||||
};
|
||||
|
||||
typedef struct image_optional_header image_optional_header;
|
||||
|
||||
struct image_nt_header {
|
||||
uint32_t inh_signature;
|
||||
image_file_header inh_filehdr;
|
||||
image_optional_header inh_optionalhdr;
|
||||
};
|
||||
|
||||
typedef struct image_nt_header image_nt_header;
|
||||
|
||||
/* Directory Entries */
|
||||
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */
|
||||
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 /* Description String */
|
||||
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* Machine Value (MIPS GP) */
|
||||
#define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */
|
||||
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */
|
||||
#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
|
||||
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
|
||||
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
|
||||
|
||||
/* Resource types */
|
||||
|
||||
#define RT_CURSOR 1
|
||||
#define RT_BITMAP 2
|
||||
#define RT_ICON 3
|
||||
#define RT_MENU 4
|
||||
#define RT_DIALOG 5
|
||||
#define RT_STRING 6
|
||||
#define RT_FONTDIR 7
|
||||
#define RT_FONT 8
|
||||
#define RT_ACCELERATOR 9
|
||||
#define RT_RCDATA 10
|
||||
#define RT_MESSAGETABLE 11
|
||||
#define RT_GROUP_CURSOR 12
|
||||
#define RT_GROUP_ICON 14
|
||||
#define RT_VERSION 16
|
||||
#define RT_DLGINCLUDE 17
|
||||
#define RT_PLUGPLAY 19
|
||||
#define RT_VXD 20
|
||||
#define RT_ANICURSOR 21
|
||||
#define RT_ANIICON 22
|
||||
#define RT_HTML 23
|
||||
|
||||
/*
|
||||
* Section header format.
|
||||
*/
|
||||
|
||||
#define IMAGE_SHORT_NAME_LEN 8
|
||||
|
||||
struct image_section_header {
|
||||
uint8_t ish_name[IMAGE_SHORT_NAME_LEN];
|
||||
union {
|
||||
uint32_t ish_paddr;
|
||||
uint32_t ish_vsize;
|
||||
} ish_misc;
|
||||
uint32_t ish_vaddr;
|
||||
uint32_t ish_rawdatasize;
|
||||
uint32_t ish_rawdataaddr;
|
||||
uint32_t ish_relocaddr;
|
||||
uint32_t ish_linenumaddr;
|
||||
uint16_t ish_numrelocs;
|
||||
uint16_t ish_numlinenums;
|
||||
uint32_t ish_characteristics;
|
||||
};
|
||||
|
||||
typedef struct image_section_header image_section_header;
|
||||
|
||||
#define IMAGE_SIZEOF_SECTION_HEADER 40
|
||||
|
||||
/*
|
||||
* Import format
|
||||
*/
|
||||
|
||||
struct image_import_by_name {
|
||||
uint16_t iibn_hint;
|
||||
uint8_t iibn_name[1];
|
||||
};
|
||||
|
||||
#define IMAGE_ORDINAL_FLAG 0x80000000
|
||||
#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
|
||||
|
||||
struct image_import_descriptor {
|
||||
uint32_t iid_import_name_table_addr;
|
||||
uint32_t iid_timestamp;
|
||||
uint32_t iid_forwardchain;
|
||||
uint32_t iid_nameaddr;
|
||||
uint32_t iid_import_address_table_addr;
|
||||
};
|
||||
|
||||
typedef struct image_import_descriptor image_import_descriptor;
|
||||
|
||||
struct image_base_reloc {
|
||||
uint32_t ibr_vaddr;
|
||||
uint32_t ibr_blocksize;
|
||||
uint16_t ibr_rel[1];
|
||||
};
|
||||
|
||||
typedef struct image_base_reloc image_base_reloc;
|
||||
|
||||
#define IMR_RELTYPE(x) ((x >> 12) & 0xF)
|
||||
#define IMR_RELOFFSET(x) (x & 0xFFF)
|
||||
|
||||
/* generic relocation types */
|
||||
#define IMAGE_REL_BASED_ABSOLUTE 0
|
||||
#define IMAGE_REL_BASED_HIGH 1
|
||||
#define IMAGE_REL_BASED_LOW 2
|
||||
#define IMAGE_REL_BASED_HIGHLOW 3
|
||||
#define IMAGE_REL_BASED_HIGHADJ 4
|
||||
#define IMAGE_REL_BASED_MIPS_JMPADDR 5
|
||||
#define IMAGE_REL_BASED_SECTION 6
|
||||
#define IMAGE_REL_BASED_REL 7
|
||||
#define IMAGE_REL_BASED_MIPS_JMPADDR16 9
|
||||
#define IMAGE_REL_BASED_IA64_IMM64 9 /* yes, 9 too */
|
||||
#define IMAGE_REL_BASED_DIR64 10
|
||||
#define IMAGE_REL_BASED_HIGH3ADJ 11
|
||||
|
||||
struct image_resource_directory_entry {
|
||||
uint32_t irde_name;
|
||||
uint32_t irde_dataoff;
|
||||
};
|
||||
|
||||
typedef struct image_resource_directory_entry image_resource_directory_entry;
|
||||
|
||||
#define RESOURCE_NAME_STR 0x80000000
|
||||
#define RESOURCE_DIR_FLAG 0x80000000
|
||||
|
||||
struct image_resource_directory {
|
||||
uint32_t ird_characteristics;
|
||||
uint32_t ird_timestamp;
|
||||
uint16_t ird_majorver;
|
||||
uint16_t ird_minorver;
|
||||
uint16_t ird_named_entries;
|
||||
uint16_t ird_id_entries;
|
||||
#ifdef notdef
|
||||
image_resource_directory_entry ird_entries[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct image_resource_directory image_resource_directory;
|
||||
|
||||
struct image_resource_directory_string {
|
||||
uint16_t irds_len;
|
||||
char irds_name[1];
|
||||
};
|
||||
|
||||
typedef struct image_resource_directory_string image_resource_directory_string;
|
||||
|
||||
struct image_resource_directory_string_u {
|
||||
uint16_t irds_len;
|
||||
char irds_name[1];
|
||||
};
|
||||
|
||||
typedef struct image_resource_directory_string_u
|
||||
image_resource_directory_string_u;
|
||||
|
||||
struct image_resource_data_entry {
|
||||
uint32_t irde_offset;
|
||||
uint32_t irde_size;
|
||||
uint32_t irde_codepage;
|
||||
uint32_t irde_rsvd;
|
||||
};
|
||||
|
||||
typedef struct image_resource_data_entry image_resource_data_entry;
|
||||
|
||||
struct message_resource_data {
|
||||
uint32_t mrd_numblocks;
|
||||
#ifdef notdef
|
||||
message_resource_block mrd_blocks[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct message_resource_data message_resource_data;
|
||||
|
||||
struct message_resource_block {
|
||||
uint32_t mrb_lowid;
|
||||
uint32_t mrb_highid;
|
||||
uint32_t mrb_entryoff;
|
||||
};
|
||||
|
||||
typedef struct message_resource_block message_resource_block;
|
||||
|
||||
struct message_resource_entry {
|
||||
uint16_t mre_len;
|
||||
uint16_t mre_flags;
|
||||
char mre_text[];
|
||||
};
|
||||
|
||||
typedef struct message_resource_entry message_resource_entry;
|
||||
|
||||
#define MESSAGE_RESOURCE_UNICODE 0x0001
|
||||
|
||||
struct image_patch_table {
|
||||
char *ipt_name;
|
||||
void (*ipt_func)(void);
|
||||
void (*ipt_wrap)(void);
|
||||
};
|
||||
|
||||
typedef struct image_patch_table image_patch_table;
|
||||
|
||||
/*
|
||||
* Note: Windows uses the _stdcall calling convention. This means
|
||||
* that the callback functions provided in the function table must
|
||||
* be declared using __attribute__((__stdcall__)), otherwise the
|
||||
* Windows code will likely screw up the %esp register and cause
|
||||
* us to jump to an invalid address when it returns.
|
||||
*/
|
||||
|
||||
#ifdef __amd64__
|
||||
#define __stdcall
|
||||
#define __regcall
|
||||
#define __fastcall
|
||||
#define REGARGS1(decl1) decl1
|
||||
#define REGARGS2(decl1, decl2) decl1, decl2
|
||||
#define REGCALL1(arg1) arg1
|
||||
#define REGCALL2(arg1, arg2) arg1, arg2
|
||||
#else
|
||||
#define __stdcall __attribute__((__stdcall__))
|
||||
#define __regcall __attribute__((__regparm__(3)))
|
||||
#define __fastcall __stdcall __regcall
|
||||
#define REGARGS1(decl1) int dummy1, int dummy2, decl1
|
||||
#define REGARGS2(decl1, decl2) int dummy1, decl2, decl1
|
||||
#define REGCALL1(arg1) 0, 0, arg1
|
||||
#define REGCALL2(arg1, arg2) 0, arg2, arg1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This mess allows us to call a _fastcall style routine with our
|
||||
* version of gcc, which lacks __attribute__((__fastcall__)). Only
|
||||
* has meaning on x86; everywhere else, it's a no-op.
|
||||
*/
|
||||
|
||||
#ifdef __i386__
|
||||
typedef __fastcall int (*fcall1)(REGARGS1(uint32_t));
|
||||
typedef __fastcall int (*fcall2)(REGARGS2(uint32_t, uint32_t));
|
||||
typedef __fastcall int (*fcall3)(REGARGS2(uint32_t, uint32_t), uint32_t);
|
||||
|
||||
static __inline uint32_t
|
||||
fastcall1(fcall1 f, uint32_t a)
|
||||
{
|
||||
return(f(REGCALL1(a)));
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
fastcall2(fcall2 f, uint32_t a, uint32_t b)
|
||||
{
|
||||
return(f(REGCALL2(a, b)));
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
fastcall3(fcall3 f, uint32_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
return(f(REGCALL2(a, b), c));
|
||||
}
|
||||
|
||||
#define FASTCALL1(f, a) \
|
||||
fastcall1((fcall1)(f), (uint32_t)(a))
|
||||
#define FASTCALL2(f, a, b) \
|
||||
fastcall2((fcall2)(f), (uint32_t)(a), (uint32_t)(b))
|
||||
#define FASTCALL3(f, a, b, c) \
|
||||
fastcall3((fcall3)(f), (uint32_t)(a), (uint32_t)(b), (uint32_t)(c))
|
||||
#else
|
||||
#define FASTCALL1(f, a) (f)((a))
|
||||
#define FASTCALL2(f, a, b) (f)((a), (b))
|
||||
#define FASTCALL3(f, a, b, c) (f)((a), (b), (c))
|
||||
#endif /* __i386__ */
|
||||
|
||||
|
||||
/*
|
||||
* AMD64 support. Microsoft uses a different calling convention
|
||||
* than everyone else on the amd64 platform. Sadly, gcc has no
|
||||
* built-in support for it (yet).
|
||||
*
|
||||
* The three major differences we're concerned with are:
|
||||
*
|
||||
* - The first 4 register-sized arguments are passed in the
|
||||
* %rcx, %rdx, %r8 and %r9 registers, and the rest are pushed
|
||||
* onto the stack. (The ELF ABI uses 6 registers, not 4).
|
||||
*
|
||||
* - The caller must reserve space on the stack for the 4
|
||||
* register arguments in case the callee has to spill them.
|
||||
*
|
||||
* - The stack myst be 16-byte aligned by the time the callee
|
||||
* executes. A call instruction implicitly pushes an 8 byte
|
||||
* return address onto the stack. We have to make sure that
|
||||
* the amount of space we consume, plus the return address,
|
||||
* is a multiple of 16 bytes in size. This means that in
|
||||
* some cases, we may need to chew up an extra 8 bytes on
|
||||
* the stack that will be unused.
|
||||
*
|
||||
* On the bright side, Microsoft seems to be using just the one
|
||||
* calling convention for all functions on amd64, unlike x86 where
|
||||
* they use a mix of _stdcall, _fastcall and _cdecl.
|
||||
*/
|
||||
|
||||
#ifdef __amd64__
|
||||
|
||||
extern uint64_t x86_64_call1(void *, uint64_t);
|
||||
extern uint64_t x86_64_call2(void *, uint64_t, uint64_t);
|
||||
extern uint64_t x86_64_call3(void *, uint64_t, uint64_t, uint64_t);
|
||||
extern uint64_t x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||
extern uint64_t x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t,
|
||||
uint64_t);
|
||||
extern uint64_t x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t,
|
||||
uint64_t, uint64_t);
|
||||
|
||||
|
||||
#define MSCALL1(fn, a) \
|
||||
x86_64_call1((fn), (uint64_t)(a))
|
||||
#define MSCALL2(fn, a, b) \
|
||||
x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b))
|
||||
#define MSCALL3(fn, a, b, c) \
|
||||
x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b), \
|
||||
(uint64_t)(c))
|
||||
#define MSCALL4(fn, a, b, c, d) \
|
||||
x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b), \
|
||||
(uint64_t)(c), (uint64_t)(d))
|
||||
#define MSCALL5(fn, a, b, c, d, e) \
|
||||
x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b), \
|
||||
(uint64_t)(c), (uint64_t)(d), (uint64_t)(e))
|
||||
#define MSCALL6(fn, a, b, c, d, e, f) \
|
||||
x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b), \
|
||||
(uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f))
|
||||
|
||||
#else /* __amd64__ */
|
||||
|
||||
#define MSCALL1(fn, a) (fn)((a))
|
||||
#define MSCALL2(fn, a, b) (fn)((a), (b))
|
||||
#define MSCALL3(fn, a, b, c) (fn)((a), (b), (c))
|
||||
#define MSCALL4(fn, a, b, c, d) (fn)((a), (b), (c), (d))
|
||||
#define MSCALL5(fn, a, b, c, d, e) (fn)((a), (b), (c), (d), (e))
|
||||
#define MSCALL6(fn, a, b, c, d, e, f) (fn)((a), (b), (c), (d), (e), (f))
|
||||
|
||||
#endif /* __amd64__ */
|
||||
|
||||
|
||||
#define FUNC void(*)(void)
|
||||
#define IMPORT_FUNC(x) { #x, (FUNC)x, NULL }
|
||||
#define IMPORT_FUNC_MAP(x, y) { #x, (FUNC)y, NULL }
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int pe_get_dos_header(vm_offset_t, image_dos_header *);
|
||||
extern int pe_is_nt_image(vm_offset_t);
|
||||
extern int pe_get_optional_header(vm_offset_t, image_optional_header *);
|
||||
extern int pe_get_file_header(vm_offset_t, image_file_header *);
|
||||
extern int pe_get_section_header(vm_offset_t, image_section_header *);
|
||||
extern int pe_numsections(vm_offset_t);
|
||||
extern vm_offset_t pe_imagebase(vm_offset_t);
|
||||
extern vm_offset_t pe_directory_offset(vm_offset_t, uint32_t);
|
||||
extern vm_offset_t pe_translate_addr (vm_offset_t, vm_offset_t);
|
||||
extern int pe_get_section(vm_offset_t, image_section_header *, const char *);
|
||||
extern int pe_relocate(vm_offset_t);
|
||||
extern int pe_get_import_descriptor(vm_offset_t, image_import_descriptor *, char *);
|
||||
extern int pe_patch_imports(vm_offset_t, char *, image_patch_table *);
|
||||
extern int pe_get_messagetable(vm_offset_t, message_resource_data **);
|
||||
extern int pe_get_message(vm_offset_t, uint32_t, char **, int *, uint16_t *);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PE_VAR_H_ */
|
|
@ -0,0 +1,199 @@
|
|||
/*-
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/compat/ndis/resource_var.h,v 1.2.2.1 2005/02/18 16:30:09 wpaul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _RESOURCE_VAR_H_
|
||||
#define _RESOURCE_VAR_H_
|
||||
|
||||
typedef int cm_resource_type;
|
||||
|
||||
struct physaddr {
|
||||
uint64_t np_quad;
|
||||
#ifdef notdef
|
||||
uint32_t np_low;
|
||||
uint32_t np_high;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct physaddr physaddr;
|
||||
|
||||
enum interface_type {
|
||||
InterfaceTypeUndefined = -1,
|
||||
Internal,
|
||||
Isa,
|
||||
Eisa,
|
||||
MicroChannel,
|
||||
TurboChannel,
|
||||
PCIBus,
|
||||
VMEBus,
|
||||
NuBus,
|
||||
PCMCIABus,
|
||||
CBus,
|
||||
MPIBus,
|
||||
MPSABus,
|
||||
ProcessorInternal,
|
||||
InternalPowerBus,
|
||||
PNPISABus,
|
||||
PNPBus,
|
||||
MaximumInterfaceType
|
||||
};
|
||||
|
||||
typedef enum interface_type interface_type;
|
||||
|
||||
#define CmResourceTypeNull 0 /* ResType_All or ResType_None (0x0000) */
|
||||
#define CmResourceTypePort 1 /* ResType_IO (0x0002) */
|
||||
#define CmResourceTypeInterrupt 2 /* ResType_IRQ (0x0004) */
|
||||
#define CmResourceTypeMemory 3 /* ResType_Mem (0x0001) */
|
||||
#define CmResourceTypeDma 4 /* ResType_DMA (0x0003) */
|
||||
#define CmResourceTypeDeviceSpecific 5 /* ResType_ClassSpecific (0xFFFF) */
|
||||
#define CmResourceTypeBusNumber 6 /* ResType_BusNumber (0x0006) */
|
||||
#define CmResourceTypeMaximum 7
|
||||
#define CmResourceTypeNonArbitrated 128 /* Not arbitrated if 0x80 bit set */
|
||||
#define CmResourceTypeConfigData 128 /* ResType_Reserved (0x8000) */
|
||||
#define CmResourceTypeDevicePrivate 129 /* ResType_DevicePrivate (0x8001) */
|
||||
#define CmResourceTypePcCardConfig 130 /* ResType_PcCardConfig (0x8002) */
|
||||
|
||||
enum cm_share_disposition {
|
||||
CmResourceShareUndetermined = 0, /* Reserved */
|
||||
CmResourceShareDeviceExclusive,
|
||||
CmResourceShareDriverExclusive,
|
||||
CmResourceShareShared
|
||||
};
|
||||
|
||||
typedef enum cm_share_disposition cm_share_disposition;
|
||||
|
||||
/* Define the bit masks for Flags when type is CmResourceTypeInterrupt */
|
||||
|
||||
#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0
|
||||
#define CM_RESOURCE_INTERRUPT_LATCHED 1
|
||||
|
||||
/* Define the bit masks for Flags when type is CmResourceTypeMemory */
|
||||
|
||||
#define CM_RESOURCE_MEMORY_READ_WRITE 0x0000
|
||||
#define CM_RESOURCE_MEMORY_READ_ONLY 0x0001
|
||||
#define CM_RESOURCE_MEMORY_WRITE_ONLY 0x0002
|
||||
#define CM_RESOURCE_MEMORY_PREFETCHABLE 0x0004
|
||||
|
||||
#define CM_RESOURCE_MEMORY_COMBINEDWRITE 0x0008
|
||||
#define CM_RESOURCE_MEMORY_24 0x0010
|
||||
#define CM_RESOURCE_MEMORY_CACHEABLE 0x0020
|
||||
|
||||
/* Define the bit masks for Flags when type is CmResourceTypePort */
|
||||
|
||||
#define CM_RESOURCE_PORT_MEMORY 0x0000
|
||||
#define CM_RESOURCE_PORT_IO 0x0001
|
||||
#define CM_RESOURCE_PORT_10_BIT_DECODE 0x0004
|
||||
#define CM_RESOURCE_PORT_12_BIT_DECODE 0x0008
|
||||
#define CM_RESOURCE_PORT_16_BIT_DECODE 0x0010
|
||||
#define CM_RESOURCE_PORT_POSITIVE_DECODE 0x0020
|
||||
#define CM_RESOURCE_PORT_PASSIVE_DECODE 0x0040
|
||||
#define CM_RESOURCE_PORT_WINDOW_DECODE 0x0080
|
||||
|
||||
/* Define the bit masks for Flags when type is CmResourceTypeDma */
|
||||
|
||||
#define CM_RESOURCE_DMA_8 0x0000
|
||||
#define CM_RESOURCE_DMA_16 0x0001
|
||||
#define CM_RESOURCE_DMA_32 0x0002
|
||||
#define CM_RESOURCE_DMA_8_AND_16 0x0004
|
||||
#define CM_RESOURCE_DMA_BUS_MASTER 0x0008
|
||||
#define CM_RESOURCE_DMA_TYPE_A 0x0010
|
||||
#define CM_RESOURCE_DMA_TYPE_B 0x0020
|
||||
#define CM_RESOURCE_DMA_TYPE_F 0x0040
|
||||
|
||||
struct cm_partial_resource_desc {
|
||||
uint8_t cprd_type;
|
||||
uint8_t cprd_sharedisp;
|
||||
uint16_t cprd_flags;
|
||||
union {
|
||||
struct {
|
||||
physaddr cprd_start;
|
||||
uint32_t cprd_len;
|
||||
} cprd_generic;
|
||||
struct {
|
||||
physaddr cprd_start;
|
||||
uint32_t cprd_len;
|
||||
} cprd_port;
|
||||
struct {
|
||||
uint32_t cprd_level;
|
||||
uint32_t cprd_vector;
|
||||
uint32_t cprd_affinity;
|
||||
} cprd_intr;
|
||||
struct {
|
||||
physaddr cprd_start;
|
||||
uint32_t cprd_len;
|
||||
} cprd_mem;
|
||||
struct {
|
||||
uint32_t cprd_chan;
|
||||
uint32_t cprd_port;
|
||||
uint32_t cprd_rsvd;
|
||||
} cprd_dmachan;
|
||||
struct {
|
||||
uint32_t cprd_data[3];
|
||||
} cprd_devpriv;
|
||||
struct {
|
||||
uint32_t cprd_datasize;
|
||||
uint32_t cprd_rsvd1;
|
||||
uint32_t cprd_rsvd2;
|
||||
} cprd_devspec;
|
||||
} u __attribute__((packed));
|
||||
};
|
||||
|
||||
typedef struct cm_partial_resource_desc cm_partial_resource_desc;
|
||||
|
||||
struct cm_partial_resource_list {
|
||||
uint16_t cprl_version;
|
||||
uint16_t cprl_revision;
|
||||
uint32_t cprl_count;
|
||||
cm_partial_resource_desc cprl_partial_descs[1];
|
||||
};
|
||||
|
||||
typedef struct cm_partial_resource_list cm_partial_resource_list;
|
||||
|
||||
struct cm_full_resource_list {
|
||||
interface_type cfrl_type;
|
||||
uint32_t cfrl_busnum;
|
||||
cm_partial_resource_desc cfrl_partiallist;
|
||||
};
|
||||
|
||||
typedef struct cm_full_resource_list cm_full_resource_list;
|
||||
|
||||
struct cm_resource_list {
|
||||
uint32_t crl_count;
|
||||
cm_full_resource_list crl_rlist;
|
||||
};
|
||||
|
||||
typedef struct cm_resource_list cm_resource_list;
|
||||
|
||||
typedef cm_partial_resource_list ndis_resource_list;
|
||||
|
||||
#endif /* _RESOURCE_VAR_H_ */
|
|
@ -0,0 +1,412 @@
|
|||
/*-
|
||||
* Copyright (c) 2003
|
||||
* 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: src/sys/compat/ndis/subr_hal.c,v 1.13.2.3 2005/03/31 04:24:35 wpaul Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <sys/callout.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sched.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <sys/systm.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <compat/ndis/pe_var.h>
|
||||
#include <compat/ndis/ntoskrnl_var.h>
|
||||
#include <compat/ndis/hal_var.h>
|
||||
|
||||
__stdcall static void KeStallExecutionProcessor(uint32_t);
|
||||
__stdcall static void WRITE_PORT_BUFFER_ULONG(uint32_t *,
|
||||
uint32_t *, uint32_t);
|
||||
__stdcall static void WRITE_PORT_BUFFER_USHORT(uint16_t *,
|
||||
uint16_t *, uint32_t);
|
||||
__stdcall static void WRITE_PORT_BUFFER_UCHAR(uint8_t *,
|
||||
uint8_t *, uint32_t);
|
||||
__stdcall static void WRITE_PORT_ULONG(uint32_t *, uint32_t);
|
||||
__stdcall static void WRITE_PORT_USHORT(uint16_t *, uint16_t);
|
||||
__stdcall static void WRITE_PORT_UCHAR(uint8_t *, uint8_t);
|
||||
__stdcall static uint32_t READ_PORT_ULONG(uint32_t *);
|
||||
__stdcall static uint16_t READ_PORT_USHORT(uint16_t *);
|
||||
__stdcall static uint8_t READ_PORT_UCHAR(uint8_t *);
|
||||
__stdcall static void READ_PORT_BUFFER_ULONG(uint32_t *,
|
||||
uint32_t *, uint32_t);
|
||||
__stdcall static void READ_PORT_BUFFER_USHORT(uint16_t *,
|
||||
uint16_t *, uint32_t);
|
||||
__stdcall static void READ_PORT_BUFFER_UCHAR(uint8_t *,
|
||||
uint8_t *, uint32_t);
|
||||
__stdcall static uint64_t KeQueryPerformanceCounter(uint64_t *);
|
||||
__stdcall static void dummy (void);
|
||||
|
||||
extern struct mtx_pool *ndis_mtxpool;
|
||||
|
||||
int
|
||||
hal_libinit()
|
||||
{
|
||||
image_patch_table *patch;
|
||||
|
||||
patch = hal_functbl;
|
||||
while (patch->ipt_func != NULL) {
|
||||
windrv_wrap((funcptr)patch->ipt_func,
|
||||
(funcptr *)&patch->ipt_wrap);
|
||||
patch++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
hal_libfini()
|
||||
{
|
||||
image_patch_table *patch;
|
||||
|
||||
patch = hal_functbl;
|
||||
while (patch->ipt_func != NULL) {
|
||||
windrv_unwrap(patch->ipt_wrap);
|
||||
patch++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
KeStallExecutionProcessor(usecs)
|
||||
uint32_t usecs;
|
||||
{
|
||||
DELAY(usecs);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
WRITE_PORT_ULONG(port, val)
|
||||
uint32_t *port;
|
||||
uint32_t val;
|
||||
{
|
||||
bus_space_write_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
WRITE_PORT_USHORT(port, val)
|
||||
uint16_t *port;
|
||||
uint16_t val;
|
||||
{
|
||||
bus_space_write_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
WRITE_PORT_UCHAR(port, val)
|
||||
uint8_t *port;
|
||||
uint8_t val;
|
||||
{
|
||||
bus_space_write_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
WRITE_PORT_BUFFER_ULONG(port, val, cnt)
|
||||
uint32_t *port;
|
||||
uint32_t *val;
|
||||
uint32_t cnt;
|
||||
{
|
||||
bus_space_write_multi_4(NDIS_BUS_SPACE_IO, 0x0,
|
||||
(bus_size_t)port, val, cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
WRITE_PORT_BUFFER_USHORT(port, val, cnt)
|
||||
uint16_t *port;
|
||||
uint16_t *val;
|
||||
uint32_t cnt;
|
||||
{
|
||||
bus_space_write_multi_2(NDIS_BUS_SPACE_IO, 0x0,
|
||||
(bus_size_t)port, val, cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
WRITE_PORT_BUFFER_UCHAR(port, val, cnt)
|
||||
uint8_t *port;
|
||||
uint8_t *val;
|
||||
uint32_t cnt;
|
||||
{
|
||||
bus_space_write_multi_1(NDIS_BUS_SPACE_IO, 0x0,
|
||||
(bus_size_t)port, val, cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static uint16_t
|
||||
READ_PORT_USHORT(port)
|
||||
uint16_t *port;
|
||||
{
|
||||
return(bus_space_read_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
|
||||
}
|
||||
|
||||
__stdcall static uint32_t
|
||||
READ_PORT_ULONG(port)
|
||||
uint32_t *port;
|
||||
{
|
||||
return(bus_space_read_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
|
||||
}
|
||||
|
||||
__stdcall static uint8_t
|
||||
READ_PORT_UCHAR(port)
|
||||
uint8_t *port;
|
||||
{
|
||||
return(bus_space_read_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
READ_PORT_BUFFER_ULONG(port, val, cnt)
|
||||
uint32_t *port;
|
||||
uint32_t *val;
|
||||
uint32_t cnt;
|
||||
{
|
||||
bus_space_read_multi_4(NDIS_BUS_SPACE_IO, 0x0,
|
||||
(bus_size_t)port, val, cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
READ_PORT_BUFFER_USHORT(port, val, cnt)
|
||||
uint16_t *port;
|
||||
uint16_t *val;
|
||||
uint32_t cnt;
|
||||
{
|
||||
bus_space_read_multi_2(NDIS_BUS_SPACE_IO, 0x0,
|
||||
(bus_size_t)port, val, cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
READ_PORT_BUFFER_UCHAR(port, val, cnt)
|
||||
uint8_t *port;
|
||||
uint8_t *val;
|
||||
uint32_t cnt;
|
||||
{
|
||||
bus_space_read_multi_1(NDIS_BUS_SPACE_IO, 0x0,
|
||||
(bus_size_t)port, val, cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The spinlock implementation in Windows differs from that of FreeBSD.
|
||||
* The basic operation of spinlocks involves two steps: 1) spin in a
|
||||
* tight loop while trying to acquire a lock, 2) after obtaining the
|
||||
* lock, disable preemption. (Note that on uniprocessor systems, you're
|
||||
* allowed to skip the first step and just lock out pre-emption, since
|
||||
* it's not possible for you to be in contention with another running
|
||||
* thread.) Later, you release the lock then re-enable preemption.
|
||||
* The difference between Windows and FreeBSD lies in how preemption
|
||||
* is disabled. In FreeBSD, it's done using critical_enter(), which on
|
||||
* the x86 arch translates to a cli instruction. This masks off all
|
||||
* interrupts, and effectively stops the scheduler from ever running
|
||||
* so _nothing_ can execute except the current thread. In Windows,
|
||||
* preemption is disabled by raising the processor IRQL to DISPATCH_LEVEL.
|
||||
* This stops other threads from running, but does _not_ block device
|
||||
* interrupts. This means ISRs can still run, and they can make other
|
||||
* threads runable, but those other threads won't be able to execute
|
||||
* until the current thread lowers the IRQL to something less than
|
||||
* DISPATCH_LEVEL.
|
||||
*
|
||||
* There's another commonly used IRQL in Windows, which is APC_LEVEL.
|
||||
* An APC is an Asynchronous Procedure Call, which differs from a DPC
|
||||
* (Defered Procedure Call) in that a DPC is queued up to run in
|
||||
* another thread, while an APC runs in the thread that scheduled
|
||||
* it (similar to a signal handler in a UNIX process). We don't
|
||||
* actually support the notion of APCs in FreeBSD, so for now, the
|
||||
* only IRQLs we're interested in are DISPATCH_LEVEL and PASSIVE_LEVEL.
|
||||
*
|
||||
* To simulate DISPATCH_LEVEL, we raise the current thread's priority
|
||||
* to PI_REALTIME, which is the highest we can give it. This should,
|
||||
* if I understand things correctly, prevent anything except for an
|
||||
* interrupt thread from preempting us. PASSIVE_LEVEL is basically
|
||||
* everything else.
|
||||
*
|
||||
* Be aware that, at least on the x86 arch, the Windows spinlock
|
||||
* functions are divided up in peculiar ways. The actual spinlock
|
||||
* functions are KfAcquireSpinLock() and KfReleaseSpinLock(), and
|
||||
* they live in HAL.dll. Meanwhile, KeInitializeSpinLock(),
|
||||
* KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
|
||||
* live in ntoskrnl.exe. Most Windows source code will call
|
||||
* KeAcquireSpinLock() and KeReleaseSpinLock(), but these are just
|
||||
* macros that call KfAcquireSpinLock() and KfReleaseSpinLock().
|
||||
* KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
|
||||
* perform the lock aquisition/release functions without doing the
|
||||
* IRQL manipulation, and are used when one is already running at
|
||||
* DISPATCH_LEVEL. Make sense? Good.
|
||||
*
|
||||
* According to the Microsoft documentation, any thread that calls
|
||||
* KeAcquireSpinLock() must be running at IRQL <= DISPATCH_LEVEL. If
|
||||
* we detect someone trying to acquire a spinlock from DEVICE_LEVEL
|
||||
* or HIGH_LEVEL, we panic.
|
||||
*/
|
||||
|
||||
__fastcall uint8_t
|
||||
KfAcquireSpinLock(REGARGS1(kspin_lock *lock))
|
||||
{
|
||||
uint8_t oldirql;
|
||||
|
||||
/* I am so going to hell for this. */
|
||||
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
|
||||
panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
|
||||
|
||||
oldirql = KeRaiseIrql(DISPATCH_LEVEL);
|
||||
KeAcquireSpinLockAtDpcLevel(lock);
|
||||
|
||||
return(oldirql);
|
||||
}
|
||||
|
||||
__fastcall void
|
||||
KfReleaseSpinLock(REGARGS2(kspin_lock *lock, uint8_t newirql))
|
||||
{
|
||||
KeReleaseSpinLockFromDpcLevel(lock);
|
||||
KeLowerIrql(newirql);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall uint8_t
|
||||
KeGetCurrentIrql(void)
|
||||
{
|
||||
if (AT_DISPATCH_LEVEL(curthread))
|
||||
return(DISPATCH_LEVEL);
|
||||
return(PASSIVE_LEVEL);
|
||||
}
|
||||
|
||||
__stdcall static uint64_t
|
||||
KeQueryPerformanceCounter(freq)
|
||||
uint64_t *freq;
|
||||
{
|
||||
if (freq != NULL)
|
||||
*freq = hz;
|
||||
|
||||
return((uint64_t)ticks);
|
||||
}
|
||||
|
||||
__fastcall uint8_t
|
||||
KfRaiseIrql(REGARGS1(uint8_t irql))
|
||||
{
|
||||
uint8_t oldirql;
|
||||
|
||||
if (irql < KeGetCurrentIrql())
|
||||
panic("IRQL_NOT_LESS_THAN");
|
||||
|
||||
if (KeGetCurrentIrql() == DISPATCH_LEVEL)
|
||||
return(DISPATCH_LEVEL);
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
oldirql = curthread->td_base_pri;
|
||||
sched_prio(curthread, PI_REALTIME);
|
||||
#if __FreeBSD_version < 600000
|
||||
curthread->td_base_pri = PI_REALTIME;
|
||||
#endif
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
return(oldirql);
|
||||
}
|
||||
|
||||
__fastcall void
|
||||
KfLowerIrql(REGARGS1(uint8_t oldirql))
|
||||
{
|
||||
if (oldirql == DISPATCH_LEVEL)
|
||||
return;
|
||||
|
||||
if (KeGetCurrentIrql() != DISPATCH_LEVEL)
|
||||
panic("IRQL_NOT_GREATER_THAN");
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
#if __FreeBSD_version < 600000
|
||||
curthread->td_base_pri = oldirql;
|
||||
#endif
|
||||
sched_prio(curthread, oldirql);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall
|
||||
static void dummy()
|
||||
{
|
||||
printf ("hal dummy called...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
image_patch_table hal_functbl[] = {
|
||||
IMPORT_FUNC(KeStallExecutionProcessor),
|
||||
IMPORT_FUNC(WRITE_PORT_ULONG),
|
||||
IMPORT_FUNC(WRITE_PORT_USHORT),
|
||||
IMPORT_FUNC(WRITE_PORT_UCHAR),
|
||||
IMPORT_FUNC(WRITE_PORT_BUFFER_ULONG),
|
||||
IMPORT_FUNC(WRITE_PORT_BUFFER_USHORT),
|
||||
IMPORT_FUNC(WRITE_PORT_BUFFER_UCHAR),
|
||||
IMPORT_FUNC(READ_PORT_ULONG),
|
||||
IMPORT_FUNC(READ_PORT_USHORT),
|
||||
IMPORT_FUNC(READ_PORT_UCHAR),
|
||||
IMPORT_FUNC(READ_PORT_BUFFER_ULONG),
|
||||
IMPORT_FUNC(READ_PORT_BUFFER_USHORT),
|
||||
IMPORT_FUNC(READ_PORT_BUFFER_UCHAR),
|
||||
IMPORT_FUNC(KfAcquireSpinLock),
|
||||
IMPORT_FUNC(KfReleaseSpinLock),
|
||||
IMPORT_FUNC(KeGetCurrentIrql),
|
||||
IMPORT_FUNC(KeQueryPerformanceCounter),
|
||||
IMPORT_FUNC(KfLowerIrql),
|
||||
IMPORT_FUNC(KfRaiseIrql),
|
||||
|
||||
/*
|
||||
* 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 },
|
||||
|
||||
/* End of list. */
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,638 @@
|
|||
/*-
|
||||
* Copyright (c) 2003
|
||||
* 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: src/sys/compat/ndis/subr_pe.c,v 1.7.2.3 2005/03/31 04:24:36 wpaul Exp $");
|
||||
|
||||
/*
|
||||
* This file contains routines for relocating and dynamically linking
|
||||
* executable object code files in the Windows(r) PE (Portable Executable)
|
||||
* format. In Windows, anything with a .EXE, .DLL or .SYS extention is
|
||||
* considered an executable, and all such files have some structures in
|
||||
* common. The PE format was apparently based largely on COFF but has
|
||||
* mutated significantly over time. We are mainly concerned with .SYS files,
|
||||
* so this module implements only enough routines to be able to parse the
|
||||
* headers and sections of a .SYS object file and perform the necessary
|
||||
* relocations and jump table patching to allow us to call into it
|
||||
* (and to have it call back to us). Note that while this module
|
||||
* can handle fixups for imported symbols, it knows nothing about
|
||||
* exporting them.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
extern int ndis_strncasecmp(const char *, const char *, size_t);
|
||||
#define strncasecmp(a, b, c) ndis_strncasecmp(a, b, c)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <compat/ndis/pe_var.h>
|
||||
|
||||
static vm_offset_t pe_functbl_match(image_patch_table *, char *);
|
||||
|
||||
/*
|
||||
* Check for an MS-DOS executable header. All Windows binaries
|
||||
* have a small MS-DOS executable prepended to them to print out
|
||||
* the "This program requires Windows" message. Even .SYS files
|
||||
* have this header, in spite of the fact that you're can't actually
|
||||
* run them directly.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_get_dos_header(imgbase, hdr)
|
||||
vm_offset_t imgbase;
|
||||
image_dos_header *hdr;
|
||||
{
|
||||
uint16_t signature;
|
||||
|
||||
if (imgbase == 0 || hdr == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
signature = *(uint16_t *)imgbase;
|
||||
if (signature != IMAGE_DOS_SIGNATURE)
|
||||
return (ENOEXEC);
|
||||
|
||||
bcopy ((char *)imgbase, (char *)hdr, sizeof(image_dos_header));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that this image has a Windows NT PE signature.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_is_nt_image(imgbase)
|
||||
vm_offset_t imgbase;
|
||||
{
|
||||
uint32_t signature;
|
||||
image_dos_header *dos_hdr;
|
||||
|
||||
if (imgbase == 0)
|
||||
return (EINVAL);
|
||||
|
||||
signature = *(uint16_t *)imgbase;
|
||||
if (signature == IMAGE_DOS_SIGNATURE) {
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
signature = *(uint32_t *)(imgbase + dos_hdr->idh_lfanew);
|
||||
if (signature == IMAGE_NT_SIGNATURE)
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(ENOEXEC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a copy of the optional header. This contains the
|
||||
* executable entry point and the directory listing which we
|
||||
* need to find the relocations and imports later.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_get_optional_header(imgbase, hdr)
|
||||
vm_offset_t imgbase;
|
||||
image_optional_header *hdr;
|
||||
{
|
||||
image_dos_header *dos_hdr;
|
||||
image_nt_header *nt_hdr;
|
||||
|
||||
if (imgbase == 0 || hdr == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
if (pe_is_nt_image(imgbase))
|
||||
return (EINVAL);
|
||||
|
||||
dos_hdr = (image_dos_header *)(imgbase);
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
|
||||
bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr,
|
||||
sizeof(image_optional_header));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a copy of the file header. Contains the number of
|
||||
* sections in this image.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_get_file_header(imgbase, hdr)
|
||||
vm_offset_t imgbase;
|
||||
image_file_header *hdr;
|
||||
{
|
||||
image_dos_header *dos_hdr;
|
||||
image_nt_header *nt_hdr;
|
||||
|
||||
if (imgbase == 0 || hdr == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
if (pe_is_nt_image(imgbase))
|
||||
return (EINVAL);
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
|
||||
bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr,
|
||||
sizeof(image_file_header));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the header of the first section in this image (usually
|
||||
* .text).
|
||||
*/
|
||||
|
||||
int
|
||||
pe_get_section_header(imgbase, hdr)
|
||||
vm_offset_t imgbase;
|
||||
image_section_header *hdr;
|
||||
{
|
||||
image_dos_header *dos_hdr;
|
||||
image_nt_header *nt_hdr;
|
||||
image_section_header *sect_hdr;
|
||||
|
||||
if (imgbase == 0 || hdr == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
if (pe_is_nt_image(imgbase))
|
||||
return (EINVAL);
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
|
||||
sizeof(image_nt_header));
|
||||
|
||||
bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of sections in this executable, or 0 on error.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_numsections(imgbase)
|
||||
vm_offset_t imgbase;
|
||||
{
|
||||
image_file_header file_hdr;
|
||||
|
||||
if (pe_get_file_header(imgbase, &file_hdr))
|
||||
return(0);
|
||||
|
||||
return (file_hdr.ifh_numsections);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the base address that this image was linked for.
|
||||
* This helps us calculate relocation addresses later.
|
||||
*/
|
||||
|
||||
vm_offset_t
|
||||
pe_imagebase(imgbase)
|
||||
vm_offset_t imgbase;
|
||||
{
|
||||
image_optional_header optional_hdr;
|
||||
|
||||
if (pe_get_optional_header(imgbase, &optional_hdr))
|
||||
return(0);
|
||||
|
||||
return (optional_hdr.ioh_imagebase);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset of a given directory structure within the
|
||||
* image. Directories reside within sections.
|
||||
*/
|
||||
|
||||
vm_offset_t
|
||||
pe_directory_offset(imgbase, diridx)
|
||||
vm_offset_t imgbase;
|
||||
uint32_t diridx;
|
||||
{
|
||||
image_optional_header opt_hdr;
|
||||
vm_offset_t dir;
|
||||
|
||||
if (pe_get_optional_header(imgbase, &opt_hdr))
|
||||
return(0);
|
||||
|
||||
if (diridx >= opt_hdr.ioh_rva_size_cnt)
|
||||
return(0);
|
||||
|
||||
dir = opt_hdr.ioh_datadir[diridx].idd_vaddr;
|
||||
|
||||
return(pe_translate_addr(imgbase, dir));
|
||||
}
|
||||
|
||||
vm_offset_t
|
||||
pe_translate_addr(imgbase, rva)
|
||||
vm_offset_t imgbase;
|
||||
vm_offset_t rva;
|
||||
{
|
||||
image_optional_header opt_hdr;
|
||||
image_section_header *sect_hdr;
|
||||
image_dos_header *dos_hdr;
|
||||
image_nt_header *nt_hdr;
|
||||
int i = 0, sections, fixedlen;
|
||||
|
||||
if (pe_get_optional_header(imgbase, &opt_hdr))
|
||||
return(0);
|
||||
|
||||
sections = pe_numsections(imgbase);
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
|
||||
sizeof(image_nt_header));
|
||||
|
||||
/*
|
||||
* The test here is to see if the RVA falls somewhere
|
||||
* inside the section, based on the section's start RVA
|
||||
* and its length. However it seems sometimes the
|
||||
* virtual length isn't enough to cover the entire
|
||||
* area of the section. We fudge by taking into account
|
||||
* the section alignment and rounding the section length
|
||||
* up to a page boundary.
|
||||
*/
|
||||
while (i++ < sections) {
|
||||
fixedlen = sect_hdr->ish_misc.ish_vsize;
|
||||
fixedlen += ((opt_hdr.ioh_sectalign - 1) -
|
||||
sect_hdr->ish_misc.ish_vsize) &
|
||||
(opt_hdr.ioh_sectalign - 1);
|
||||
if (sect_hdr->ish_vaddr <= (uint32_t)rva &&
|
||||
(sect_hdr->ish_vaddr + fixedlen) >
|
||||
(uint32_t)rva)
|
||||
break;
|
||||
sect_hdr++;
|
||||
}
|
||||
|
||||
if (i > sections)
|
||||
return(0);
|
||||
|
||||
return((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr +
|
||||
sect_hdr->ish_rawdataaddr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the section header for a particular section. Note that
|
||||
* section names can be anything, but there are some standard
|
||||
* ones (.text, .data, .rdata, .reloc).
|
||||
*/
|
||||
|
||||
int
|
||||
pe_get_section(imgbase, hdr, name)
|
||||
vm_offset_t imgbase;
|
||||
image_section_header *hdr;
|
||||
const char *name;
|
||||
{
|
||||
image_dos_header *dos_hdr;
|
||||
image_nt_header *nt_hdr;
|
||||
image_section_header *sect_hdr;
|
||||
|
||||
int i, sections;
|
||||
|
||||
if (imgbase == 0 || hdr == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
if (pe_is_nt_image(imgbase))
|
||||
return (EINVAL);
|
||||
|
||||
sections = pe_numsections(imgbase);
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
|
||||
sizeof(image_nt_header));
|
||||
|
||||
for (i = 0; i < sections; i++) {
|
||||
if (!strcmp ((char *)§_hdr->ish_name, name)) {
|
||||
bcopy((char *)sect_hdr, (char *)hdr,
|
||||
sizeof(image_section_header));
|
||||
return(0);
|
||||
} else
|
||||
sect_hdr++;
|
||||
}
|
||||
|
||||
return (ENOEXEC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the base relocations to this image. The relocation table
|
||||
* resides within the .reloc section. Relocations are specified in
|
||||
* blocks which refer to a particular page. We apply the relocations
|
||||
* one page block at a time.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_relocate(imgbase)
|
||||
vm_offset_t imgbase;
|
||||
{
|
||||
image_section_header sect;
|
||||
image_base_reloc *relhdr;
|
||||
uint16_t rel, *sloc;
|
||||
vm_offset_t base;
|
||||
vm_size_t delta;
|
||||
uint32_t *lloc;
|
||||
uint64_t *qloc;
|
||||
int i, count;
|
||||
vm_offset_t txt;
|
||||
|
||||
base = pe_imagebase(imgbase);
|
||||
pe_get_section(imgbase, §, ".text");
|
||||
txt = pe_translate_addr(imgbase, sect.ish_vaddr);
|
||||
delta = (uint32_t)(txt) - base - sect.ish_vaddr;
|
||||
|
||||
pe_get_section(imgbase, §, ".reloc");
|
||||
|
||||
relhdr = (image_base_reloc *)(imgbase + sect.ish_rawdataaddr);
|
||||
|
||||
do {
|
||||
count = (relhdr->ibr_blocksize -
|
||||
(sizeof(uint32_t) * 2)) / sizeof(uint16_t);
|
||||
for (i = 0; i < count; i++) {
|
||||
rel = relhdr->ibr_rel[i];
|
||||
switch (IMR_RELTYPE(rel)) {
|
||||
case IMAGE_REL_BASED_ABSOLUTE:
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGHLOW:
|
||||
lloc = (uint32_t *)pe_translate_addr(imgbase,
|
||||
relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
|
||||
*lloc = pe_translate_addr(imgbase,
|
||||
(*lloc - base));
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGH:
|
||||
sloc = (uint16_t *)pe_translate_addr(imgbase,
|
||||
relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
|
||||
*sloc += (delta & 0xFFFF0000) >> 16;
|
||||
break;
|
||||
case IMAGE_REL_BASED_LOW:
|
||||
sloc = (uint16_t *)pe_translate_addr(imgbase,
|
||||
relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
|
||||
*sloc += (delta & 0xFFFF);
|
||||
break;
|
||||
case IMAGE_REL_BASED_DIR64:
|
||||
qloc = (uint64_t *)pe_translate_addr(imgbase,
|
||||
relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
|
||||
*qloc = pe_translate_addr(imgbase,
|
||||
(*qloc - base));
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("[%d]reloc type: %d\n",i,
|
||||
IMR_RELTYPE(rel));
|
||||
break;
|
||||
}
|
||||
}
|
||||
relhdr = (image_base_reloc *)((vm_offset_t)relhdr +
|
||||
relhdr->ibr_blocksize);
|
||||
} while (relhdr->ibr_blocksize);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the import descriptor for a particular module. An image
|
||||
* may be linked against several modules, typically HAL.dll, ntoskrnl.exe
|
||||
* and NDIS.SYS. For each module, there is a list of imported function
|
||||
* names and their addresses.
|
||||
*
|
||||
* Note: module names are case insensitive!
|
||||
*/
|
||||
|
||||
int
|
||||
pe_get_import_descriptor(imgbase, desc, module)
|
||||
vm_offset_t imgbase;
|
||||
image_import_descriptor *desc;
|
||||
char *module;
|
||||
{
|
||||
vm_offset_t offset;
|
||||
image_import_descriptor *imp_desc;
|
||||
char *modname;
|
||||
|
||||
if (imgbase == 0 || module == NULL || desc == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_IMPORT);
|
||||
if (offset == 0)
|
||||
return (ENOENT);
|
||||
|
||||
imp_desc = (void *)offset;
|
||||
|
||||
while (imp_desc->iid_nameaddr) {
|
||||
modname = (char *)pe_translate_addr(imgbase,
|
||||
imp_desc->iid_nameaddr);
|
||||
if (!strncasecmp(module, modname, strlen(module))) {
|
||||
bcopy((char *)imp_desc, (char *)desc,
|
||||
sizeof(image_import_descriptor));
|
||||
return(0);
|
||||
}
|
||||
imp_desc++;
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
int
|
||||
pe_get_messagetable(imgbase, md)
|
||||
vm_offset_t imgbase;
|
||||
message_resource_data **md;
|
||||
{
|
||||
image_resource_directory *rdir, *rtype;
|
||||
image_resource_directory_entry *dent, *dent2;
|
||||
image_resource_data_entry *rent;
|
||||
vm_offset_t offset;
|
||||
int i;
|
||||
|
||||
if (imgbase == 0)
|
||||
return(EINVAL);
|
||||
|
||||
offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_RESOURCE);
|
||||
if (offset == 0)
|
||||
return (ENOENT);
|
||||
|
||||
rdir = (image_resource_directory *)offset;
|
||||
|
||||
dent = (image_resource_directory_entry *)(offset +
|
||||
sizeof(image_resource_directory));
|
||||
|
||||
for (i = 0; i < rdir->ird_id_entries; i++){
|
||||
if (dent->irde_name != RT_MESSAGETABLE) {
|
||||
dent++;
|
||||
continue;
|
||||
}
|
||||
dent2 = dent;
|
||||
while (dent2->irde_dataoff & RESOURCE_DIR_FLAG) {
|
||||
rtype = (image_resource_directory *)(offset +
|
||||
(dent2->irde_dataoff & ~RESOURCE_DIR_FLAG));
|
||||
dent2 = (image_resource_directory_entry *)
|
||||
((uintptr_t)rtype +
|
||||
sizeof(image_resource_directory));
|
||||
}
|
||||
rent = (image_resource_data_entry *)(offset +
|
||||
dent2->irde_dataoff);
|
||||
*md = (message_resource_data *)pe_translate_addr(imgbase,
|
||||
rent->irde_offset);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(ENOENT);
|
||||
}
|
||||
|
||||
int
|
||||
pe_get_message(imgbase, id, str, len, flags)
|
||||
vm_offset_t imgbase;
|
||||
uint32_t id;
|
||||
char **str;
|
||||
int *len;
|
||||
uint16_t *flags;
|
||||
{
|
||||
message_resource_data *md = NULL;
|
||||
message_resource_block *mb;
|
||||
message_resource_entry *me;
|
||||
uint32_t i;
|
||||
|
||||
pe_get_messagetable(imgbase, &md);
|
||||
|
||||
if (md == NULL)
|
||||
return(ENOENT);
|
||||
|
||||
mb = (message_resource_block *)((uintptr_t)md +
|
||||
sizeof(message_resource_data));
|
||||
|
||||
for (i = 0; i < md->mrd_numblocks; i++) {
|
||||
if (id >= mb->mrb_lowid && id <= mb->mrb_highid) {
|
||||
me = (message_resource_entry *)((uintptr_t)md +
|
||||
mb->mrb_entryoff);
|
||||
for (i = id - mb->mrb_lowid; i > 0; i--)
|
||||
me = (message_resource_entry *)((uintptr_t)me +
|
||||
me->mre_len);
|
||||
*str = me->mre_text;
|
||||
*len = me->mre_len;
|
||||
*flags = me->mre_flags;
|
||||
return(0);
|
||||
}
|
||||
mb++;
|
||||
}
|
||||
|
||||
return(ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the function that matches a particular name. This doesn't
|
||||
* need to be particularly speedy since it's only run when loading
|
||||
* a module for the first time.
|
||||
*/
|
||||
|
||||
static vm_offset_t
|
||||
pe_functbl_match(functbl, name)
|
||||
image_patch_table *functbl;
|
||||
char *name;
|
||||
{
|
||||
image_patch_table *p;
|
||||
|
||||
if (functbl == NULL || name == NULL)
|
||||
return(0);
|
||||
|
||||
p = functbl;
|
||||
|
||||
while (p->ipt_name != NULL) {
|
||||
if (!strcmp(p->ipt_name, name))
|
||||
return((vm_offset_t)p->ipt_wrap);
|
||||
p++;
|
||||
}
|
||||
printf ("no match for %s\n", name);
|
||||
|
||||
/*
|
||||
* Return the wrapper pointer for this routine.
|
||||
* For x86, this is the same as the funcptr.
|
||||
* For amd64, this points to a wrapper routine
|
||||
* that does calling convention translation and
|
||||
* then invokes the underlying routine.
|
||||
*/
|
||||
return((vm_offset_t)p->ipt_wrap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch the imported function addresses for a given module.
|
||||
* The caller must specify the module name and provide a table
|
||||
* of function pointers that will be patched into the jump table.
|
||||
* Note that there are actually two copies of the jump table: one
|
||||
* copy is left alone. In a .SYS file, the jump tables are usually
|
||||
* merged into the INIT segment.
|
||||
*/
|
||||
|
||||
int
|
||||
pe_patch_imports(imgbase, module, functbl)
|
||||
vm_offset_t imgbase;
|
||||
char *module;
|
||||
image_patch_table *functbl;
|
||||
{
|
||||
image_import_descriptor imp_desc;
|
||||
char *fname;
|
||||
vm_offset_t *nptr, *fptr;
|
||||
vm_offset_t func;
|
||||
|
||||
if (imgbase == 0 || module == NULL || functbl == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
if (pe_get_import_descriptor(imgbase, &imp_desc, module))
|
||||
return(ENOEXEC);
|
||||
|
||||
nptr = (vm_offset_t *)pe_translate_addr(imgbase,
|
||||
imp_desc.iid_import_name_table_addr);
|
||||
fptr = (vm_offset_t *)pe_translate_addr(imgbase,
|
||||
imp_desc.iid_import_address_table_addr);
|
||||
|
||||
while (nptr != NULL && pe_translate_addr(imgbase, *nptr)) {
|
||||
fname = (char *)pe_translate_addr(imgbase, (*nptr) + 2);
|
||||
func = pe_functbl_match(functbl, fname);
|
||||
if (func)
|
||||
*fptr = func;
|
||||
#ifdef notdef
|
||||
if (*fptr == 0)
|
||||
return(ENOENT);
|
||||
#endif
|
||||
nptr++;
|
||||
fptr++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*-
|
||||
* 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: src/sys/compat/ndis/subr_usbd.c,v 1.1.2.1 2005/03/31 04:24:36 wpaul Exp $");
|
||||
|
||||
#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;
|
||||
|
||||
__stdcall static uint32_t usbd_iodispatch(device_object *, irp *);
|
||||
|
||||
__stdcall static void USBD_GetUSBDIVersion(usbd_version_info *);
|
||||
__stdcall 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++;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
__stdcall static uint32_t
|
||||
usbd_iodispatch(dobj, ip)
|
||||
device_object *dobj;
|
||||
irp *ip;
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
__stdcall 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;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
dummy(void)
|
||||
{
|
||||
printf("USBD dummy called\n");
|
||||
return;
|
||||
}
|
||||
|
||||
image_patch_table usbd_functbl[] = {
|
||||
IMPORT_FUNC(USBD_GetUSBDIVersion),
|
||||
#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 },
|
||||
|
||||
/* End of list. */
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*-
|
||||
* Copyright (c) 2003
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/compat/ndis/usbd_var.h,v 1.1.2.1 2005/03/31 04:24:36 wpaul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _USBD_VAR_H_
|
||||
#define _USBD_VAR_H_
|
||||
|
||||
#define USBDI_VERSION 0x00000500
|
||||
#define USB_VER_1_1 0x00000110
|
||||
#define USB_VER_2_0 0x00000200
|
||||
|
||||
struct usbd_version_info {
|
||||
uint32_t uvi_usbdi_vers;
|
||||
uint32_t uvi_supported_vers;
|
||||
};
|
||||
|
||||
typedef struct usbd_version_info usbd_version_info;
|
||||
|
||||
extern image_patch_table usbd_functbl[];
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int usbd_libinit(void);
|
||||
extern int usbd_libfini(void);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _USBD_VAR_H_ */
|
|
@ -0,0 +1,177 @@
|
|||
/*-
|
||||
* 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.
|
||||
*
|
||||
* The x86_64 callback routines were written and graciously submitted
|
||||
* by Ville-Pertti Keinonen <will@exomi.com>.
|
||||
*
|
||||
* $FreeBSD: src/sys/compat/ndis/winx64_wrap.S,v 1.3.2.1 2005/02/18 16:30:09 wpaul Exp $
|
||||
*/
|
||||
|
||||
#include <machine/asmacros.h>
|
||||
|
||||
/*
|
||||
* Wrapper for handling up to 16 arguments. We can't really
|
||||
* know how many arguments the caller will pass us. I'm taking an
|
||||
* educated guess that we'll never get over 16. Handling too
|
||||
* few arguments is bad. Handling too many is inefficient, but
|
||||
* not fatal. If someone can think of a way to handle an arbitrary
|
||||
* number of arguments with more elegant code, freel free to let
|
||||
* me know.
|
||||
*
|
||||
* Standard amd64 calling conventions specify the following registers
|
||||
* to be used for passing the first 6 arguments:
|
||||
*
|
||||
* %rdi, %rsi, %rdx, %rcx, %r8, %r9
|
||||
*
|
||||
* Further arguments are passed on the stack (the 7th argument is
|
||||
* located immediately after the return address).
|
||||
*
|
||||
* Windows x86_64 calling conventions only pass the first 4
|
||||
* arguments in registers:
|
||||
*
|
||||
* %rcx, %rdx, %r8, %r9
|
||||
*
|
||||
* Even when arguments are passed in registers, the stack must have
|
||||
* space reserved for those arguments. Thus the 5th argument (the
|
||||
* first non-register argument) is placed 32 bytes after the return
|
||||
* address. Additionally, %rdi and %rsi must be preserved. (These
|
||||
* two registers are not scratch registers in the standard convention.)
|
||||
*
|
||||
* Note that in this template, we load a contrived 64 bit address into
|
||||
* %r11 to represent our jump address. This is to guarantee that the
|
||||
* assembler leaves enough room to patch in an absolute 64-bit address
|
||||
* later. The idea behind this code is that we want to avoid having to
|
||||
* manually create all the wrapper functions at compile time with
|
||||
* a bunch of macros. This is doable, but a) messy and b) requires
|
||||
* us to maintain two separate tables (one for the UNIX function
|
||||
* pointers and another with the wrappers). This means I'd have to
|
||||
* update two different tables each time I added a function.
|
||||
*
|
||||
* To avoid this, we create the wrappers at runtime instead. The
|
||||
* image patch tables now contain two pointers: one two the normal
|
||||
* routine, and a blank one for the wrapper. To construct a wrapper,
|
||||
* we allocate some memory and copy the template function into it,
|
||||
* then patch the function pointer for the routine we want to wrap
|
||||
* into the newly created wrapper. The subr_pe module can then
|
||||
* simply patch the wrapper routine into the jump table into the
|
||||
* windows image. As a bonus, the wrapper pointer not only serves
|
||||
* as the wrapper entry point address, it's also a data pointer
|
||||
* that we can pass to free() later when we unload the module.
|
||||
*/
|
||||
|
||||
.globl x86_64_wrap_call
|
||||
.globl x86_64_wrap_end
|
||||
|
||||
ENTRY(x86_64_wrap)
|
||||
subq $96,%rsp # allocate space on stack
|
||||
mov %rsi,96-8(%rsp) # save %rsi
|
||||
mov %rdi,96-16(%rsp)# save %rdi
|
||||
mov %rcx,%r10 # temporarily save %rcx in scratch
|
||||
mov %rsp,%rsi
|
||||
add $96+56,%rsi # source == old stack top (stack+56)
|
||||
mov %rsp,%rdi # destination == new stack top
|
||||
mov $10,%rcx # count == 10 quadwords
|
||||
rep
|
||||
movsq # copy old stack contents to new location
|
||||
mov %r10,%rdi # set up arg0 (%rcx -> %rdi)
|
||||
mov %rdx,%rsi # set up arg1 (%rdx -> %rsi)
|
||||
mov %r8,%rdx # set up arg2 (%r8 -> %rdx)
|
||||
mov %r9,%rcx # set up arg3 (%r9 -> %rcx)
|
||||
mov 96+40(%rsp),%r8 # set up arg4 (stack+40 -> %r8)
|
||||
mov 96+48(%rsp),%r9 # set up arg5 (stack+48 -> %r9)
|
||||
xor %rax,%rax # clear return value
|
||||
x86_64_wrap_call:
|
||||
mov $0xFF00FF00FF00FF00,%r11
|
||||
callq *%r11 # call routine
|
||||
mov 96-16(%rsp),%rdi# restore %rdi
|
||||
mov 96-8(%rsp),%rsi # restore %rsi
|
||||
addq $96,%rsp # delete space on stack
|
||||
ret
|
||||
x86_64_wrap_end:
|
||||
|
||||
/*
|
||||
* Functions for invoking x86_64 callbacks. In each case, the first
|
||||
* argument is a pointer to the function.
|
||||
*/
|
||||
|
||||
ENTRY(x86_64_call1)
|
||||
subq $8,%rsp
|
||||
mov %rsi,%rcx
|
||||
call *%rdi
|
||||
addq $8,%rsp
|
||||
ret
|
||||
|
||||
ENTRY(x86_64_call2)
|
||||
subq $24,%rsp
|
||||
mov %rsi,%rcx
|
||||
/* %rdx is already correct */
|
||||
call *%rdi
|
||||
addq $24,%rsp
|
||||
ret
|
||||
|
||||
ENTRY(x86_64_call3)
|
||||
subq $24,%rsp
|
||||
mov %rcx,%r8
|
||||
mov %rsi,%rcx
|
||||
call *%rdi
|
||||
addq $24,%rsp
|
||||
ret
|
||||
|
||||
ENTRY(x86_64_call4)
|
||||
subq $40,%rsp
|
||||
mov %r8,%r9
|
||||
mov %rcx,%r8
|
||||
mov %rsi,%rcx
|
||||
call *%rdi
|
||||
addq $40,%rsp
|
||||
ret
|
||||
|
||||
ENTRY(x86_64_call5)
|
||||
subq $40,%rsp
|
||||
mov %r9,32(%rsp)
|
||||
mov %r8,%r9
|
||||
mov %rcx,%r8
|
||||
mov %rsi,%rcx
|
||||
call *%rdi
|
||||
addq $40,%rsp
|
||||
ret
|
||||
|
||||
ENTRY(x86_64_call6)
|
||||
subq $56,%rsp
|
||||
mov 56+8(%rsp),%rax
|
||||
mov %r9,32(%rsp)
|
||||
mov %rax,40(%rsp)
|
||||
mov %r8,%r9
|
||||
mov %rcx,%r8
|
||||
mov %rsi,%rcx
|
||||
call *%rdi
|
||||
addq $56,%rsp
|
||||
ret
|
Loading…
Reference in New Issue