HardenedBSD/sys/compat/ndis/ntoskrnl_var.h

527 lines
14 KiB
C

/*-
* 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$
*/
#ifndef _NTOSKRNL_VAR_H_
#define _NTOSKRNL_VAR_H_
/* Note: assumes x86 page size of 4K. */
#define PAGE_SHIFT 12
#define SPAN_PAGES(ptr, len) \
((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE -1)) + \
(len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
#define PAGE_ALIGN(ptr) \
((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
#define BYTE_OFFSET(ptr) \
((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
#define MDL_INIT(b, baseva, len) \
(b)->nb_next = NULL; \
(b)->nb_size = (uint16_t)(sizeof(struct ndis_buffer) + \
(sizeof(uint32_t) * SPAN_PAGES((baseva), (len)))); \
(b)->nb_flags = 0; \
(b)->nb_startva = (void *)PAGE_ALIGN((baseva)); \
(b)->nb_byteoffset = BYTE_OFFSET((baseva)); \
(b)->nb_bytecount = (uint32_t)(len);
#define MDL_VA(b) \
((void *)((char *)((b)->nb_startva) + (b)->nb_byteoffset))
#define WDM_MAJOR 1
#define WDM_MINOR_WIN98 0x00
#define WDM_MINOR_WINME 0x05
#define WDM_MINOR_WIN2000 0x10
#define WDM_MINOR_WINXP 0x20
#define WDM_MINOR_WIN2003 0x30
/*-
* The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
* According to the Windows DDK header files, KSPIN_LOCK is defined like this:
* typedef ULONG_PTR KSPIN_LOCK;
*
* From basetsd.h (SDK, Feb. 2003):
* typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
* typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
* typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
*
* The keyword __int3264 specifies an integral type that has the following
* properties:
* + It is 32-bit on 32-bit platforms
* + It is 64-bit on 64-bit platforms
* + It is 32-bit on the wire for backward compatibility.
* It gets truncated on the sending side and extended appropriately
* (signed or unsigned) on the receiving side.
*
* Thus register_t seems the proper mapping onto FreeBSD for spin locks.
*/
typedef register_t kspin_lock;
struct slist_entry {
struct slist_entry *sl_next;
};
typedef struct slist_entry slist_entry;
union slist_header {
uint64_t slh_align;
struct {
struct slist_entry *slh_next;
uint16_t slh_depth;
uint16_t slh_seq;
} slh_list;
};
typedef union slist_header slist_header;
struct list_entry {
struct list_entry *nle_flink;
struct list_entry *nle_blink;
};
typedef struct list_entry list_entry;
#define INIT_LIST_HEAD(l) \
l->nle_flink = l->nle_blink = l
#define REMOVE_LIST_ENTRY(e) \
do { \
list_entry *b; \
list_entry *f; \
\
f = e->nle_flink; \
b = e->nle_blink; \
b->nle_flink = f; \
f->nle_blink = b; \
} while (0)
#define REMOVE_LIST_HEAD(l) \
do { \
list_entry *f; \
list_entry *e; \
\
e = l->nle_flink; \
f = e->nle_flink; \
l->nle_flink = f; \
f->nle_blink = l; \
} while (0)
#define REMOVE_LIST_TAIL(l) \
do { \
list_entry *b; \
list_entry *e; \
\
e = l->nle_blink; \
b = e->nle_blink; \
l->nle_blink = b; \
b->nle_flink = l; \
} while (0)
#define INSERT_LIST_TAIL(l, e) \
do { \
list_entry *b; \
\
b = l->nle_blink; \
e->nle_flink = l; \
e->nle_blink = b; \
b->nle_flink = e; \
l->nle_blink = e; \
} while (0)
#define INSERT_LIST_HEAD(l, e) \
do { \
list_entry *f; \
\
f = l->nle_flink; \
e->nle_flink = f; \
e->nle_blink = l; \
f->nle_blink = e; \
l->nle_flink = e; \
} while (0)
struct nt_dispatch_header {
uint8_t dh_type;
uint8_t dh_abs;
uint8_t dh_size;
uint8_t dh_inserted;
uint32_t dh_sigstate;
list_entry dh_waitlisthead;
};
typedef struct nt_dispatch_header nt_dispatch_header;
#define OTYPE_EVENT 0
#define OTYPE_MUTEX 1
#define OTYPE_THREAD 2
#define OTYPE_TIMER 3
/* Windows dispatcher levels. */
#define PASSIVE_LEVEL 0
#define LOW_LEVEL 0
#define APC_LEVEL 1
#define DISPATCH_LEVEL 2
#define DEVICE_LEVEL (DISPATCH_LEVEL + 1)
#define PROFILE_LEVEL 27
#define CLOCK1_LEVEL 28
#define CLOCK2_LEVEL 28
#define IPI_LEVEL 29
#define POWER_LEVEL 30
#define HIGH_LEVEL 31
#define SYNC_LEVEL_UP DISPATCH_LEVEL
#define SYNC_LEVEL_MP (IPI_LEVEL - 1)
#define AT_PASSIVE_LEVEL(td) \
((td)->td_proc->p_flag & P_KTHREAD == FALSE)
#define AT_DISPATCH_LEVEL(td) \
((td)->td_base_pri == PI_REALTIME)
#define AT_DIRQL_LEVEL(td) \
((td)->td_priority <= PI_NET)
#define AT_HIGH_LEVEL(td) \
((td)->td_critnest != 0)
struct nt_objref {
nt_dispatch_header no_dh;
void *no_obj;
TAILQ_ENTRY(nt_objref) link;
};
TAILQ_HEAD(nt_objref_head, nt_objref);
typedef struct nt_objref nt_objref;
#define EVENT_TYPE_NOTIFY 0
#define EVENT_TYPE_SYNC 1
/*
* We need to use the timeout()/untimeout() API for ktimers
* since timers can be initialized, but not destroyed (so
* malloc()ing our own callout structures would mean a leak,
* since there'd be no way to free() them). This means we
* need to use struct callout_handle, which is really just a
* pointer. To make it easier to deal with, we use a union
* to overlay the callout_handle over the k_timerlistentry.
* The latter is a list_entry, which is two pointers, so
* there's enough space available to hide a callout_handle
* there.
*/
struct ktimer {
nt_dispatch_header k_header;
uint64_t k_duetime;
union {
list_entry k_timerlistentry;
struct callout_handle k_handle;
} u;
void *k_dpc;
uint32_t k_period;
};
#define k_timerlistentry u.k_timerlistentry
#define k_handle u.k_handle
typedef struct ktimer ktimer;
struct nt_kevent {
nt_dispatch_header k_header;
};
typedef struct nt_kevent nt_kevent;
/* Kernel defered procedure call (i.e. timer callback) */
struct kdpc;
typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
struct kdpc {
uint16_t k_type;
uint8_t k_num;
uint8_t k_importance;
list_entry k_dpclistentry;
kdpc_func k_deferedfunc;
void *k_deferredctx;
void *k_sysarg1;
void *k_sysarg2;
register_t k_lock;
};
typedef struct kdpc kdpc;
/*
* Note: the acquisition count is BSD-specific. The Microsoft
* documentation says that mutexes can be acquired recursively
* by a given thread, but that you must release the mutex as
* many times as you acquired it before it will be set to the
* signalled state (i.e. before any other threads waiting on
* the object will be woken up). However the Windows KMUTANT
* structure has no field for keeping track of the number of
* acquisitions, so we need to add one ourselves. As long as
* driver code treats the mutex as opaque, we should be ok.
*/
struct kmutant {
nt_dispatch_header km_header;
union {
list_entry km_listentry;
uint32_t km_acquirecnt;
} u;
void *km_ownerthread;
uint8_t km_abandoned;
uint8_t km_apcdisable;
};
#define km_listentry u.km_listentry
#define km_acquirecnt u.km_acquirecnt
typedef struct kmutant kmutant;
#define LOOKASIDE_DEPTH 256
struct general_lookaside {
slist_header gl_listhead;
uint16_t gl_depth;
uint16_t gl_maxdepth;
uint32_t gl_totallocs;
union {
uint32_t gl_allocmisses;
uint32_t gl_allochits;
} u_a;
uint32_t gl_totalfrees;
union {
uint32_t gl_freemisses;
uint32_t gl_freehits;
} u_m;
uint32_t gl_type;
uint32_t gl_tag;
uint32_t gl_size;
void *gl_allocfunc;
void *gl_freefunc;
list_entry gl_listent;
uint32_t gl_lasttotallocs;
union {
uint32_t gl_lastallocmisses;
uint32_t gl_lastallochits;
} u_l;
uint32_t gl_rsvd[2];
};
typedef struct general_lookaside general_lookaside;
struct npaged_lookaside_list {
general_lookaside nll_l;
kspin_lock nll_obsoletelock;
};
typedef struct npaged_lookaside_list npaged_lookaside_list;
typedef struct npaged_lookaside_list paged_lookaside_list;
typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
typedef void (*lookaside_free_func)(void *);
struct irp;
struct kdevice_qentry {
list_entry kqe_devlistent;
uint32_t kqe_sortkey;
uint8_t kqe_inserted;
};
typedef struct kdevice_qentry kdevice_qentry;
struct kdevice_queue {
uint16_t kq_type;
uint16_t kq_size;
list_entry kq_devlisthead;
kspin_lock kq_lock;
uint8_t kq_busy;
};
typedef struct kdevice_queue kdevice_queue;
struct wait_ctx_block {
kdevice_qentry wcb_waitqueue;
void *wcb_devfunc;
void *wcb_devctx;
uint32_t wcb_mapregcnt;
void *wcb_devobj;
void *wcb_curirp;
void *wcb_bufchaindpc;
};
typedef struct wait_ctx_block wait_ctx_block;
struct wait_block {
list_entry wb_waitlist;
void *wb_kthread;
nt_dispatch_header *wb_object;
struct wait_block *wb_next;
uint16_t wb_waitkey;
uint16_t wb_waittype;
};
typedef struct wait_block wait_block;
#define THREAD_WAIT_OBJECTS 3
#define MAX_WAIT_OBJECTS 64
#define WAITTYPE_ALL 0
#define WAITTYPE_ANY 1
struct thread_context {
void *tc_thrctx;
void *tc_thrfunc;
};
typedef struct thread_context thread_context;
struct device_object {
uint16_t do_type;
uint16_t do_size;
uint32_t do_refcnt;
struct device_object *do_drvobj;
struct device_object *do_nextdev;
struct device_object *do_attacheddev;
struct irp *do_currirp;
void *do_iotimer;
uint32_t do_flags;
uint32_t do_characteristics;
void *do_vpb;
void *do_devext;
uint8_t do_stacksize;
union {
list_entry do_listent;
wait_ctx_block do_wcb;
} queue;
uint32_t do_alignreq;
kdevice_queue do_devqueue;
struct kdpc do_dpc;
uint32_t do_activethreads;
void *do_securitydesc;
struct nt_kevent do_devlock;
uint16_t do_sectorsz;
uint16_t do_spare1;
void *do_devobj_ext;
void *do_rsvd;
};
typedef struct device_object device_object;
struct irp {
uint32_t i_dummy;
};
typedef struct irp irp;
typedef uint32_t (*driver_dispatch)(device_object *, irp *);
#define DEVPROP_DEVICE_DESCRIPTION 0x00000000
#define DEVPROP_HARDWARE_ID 0x00000001
#define DEVPROP_COMPATIBLE_IDS 0x00000002
#define DEVPROP_BOOTCONF 0x00000003
#define DEVPROP_BOOTCONF_TRANSLATED 0x00000004
#define DEVPROP_CLASS_NAME 0x00000005
#define DEVPROP_CLASS_GUID 0x00000006
#define DEVPROP_DRIVER_KEYNAME 0x00000007
#define DEVPROP_MANUFACTURER 0x00000008
#define DEVPROP_FRIENDLYNAME 0x00000009
#define DEVPROP_LOCATION_INFO 0x0000000A
#define DEVPROP_PHYSDEV_NAME 0x0000000B
#define DEVPROP_BUSTYPE_GUID 0x0000000C
#define DEVPROP_LEGACY_BUSTYPE 0x0000000D
#define DEVPROP_BUS_NUMBER 0x0000000E
#define DEVPROP_ENUMERATOR_NAME 0x0000000F
#define DEVPROP_ADDRESS 0x00000010
#define DEVPROP_UINUMBER 0x00000011
#define DEVPROP_INSTALL_STATE 0x00000012
#define DEVPROP_REMOVAL_POLICY 0x00000013
#define STATUS_SUCCESS 0x00000000
#define STATUS_USER_APC 0x000000C0
#define STATUS_KERNEL_APC 0x00000100
#define STATUS_ALERTED 0x00000101
#define STATUS_TIMEOUT 0x00000102
#define STATUS_INVALID_PARAMETER 0xC000000D
#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010
#define STATUS_BUFFER_TOO_SMALL 0xC0000023
#define STATUS_MUTANT_NOT_OWNED 0xC0000046
#define STATUS_INVALID_PARAMETER_2 0xC00000F0
#define STATUS_WAIT_0 0x00000000
/*
* FreeBSD's kernel stack is 2 pages in size by default. The
* Windows stack is larger, so we need to give our threads more
* stack pages. 4 should be enough, we use 8 just to extra safe.
*/
#define NDIS_KSTACK_PAGES 8
extern image_patch_table ntoskrnl_functbl[];
__BEGIN_DECLS
extern int ntoskrnl_libinit(void);
extern int ntoskrnl_libfini(void);
__stdcall extern void ntoskrnl_init_dpc(kdpc *, void *, void *);
__stdcall extern uint8_t ntoskrnl_queue_dpc(kdpc *, void *, void *);
__stdcall extern uint8_t ntoskrnl_dequeue_dpc(kdpc *);
__stdcall extern void ntoskrnl_init_timer(ktimer *);
__stdcall extern void ntoskrnl_init_timer_ex(ktimer *, uint32_t);
__stdcall extern uint8_t ntoskrnl_set_timer(ktimer *, int64_t, kdpc *);
__stdcall extern uint8_t ntoskrnl_set_timer_ex(ktimer *, int64_t,
uint32_t, kdpc *);
__stdcall extern uint8_t ntoskrnl_cancel_timer(ktimer *);
__stdcall extern uint8_t ntoskrnl_read_timer(ktimer *);
__stdcall extern uint32_t ntoskrnl_waitforobj(nt_dispatch_header *, uint32_t,
uint32_t, uint8_t, int64_t *);
__stdcall extern void ntoskrnl_init_event(nt_kevent *, uint32_t, uint8_t);
__stdcall extern void ntoskrnl_clear_event(nt_kevent *);
__stdcall extern uint32_t ntoskrnl_read_event(nt_kevent *);
__stdcall extern uint32_t ntoskrnl_set_event(nt_kevent *, uint32_t, uint8_t);
__stdcall extern uint32_t ntoskrnl_reset_event(nt_kevent *);
__fastcall extern void ntoskrnl_lock_dpc(REGARGS1(kspin_lock *));
__fastcall extern void ntoskrnl_unlock_dpc(REGARGS1(kspin_lock *));
/*
* On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
* routines live in the HAL. We try to imitate this behavior.
*/
#ifdef __i386__
#define ntoskrnl_acquire_spinlock(a, b) *(b) = FASTCALL1(hal_lock, a)
#define ntoskrnl_release_spinlock(a, b) FASTCALL2(hal_unlock, a, b)
#define ntoskrnl_raise_irql(a) FASTCALL1(hal_raise_irql, a)
#define ntoskrnl_lower_irql(a) FASTCALL1(hal_lower_irql, a)
#endif /* __i386__ */
__END_DECLS
#endif /* _NTOSKRNL_VAR_H_ */