- Add pe_get_message() and pe_get_messagetable() for processing
the RT_MESSAGETABLE resources that some driver binaries have. This allows us to print error messages in ndis_syslog(). - Correct the implementation of InterlockedIncrement() and InterlockedDecrement() -- they return uint32_t, not void. - Correct the declarations of the 64-bit arithmetic shift routines in subr_ntoskrnl.c (_allshr, allshl, etc...). These do not follow the _stdcall convention: instead, they appear to be __attribute__((regparm(3)). - Change the implementation of KeInitializeSpinLock(). There is no complementary KeFreeSpinLock() function, so creating a new mutex on each call to KeInitializeSpinLock() leaks resources when a driver is unloaded. For now, KeInitializeSpinLock() returns a handle to the ntoskrnl interlock mutex. - Use a driver's MiniportDisableInterrupt() and MiniportEnableInterrupt() routines if they exist. I'm not sure if I'm doing this right yet, but at the very least this shouldn't break any currently working drivers, and it makes the Intel PRO/1000 driver work. - In ndis_register_intr(), save some state that might be needed later, and save a pointer to the driver's interrupt structure in the ndis_miniport_block. - Save a pointer to the driver image for use by ndis_syslog() when it calls pe_get_message().
This commit is contained in:
parent
f25a19f66f
commit
09bebfadee
@ -1179,6 +1179,7 @@ ndis_load_driver(img, arg)
|
||||
|
||||
block->nmb_ifp = &sc->arpcom.ac_if;
|
||||
block->nmb_dev = sc->ndis_dev;
|
||||
block->nmb_img = img;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -1280,6 +1280,7 @@ struct ndis_miniport_block {
|
||||
ndis_status nmb_getstat;
|
||||
ndis_status nmb_setstat;
|
||||
struct nte_head nmb_timerlist;
|
||||
vm_offset_t nmb_img;
|
||||
};
|
||||
|
||||
typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *,
|
||||
|
@ -230,6 +230,29 @@ typedef struct image_nt_header image_nt_header;
|
||||
#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.
|
||||
*/
|
||||
@ -303,6 +326,80 @@ typedef struct image_base_reloc image_base_reloc;
|
||||
#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;
|
||||
@ -325,6 +422,10 @@ 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 *);
|
||||
#ifdef _KERNEL
|
||||
extern int pe_get_messagetable(vm_offset_t, message_resource_data **);
|
||||
extern int pe_get_message(vm_offset_t, uint32_t, char **, int *);
|
||||
#endif
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PE_VAR_H_ */
|
||||
|
@ -796,10 +796,13 @@ ndis_syslog(ndis_handle adapter, ndis_error_code code,
|
||||
ndis_miniport_block *block;
|
||||
va_list ap;
|
||||
int i;
|
||||
char *str = NULL;
|
||||
|
||||
block = (ndis_miniport_block *)adapter;
|
||||
|
||||
device_printf (block->nmb_dev, "NDIS ERROR: %x\n", code);
|
||||
pe_get_message(block->nmb_img, code, &str, &i);
|
||||
device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
|
||||
str == NULL ? "unknown error" : str);
|
||||
device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
|
||||
|
||||
va_start(ap, numerrors);
|
||||
@ -1894,7 +1897,14 @@ ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
|
||||
uint8_t shared;
|
||||
ndis_interrupt_mode imode;
|
||||
{
|
||||
ndis_miniport_block *block;
|
||||
|
||||
block = adapter;
|
||||
|
||||
intr->ni_block = adapter;
|
||||
intr->ni_isrreq = reqisr;
|
||||
intr->ni_shared = shared;
|
||||
block->nmb_interrupt = intr;
|
||||
return(NDIS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <compat/ndis/ntoskrnl_var.h>
|
||||
|
||||
#define __stdcall __attribute__((__stdcall__))
|
||||
#define __regparm __attribute__((regparm(3)))
|
||||
|
||||
#define FUNC void(*)(void)
|
||||
|
||||
__stdcall static uint32_t ntoskrnl_unicode_equal(ndis_unicode_string *,
|
||||
@ -82,13 +84,13 @@ __stdcall static uint8_t ntoskrnl_readreg_uchar(uint8_t *);
|
||||
__stdcall static int64_t _allmul(int64_t, int64_t);
|
||||
__stdcall static int64_t _alldiv(int64_t, int64_t);
|
||||
__stdcall static int64_t _allrem(int64_t, int64_t);
|
||||
__stdcall static int64_t _allshr(int64_t, int);
|
||||
__stdcall static int64_t _allshl(int64_t, int);
|
||||
__regparm static int64_t _allshr(int64_t, uint8_t);
|
||||
__regparm static int64_t _allshl(int64_t, uint8_t);
|
||||
__stdcall static uint64_t _aullmul(uint64_t, uint64_t);
|
||||
__stdcall static uint64_t _aulldiv(uint64_t, uint64_t);
|
||||
__stdcall static uint64_t _aullrem(uint64_t, uint64_t);
|
||||
__stdcall static uint64_t _aullshr(uint64_t, int);
|
||||
__stdcall static uint64_t _aullshl(uint64_t, int);
|
||||
__regparm static uint64_t _aullshr(uint64_t, uint8_t);
|
||||
__regparm static uint64_t _aullshl(uint64_t, uint8_t);
|
||||
__stdcall static void *ntoskrnl_allocfunc(uint32_t, size_t, uint32_t);
|
||||
__stdcall static void ntoskrnl_freefunc(void *);
|
||||
__stdcall static void ntoskrnl_init_lookaside(paged_lookaside_list *,
|
||||
@ -108,11 +110,13 @@ __stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_entry *,
|
||||
kspin_lock * */void);
|
||||
__stdcall static void ntoskrnl_lock_dpc(/*kspin_lock * */ void);
|
||||
__stdcall static void ntoskrnl_unlock_dpc(/*kspin_lock * */ void);
|
||||
__stdcall static void ntoskrnl_interlock_inc(/*volatile uint32_t * */ void);
|
||||
__stdcall static void ntoskrnl_interlock_dec(/*volatile uint32_t * */ void);
|
||||
__stdcall static uint32_t
|
||||
ntoskrnl_interlock_inc(/*volatile uint32_t * */ void);
|
||||
__stdcall static uint32_t
|
||||
ntoskrnl_interlock_dec(/*volatile uint32_t * */ void);
|
||||
__stdcall static void ntoskrnl_freemdl(ndis_buffer *);
|
||||
__stdcall static void *ntoskrnl_mmaplockedpages(ndis_buffer *, uint8_t);
|
||||
__stdcall static void ntoskrnl_create_lock(kspin_lock *);
|
||||
__stdcall static void ntoskrnl_init_lock(kspin_lock *);
|
||||
__stdcall static void dummy(void);
|
||||
__stdcall static size_t ntoskrnl_memcmp(const void *, const void *, size_t);
|
||||
|
||||
@ -121,7 +125,7 @@ static struct mtx ntoskrnl_interlock;
|
||||
int
|
||||
ntoskrnl_libinit()
|
||||
{
|
||||
mtx_init(&ntoskrnl_interlock, "ntoskrnllock", MTX_NETWORK_LOCK,
|
||||
mtx_init(&ntoskrnl_interlock, "ntoskrnllock", "ntoskrnl interlock",
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
|
||||
return(0);
|
||||
@ -333,34 +337,34 @@ _aullrem(a, b)
|
||||
return (a % b);
|
||||
}
|
||||
|
||||
__stdcall static int64_t
|
||||
__regparm static int64_t
|
||||
_allshl(a, b)
|
||||
int64_t a;
|
||||
int b;
|
||||
uint8_t b;
|
||||
{
|
||||
return (a << b);
|
||||
}
|
||||
|
||||
__stdcall static uint64_t
|
||||
__regparm static uint64_t
|
||||
_aullshl(a, b)
|
||||
uint64_t a;
|
||||
int b;
|
||||
uint8_t b;
|
||||
{
|
||||
return (a << b);
|
||||
}
|
||||
|
||||
__stdcall static int64_t
|
||||
__regparm static int64_t
|
||||
_allshr(a, b)
|
||||
int64_t a;
|
||||
int b;
|
||||
uint8_t b;
|
||||
{
|
||||
return (a >> b);
|
||||
}
|
||||
|
||||
__stdcall static uint64_t
|
||||
__regparm static uint64_t
|
||||
_aullshr(a, b)
|
||||
uint64_t a;
|
||||
int b;
|
||||
uint8_t b;
|
||||
{
|
||||
return (a >> b);
|
||||
}
|
||||
@ -567,7 +571,7 @@ ntoskrnl_unlock_dpc(/*lock*/ void)
|
||||
return;
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
__stdcall static uint32_t
|
||||
ntoskrnl_interlock_inc(/*addend*/ void)
|
||||
{
|
||||
volatile uint32_t *addend;
|
||||
@ -578,10 +582,10 @@ ntoskrnl_interlock_inc(/*addend*/ void)
|
||||
(*addend)++;
|
||||
mtx_unlock(&ntoskrnl_interlock);
|
||||
|
||||
return;
|
||||
return(*addend);
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
__stdcall static uint32_t
|
||||
ntoskrnl_interlock_dec(/*addend*/ void)
|
||||
{
|
||||
volatile uint32_t *addend;
|
||||
@ -592,7 +596,7 @@ ntoskrnl_interlock_dec(/*addend*/ void)
|
||||
(*addend)--;
|
||||
mtx_unlock(&ntoskrnl_interlock);
|
||||
|
||||
return;
|
||||
return(*addend);
|
||||
}
|
||||
|
||||
__stdcall static void
|
||||
@ -623,19 +627,19 @@ ntoskrnl_mmaplockedpages(buf, accessmode)
|
||||
return(MDL_VA(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* The KeInitializeSpinLock(), KefAcquireSpinLockAtDpcLevel()
|
||||
* and KefReleaseSpinLockFromDpcLevel() appear to be analagous
|
||||
* to splnet()/splx() in their use. We can't create a new mutex
|
||||
* lock here because there is no complimentary KeFreeSpinLock()
|
||||
* function. For now, what we do is initialize the lock with
|
||||
* a pointer to the ntoskrnl interlock mutex.
|
||||
*/
|
||||
__stdcall static void
|
||||
ntoskrnl_create_lock(lock)
|
||||
ntoskrnl_init_lock(lock)
|
||||
kspin_lock *lock;
|
||||
{
|
||||
struct mtx *mtx;
|
||||
|
||||
mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
if (mtx == NULL)
|
||||
return;
|
||||
mtx_init(mtx, "ntoslock", "ntoskrnl spinlock",
|
||||
MTX_DEF | MTX_RECURSE | MTX_DUPOK);
|
||||
|
||||
*lock = (kspin_lock)mtx;
|
||||
*lock = (kspin_lock)&ntoskrnl_interlock;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -715,7 +719,7 @@ image_patch_table ntoskrnl_functbl[] = {
|
||||
{ "InterlockedDecrement", (FUNC)ntoskrnl_interlock_dec },
|
||||
{ "IoFreeMdl", (FUNC)ntoskrnl_freemdl },
|
||||
{ "MmMapLockedPages", (FUNC)ntoskrnl_mmaplockedpages },
|
||||
{ "KeInitializeSpinLock", (FUNC)ntoskrnl_create_lock },
|
||||
{ "KeInitializeSpinLock", (FUNC)ntoskrnl_init_lock },
|
||||
|
||||
/*
|
||||
* This last entry is a catch-all for any function we haven't
|
||||
|
@ -61,6 +61,15 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <compat/ndis/pe_var.h>
|
||||
#ifdef _KERNEL
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <compat/ndis/resource_var.h>
|
||||
#include <compat/ndis/ntoskrnl_var.h>
|
||||
#include <compat/ndis/ndis_var.h>
|
||||
#endif
|
||||
|
||||
static u_int32_t pe_functbl_match(image_patch_table *, char *);
|
||||
|
||||
@ -456,6 +465,98 @@ pe_get_import_descriptor(imgbase, desc, module)
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
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)
|
||||
vm_offset_t imgbase;
|
||||
uint32_t id;
|
||||
char **str;
|
||||
int *len;
|
||||
{
|
||||
message_resource_data *md = NULL;
|
||||
message_resource_block *mb;
|
||||
message_resource_entry *me;
|
||||
int i;
|
||||
char m[1024], *msg;
|
||||
|
||||
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);
|
||||
if (me->mre_flags == MESSAGE_RESOURCE_UNICODE) {
|
||||
msg = m;
|
||||
ndis_unicode_to_ascii((uint16_t *)me->mre_text,
|
||||
me->mre_len, &msg);
|
||||
*str = m;
|
||||
} else
|
||||
*str = me->mre_text;
|
||||
*len = me->mre_len;
|
||||
return(0);
|
||||
}
|
||||
mb++;
|
||||
}
|
||||
|
||||
return(ENOENT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find the function that matches a particular name. This doesn't
|
||||
* need to be particularly speedy since it's only run when loading
|
||||
|
@ -597,11 +597,12 @@ ndis_attach(dev)
|
||||
fail:
|
||||
if (error)
|
||||
ndis_detach(dev);
|
||||
|
||||
/* We're done talking to the NIC for now; halt it. */
|
||||
ifp->if_flags |= IFF_UP;
|
||||
ndis_halt_nic(sc);
|
||||
ifp->if_flags &= ~IFF_UP;
|
||||
else {
|
||||
/* We're done talking to the NIC for now; halt it. */
|
||||
ifp->if_flags |= IFF_UP;
|
||||
ndis_halt_nic(sc);
|
||||
ifp->if_flags &= ~IFF_UP;
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
||||
@ -841,6 +842,9 @@ ndis_intrtask(arg, pending)
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
ndis_intrhand(sc);
|
||||
mtx_lock(&sc->ndis_intrmtx);
|
||||
ndis_enable_intr(sc);
|
||||
mtx_unlock(&sc->ndis_intrmtx);
|
||||
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
ndis_start(ifp);
|
||||
@ -864,7 +868,12 @@ ndis_intr(arg)
|
||||
return;
|
||||
|
||||
mtx_lock(&sc->ndis_intrmtx);
|
||||
ndis_isr(sc, &is_our_intr, &call_isr);
|
||||
if (sc->ndis_block.nmb_interrupt->ni_isrreq == TRUE)
|
||||
ndis_isr(sc, &is_our_intr, &call_isr);
|
||||
else {
|
||||
ndis_disable_intr(sc);
|
||||
call_isr = 1;
|
||||
}
|
||||
mtx_unlock(&sc->ndis_intrmtx);
|
||||
|
||||
if (is_our_intr || call_isr)
|
||||
@ -1098,12 +1107,22 @@ ndis_init(xsc)
|
||||
sc->ndis_txpending = sc->ndis_maxpkts;
|
||||
sc->ndis_link = 0;
|
||||
|
||||
ndis_enable_intr(sc);
|
||||
|
||||
if (sc->ndis_80211)
|
||||
ndis_setstate_80211(sc);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
|
||||
/*
|
||||
* Some drivers don't set this value. The NDIS spec says
|
||||
* the default checkforhang timeout is approximately 2
|
||||
* seconds.
|
||||
*/
|
||||
if (sc->ndis_block.nmb_checkforhangsecs == 0)
|
||||
sc->ndis_block.nmb_checkforhangsecs = 2;
|
||||
|
||||
if (sc->ndis_chars.nmc_checkhang_func != NULL)
|
||||
sc->ndis_stat_ch = timeout(ndis_tick, sc,
|
||||
hz * sc->ndis_block.nmb_checkforhangsecs);
|
||||
|
Loading…
Reference in New Issue
Block a user