Added the original FreeBSD RELENG_54 files in sys/compat/ndis.

This commit is contained in:
rittera 2006-03-30 22:56:50 +00:00
parent 58cc83950f
commit 3d0ceda304
15 changed files with 13543 additions and 0 deletions

47
sys/compat/ndis/cfg_var.h Normal file
View File

@ -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_ */

58
sys/compat/ndis/hal_var.h Normal file
View File

@ -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_ */

1764
sys/compat/ndis/kern_ndis.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

1609
sys/compat/ndis/ndis_var.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

573
sys/compat/ndis/pe_var.h Normal file
View File

@ -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_ */

View File

@ -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_ */

412
sys/compat/ndis/subr_hal.c Normal file
View File

@ -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 }
};

3305
sys/compat/ndis/subr_ndis.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

638
sys/compat/ndis/subr_pe.c Normal file
View File

@ -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 *)&sect_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, &sect, ".text");
txt = pe_translate_addr(imgbase, sect.ish_vaddr);
delta = (uint32_t)(txt) - base - sect.ish_vaddr;
pe_get_section(imgbase, &sect, ".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);
}

156
sys/compat/ndis/subr_usbd.c Normal file
View File

@ -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 }
};

View File

@ -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_ */

View File

@ -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