summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/ndis/hal_var.h8
-rw-r--r--sys/compat/ndis/kern_ndis.c23
-rw-r--r--sys/compat/ndis/ndis_var.h5
-rw-r--r--sys/compat/ndis/ntoskrnl_var.h4
-rw-r--r--sys/compat/ndis/pe_var.h41
-rw-r--r--sys/compat/ndis/subr_hal.c33
-rw-r--r--sys/compat/ndis/subr_ndis.c139
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c139
-rw-r--r--usr.sbin/ndiscvt/ndiscvt.8122
-rw-r--r--usr.sbin/ndiscvt/ndiscvt.c155
10 files changed, 511 insertions, 158 deletions
diff --git a/sys/compat/ndis/hal_var.h b/sys/compat/ndis/hal_var.h
index 64a209f..d0da06d 100644
--- a/sys/compat/ndis/hal_var.h
+++ b/sys/compat/ndis/hal_var.h
@@ -46,10 +46,10 @@
extern image_patch_table hal_functbl[];
__BEGIN_DECLS
-__stdcall extern uint8_t hal_lock(/*kspin_lock * */void);
-__stdcall extern void hal_unlock(/*kspin_lock *, uint8_t*/void);
-__stdcall extern uint8_t hal_raise_irql(/*uint8_t*/ void);
-__stdcall extern void hal_lower_irql(/*uint8_t*/ void);
+__fastcall extern uint8_t hal_lock(REGARGS1(kspin_lock *lock));
+__fastcall void hal_unlock(REGARGS2(kspin_lock *lock, uint8_t newirql));
+__fastcall extern uint8_t hal_raise_irql(REGARGS1(uint8_t irql));
+__fastcall extern void hal_lower_irql(REGARGS1(uint8_t oldirql));
__stdcall extern uint8_t hal_irql(void);
__END_DECLS
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index 59c9d38..49b012f 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -605,6 +605,8 @@ ndis_create_sysctls(arg)
struct ndis_softc *sc;
ndis_cfg *vals;
char buf[256];
+ struct sysctl_oid *oidp;
+ struct sysctl_ctx_entry *e;
if (arg == NULL)
return(EINVAL);
@@ -633,6 +635,27 @@ ndis_create_sysctls(arg)
vals++;
continue;
}
+
+ /* See if we already have a sysctl with this name */
+
+ oidp = NULL;
+#if __FreeBSD_version < 502113
+ TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
+#else
+ TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
+#endif
+ oidp = e->entry;
+ if (ndis_strcasecmp(oidp->oid_name,
+ vals->nc_cfgkey) == 0)
+ break;
+ oidp = NULL;
+ }
+
+ if (oidp != NULL) {
+ vals++;
+ continue;
+ }
+
#if __FreeBSD_version < 502113
SYSCTL_ADD_STRING(&sc->ndis_ctx,
SYSCTL_CHILDREN(sc->ndis_tree),
diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h
index 2c88b9d..0ddcc26 100644
--- a/sys/compat/ndis/ndis_var.h
+++ b/sys/compat/ndis/ndis_var.h
@@ -1314,7 +1314,11 @@ struct ndis_timer_entry {
TAILQ_HEAD(nte_head, ndis_timer_entry);
+#define NDIS_FH_TYPE_VFS 0
+#define NDIS_FH_TYPE_MODULE 1
+
struct ndis_fh {
+ int nf_type;
void *nf_vp;
void *nf_map;
uint32_t nf_maplen;
@@ -1522,6 +1526,7 @@ extern int ndis_unsched(void (*)(void *), void *, int);
extern int ndis_thsuspend(struct proc *, int);
extern void ndis_thresume(struct proc *);
extern int ndis_strcasecmp(const char *, const char *);
+extern int ndis_strncasecmp(const char *, const char *, size_t);
__END_DECLS
#endif /* _NDIS_VAR_H_ */
diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h
index b70ce90..891fef8 100644
--- a/sys/compat/ndis/ntoskrnl_var.h
+++ b/sys/compat/ndis/ntoskrnl_var.h
@@ -508,8 +508,8 @@ __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 *);
-__stdcall extern void ntoskrnl_lock_dpc(/*kspin_lock * */ void);
-__stdcall extern void ntoskrnl_unlock_dpc(/*kspin_lock * */ void);
+__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()
diff --git a/sys/compat/ndis/pe_var.h b/sys/compat/ndis/pe_var.h
index e156f0f..b78ebbb 100644
--- a/sys/compat/ndis/pe_var.h
+++ b/sys/compat/ndis/pe_var.h
@@ -418,8 +418,20 @@ typedef struct image_patch_table image_patch_table;
#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
@@ -430,37 +442,34 @@ typedef struct image_patch_table image_patch_table;
*/
#ifdef __i386__
-typedef __stdcall int (*fcall)(void);
-typedef __stdcall int (*fcall2)(int);
+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(fcall f, uint32_t a)
+fastcall1(fcall1 f, uint32_t a)
{
- __asm__ __volatile__ ("movl %0,%%ecx" : : "r" (a));
- return(f());
+ return(f(REGCALL1(a)));
}
static __inline uint32_t
-fastcall2(fcall f, uint32_t a, uint32_t b)
+fastcall2(fcall2 f, uint32_t a, uint32_t b)
{
- __asm__ __volatile__ ("movl %0,%%ecx" : : "r" (a));
- __asm__ __volatile__ ("movl %0,%%edx" : : "r" (b));
- return(f());
+ return(f(REGCALL2(a, b)));
}
static __inline uint32_t
-fastcall3(fcall2 f, uint32_t a, uint32_t b, uint32_t c)
+fastcall3(fcall3 f, uint32_t a, uint32_t b, uint32_t c)
{
- __asm__ __volatile__ ("movl %0,%%ecx" : : "r" (a));
- __asm__ __volatile__ ("movl %0,%%edx" : : "r" (b));
- return(f(c));
+ return(f(REGCALL2(a, b), c));
}
#define FASTCALL1(f, a) \
- fastcall1((fcall)(f), (uint32_t)(a))
+ fastcall1((fcall1)(f), (uint32_t)(a))
#define FASTCALL2(f, a, b) \
- fastcall2((fcall)(f), (uint32_t)(a), (uint32_t)(b))
+ fastcall2((fcall2)(f), (uint32_t)(a), (uint32_t)(b))
#define FASTCALL3(f, a, b, c) \
- fastcall3((fcall2)(f), (uint32_t)(a), (uint32_t)(b), (uint32_t)(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))
diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c
index deae5ef..42cea66 100644
--- a/sys/compat/ndis/subr_hal.c
+++ b/sys/compat/ndis/subr_hal.c
@@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <compat/ndis/pe_var.h>
-#include <compat/ndis/hal_var.h>
#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/hal_var.h>
#define FUNC void(*)(void)
@@ -252,14 +252,11 @@ hal_readport_buf_uchar(port, val, cnt)
* or HIGH_LEVEL, we panic.
*/
-__stdcall uint8_t
-hal_lock(/*lock*/void)
+__fastcall uint8_t
+hal_lock(REGARGS1(kspin_lock *lock))
{
- kspin_lock *lock;
uint8_t oldirql;
- __asm__ __volatile__ ("" : "=c" (lock));
-
/* I am so going to hell for this. */
if (hal_irql() > DISPATCH_LEVEL)
panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
@@ -270,14 +267,9 @@ hal_lock(/*lock*/void)
return(oldirql);
}
-__stdcall void
-hal_unlock(/*lock, newirql*/void)
+__fastcall void
+hal_unlock(REGARGS2(kspin_lock *lock, uint8_t newirql))
{
- kspin_lock *lock;
- uint8_t newirql;
-
- __asm__ __volatile__ ("" : "=c" (lock), "=d" (newirql));
-
FASTCALL1(ntoskrnl_unlock_dpc, lock);
FASTCALL1(hal_lower_irql, newirql);
@@ -302,14 +294,11 @@ hal_perfcount(freq)
return((uint64_t)ticks);
}
-__stdcall uint8_t
-hal_raise_irql(/*irql*/ void)
+__fastcall uint8_t
+hal_raise_irql(REGARGS1(uint8_t irql))
{
- uint8_t irql;
uint8_t oldirql;
- __asm__ __volatile__ ("" : "=c" (irql));
-
if (irql < hal_irql())
panic("IRQL_NOT_LESS_THAN");
@@ -325,13 +314,9 @@ hal_raise_irql(/*irql*/ void)
return(oldirql);
}
-__stdcall void
-hal_lower_irql(/*oldirql*/ void)
+__fastcall void
+hal_lower_irql(REGARGS1(uint8_t oldirql))
{
- uint8_t oldirql;
-
- __asm__ __volatile__ ("" : "=c" (oldirql));
-
if (oldirql == DISPATCH_LEVEL)
return;
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index e85ec7f..3213b1c 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <sys/kthread.h>
+#include <sys/linker.h>
+#include <sys/mount.h>
+#include <sys/sysproto.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -260,6 +263,7 @@ __stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
void **, uint32_t *, uint32_t *);
__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
void **, uint32_t *, uint32_t *, uint32_t);
+static int ndis_find_sym(linker_file_t, char *, char *, caddr_t *);
__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
ndis_unicode_string *, ndis_physaddr);
__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
@@ -572,13 +576,36 @@ ndis_strcasecmp(s1, s2)
b = *s2++;
if (toupper(a) != toupper(b))
break;
- if (*s1++ == 0)
+ if (*s1++ == '\0')
return(0);
}
return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}
+int
+ndis_strncasecmp(s1, s2, n)
+ const char *s1;
+ const char *s2;
+ size_t n;
+{
+ char a, b;
+
+ if (n != 0) {
+ do {
+ a = *s1;
+ b = *s2++;
+ if (toupper(a) != toupper(b))
+ return (*(const unsigned char *)s1 -
+ *(const unsigned char *)(s2 - 1));
+ if (*s1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+
+ return(0);
+}
+
__stdcall static void
ndis_read_cfg(status, parm, cfg, key, type)
ndis_status *status;
@@ -2533,6 +2560,32 @@ ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
}
+static int
+ndis_find_sym(lf, filename, suffix, sym)
+ linker_file_t lf;
+ char *filename;
+ char *suffix;
+ caddr_t *sym;
+{
+ char fullsym[MAXPATHLEN];
+ int i;
+
+ bzero(fullsym, sizeof(fullsym));
+ strcpy(fullsym, filename);
+ for (i = 0; i < strlen(fullsym); i++) {
+ if (fullsym[i] == '.')
+ fullsym[i] = '_';
+ else
+ fullsym[i] = tolower(fullsym[i]);
+ }
+ strcat(fullsym, suffix);
+ *sym = linker_file_lookup_symbol(lf, fullsym, 0);
+ if (*sym == 0)
+ return(ENOENT);
+
+ return(0);
+}
+
/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
__stdcall static void
ndis_open_file(status, filehandle, filelength, filename, highestaddr)
@@ -2550,19 +2603,74 @@ ndis_open_file(status, filehandle, filelength, filename, highestaddr)
struct vattr *vap = &vat;
ndis_fh *fh;
char path[MAXPATHLEN];
+ linker_file_t head, lf;
+ caddr_t kldstart, kldend;
ndis_unicode_to_ascii(filename->nus_buf,
filename->nus_len, &afilename);
- sprintf(path, "%s/%s", ndis_filepath, afilename);
- free(afilename, M_DEVBUF);
-
fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT);
if (fh == NULL) {
*status = NDIS_STATUS_RESOURCES;
return;
}
+ /*
+ * During system bootstrap, it's impossible to load files
+ * from the rootfs since it's not mounted yet. We therefore
+ * offer the possibility of opening files that have been
+ * preloaded as modules instead. Both choices will work
+ * when kldloading a module from multiuser, but only the
+ * module option will work during bootstrap. The module
+ * loading option works by using the ndiscvt(8) utility
+ * to convert the arbitrary file into a .ko using objcopy(1).
+ * This file will contain two special symbols: filename_start
+ * and filename_end. All we have to do is traverse the KLD
+ * list in search of those symbols and we've found the file
+ * data. As an added bonus, ndiscvt(8) will also generate
+ * a normal .o file which can be linked statically with
+ * the kernel. This means that the symbols will actual reside
+ * in the kernel's symbol table, but that doesn't matter to
+ * us since the kernel appears to us as just another module.
+ */
+
+ /*
+ * This is an evil trick for getting the head of the linked
+ * file list, which is not exported from kern_linker.o. It
+ * happens that linker file #1 is always the kernel, and is
+ * always the first element in the list.
+ */
+
+ head = linker_find_file_by_id(1);
+ for (lf = head; lf != NULL; lf = TAILQ_NEXT(lf, link)) {
+ if (ndis_find_sym(lf, afilename, "_start", &kldstart))
+ continue;
+ if (ndis_find_sym(lf, afilename, "_end", &kldend))
+ continue;
+ fh->nf_vp = lf;
+ fh->nf_type = NDIS_FH_TYPE_MODULE;
+ fh->nf_map = kldstart;
+ *filelength = fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF;
+ *filehandle = fh;
+ free(afilename, M_DEVBUF);
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+ }
+
+ if (TAILQ_EMPTY(&mountlist)) {
+ free(fh, M_TEMP);
+ *status = NDIS_STATUS_FILE_NOT_FOUND;
+ printf("NDIS: could not find file %s in linker list\n",
+ afilename);
+ printf("NDIS: and no filesystems mounted yet, "
+ "aborting NdisOpenFile()\n");
+ free(afilename, M_DEVBUF);
+ return;
+ }
+
+ sprintf(path, "%s/%s", ndis_filepath, afilename);
+ free(afilename, M_DEVBUF);
+
mtx_lock(&Giant);
/* Some threads don't have a current working directory. */
@@ -2593,6 +2701,7 @@ ndis_open_file(status, filehandle, filelength, filename, highestaddr)
fh->nf_vp = nd.ni_vp;
fh->nf_map = NULL;
+ fh->nf_type = NDIS_FH_TYPE_VFS;
*filehandle = fh;
*filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
*status = NDIS_STATUS_SUCCESS;
@@ -2627,6 +2736,13 @@ ndis_map_file(status, mappedbuffer, filehandle)
return;
}
+ if (fh->nf_type == NDIS_FH_TYPE_MODULE) {
+ /* Already found the mapping address during the open. */
+ *status = NDIS_STATUS_SUCCESS;
+ *mappedbuffer = fh->nf_map;
+ return;
+ }
+
fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT);
if (fh->nf_map == NULL) {
@@ -2658,7 +2774,9 @@ ndis_unmap_file(filehandle)
if (fh->nf_map == NULL)
return;
- free(fh->nf_map, M_DEVBUF);
+
+ if (fh->nf_type == NDIS_FH_TYPE_VFS)
+ free(fh->nf_map, M_DEVBUF);
fh->nf_map = NULL;
return;
@@ -2676,16 +2794,19 @@ ndis_close_file(filehandle)
fh = (ndis_fh *)filehandle;
if (fh->nf_map != NULL) {
- free(fh->nf_map, M_DEVBUF);
+ if (fh->nf_type == NDIS_FH_TYPE_VFS)
+ free(fh->nf_map, M_DEVBUF);
fh->nf_map = NULL;
}
if (fh->nf_vp == NULL)
return;
- mtx_lock(&Giant);
- vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
- mtx_unlock(&Giant);
+ if (fh->nf_type == NDIS_FH_TYPE_VFS) {
+ mtx_lock(&Giant);
+ vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
+ mtx_unlock(&Giant);
+ }
fh->nf_vp = NULL;
free(fh, M_DEVBUF);
diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
index b8c85f4..2a39374 100644
--- a/sys/compat/ndis/subr_ntoskrnl.c
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -62,9 +62,9 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <compat/ndis/pe_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
#include <compat/ndis/hal_var.h>
#include <compat/ndis/resource_var.h>
-#include <compat/ndis/ntoskrnl_var.h>
#include <compat/ndis/ndis_var.h>
#define __regparm __attribute__((regparm(3)))
@@ -81,8 +81,10 @@ __stdcall static ndis_status ntoskrnl_ansi_to_unicode(ndis_unicode_string *,
ndis_ansi_string *, uint8_t);
__stdcall static void *ntoskrnl_iobuildsynchfsdreq(uint32_t, void *,
void *, uint32_t, uint32_t *, void *, void *);
-__stdcall static uint32_t ntoskrnl_iofcalldriver(/*void *, void * */ void);
-__stdcall static void ntoskrnl_iofcompletereq(/*void *, uint8_t*/ void);
+__fastcall static uint32_t ntoskrnl_iofcalldriver(REGARGS2(void *dobj,
+ void *irp));
+__fastcall static void ntoskrnl_iofcompletereq(REGARGS2(void *irp,
+ uint8_t prioboost));
__stdcall static uint32_t ntoskrnl_waitforobjs(uint32_t,
nt_dispatch_header **, uint32_t, uint32_t, uint32_t, uint8_t,
int64_t *, wait_block *);
@@ -117,19 +119,22 @@ __stdcall static void ntoskrnl_init_nplookaside(npaged_lookaside_list *,
lookaside_alloc_func *, lookaside_free_func *,
uint32_t, size_t, uint32_t, uint16_t);
__stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *);
-__stdcall static slist_entry *ntoskrnl_push_slist(/*slist_header *,
- slist_entry * */ void);
-__stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_header * */ void);
-__stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_header *,
- slist_entry *,*/ kspin_lock *);
-__stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_header *,
- kspin_lock * */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_interlock_addstat(/*uint64_t,
- uint32_t*/ void);
+__fastcall static slist_entry *ntoskrnl_push_slist(REGARGS2(slist_header *head,
+ slist_entry *entry));
+__fastcall static slist_entry *ntoskrnl_pop_slist(REGARGS1(slist_header
+ *head));
+__fastcall static slist_entry
+ *ntoskrnl_push_slist_ex(REGARGS2(slist_header *head,
+ slist_entry *entry), kspin_lock *lock);
+__fastcall static slist_entry
+ *ntoskrnl_pop_slist_ex(REGARGS2(slist_header *head,
+ kspin_lock *lock));
+__fastcall static uint32_t
+ ntoskrnl_interlock_inc(REGARGS1(volatile uint32_t *addend));
+__fastcall static uint32_t
+ ntoskrnl_interlock_dec(REGARGS1(volatile uint32_t *addend));
+__fastcall static void ntoskrnl_interlock_addstat(REGARGS2(uint64_t *addend,
+ uint32_t inc));
__stdcall static void ntoskrnl_freemdl(ndis_buffer *);
__stdcall static uint32_t ntoskrnl_sizeofmdl(void *, size_t);
__stdcall static void ntoskrnl_build_npaged_mdl(ndis_buffer *);
@@ -162,7 +167,7 @@ __stdcall static uint32_t ntoskrnl_release_mutex(kmutant *, uint8_t);
__stdcall static uint32_t ntoskrnl_read_mutex(kmutant *);
__stdcall static ndis_status ntoskrnl_objref(ndis_handle, uint32_t, void *,
uint8_t, void **, void **);
-__stdcall static void ntoskrnl_objderef(/*void * */ void);
+__fastcall static void ntoskrnl_objderef(REGARGS1(void *object));
__stdcall static uint32_t ntoskrnl_zwclose(ndis_handle);
static uint32_t ntoskrnl_dbgprint(char *, ...);
__stdcall static void ntoskrnl_debugger(void);
@@ -293,25 +298,15 @@ ntoskrnl_iobuildsynchfsdreq(func, dobj, buf, len, off, event, status)
return(NULL);
}
-__stdcall static uint32_t
-ntoskrnl_iofcalldriver(/*dobj, irp*/)
+__fastcall static uint32_t
+ntoskrnl_iofcalldriver(REGARGS2(void *dobj, void *irp))
{
- void *dobj;
- void *irp;
-
- __asm__ __volatile__ ("" : "=c" (dobj), "=d" (irp));
-
return(0);
}
-__stdcall static void
-ntoskrnl_iofcompletereq(/*irp, prioboost*/)
+__fastcall static void
+ntoskrnl_iofcompletereq(REGARGS2(void *irp, uint8_t prioboost))
{
- void *irp;
- uint8_t prioboost;
-
- __asm__ __volatile__ ("" : "=c" (irp), "=d" (prioboost));
-
return;
}
@@ -957,49 +952,38 @@ ntoskrnl_delete_nplookaside(lookaside)
* declared to be _fastcall in Windows. gcc 3.4 is supposed
* to have support for this calling convention, however we
* don't have that version available yet, so we kludge things
- * up using some inline assembly.
+ * up using __regparm__(3) and some argument shuffling.
*/
-__stdcall static slist_entry *
-ntoskrnl_push_slist(/*head, entry*/ void)
+__fastcall static slist_entry *
+ntoskrnl_push_slist(REGARGS2(slist_header *head, slist_entry *entry))
{
- slist_header *head;
- slist_entry *entry;
slist_entry *oldhead;
- __asm__ __volatile__ ("" : "=c" (head), "=d" (entry));
-
oldhead = (slist_entry *)FASTCALL3(ntoskrnl_push_slist_ex,
head, entry, &ntoskrnl_global);
return(oldhead);
}
-__stdcall static slist_entry *
-ntoskrnl_pop_slist(/*head*/ void)
+__fastcall static slist_entry *
+ntoskrnl_pop_slist(REGARGS1(slist_header *head))
{
- slist_header *head;
slist_entry *first;
- __asm__ __volatile__ ("" : "=c" (head));
-
first = (slist_entry *)FASTCALL2(ntoskrnl_pop_slist_ex,
head, &ntoskrnl_global);
return(first);
}
-__stdcall static slist_entry *
-ntoskrnl_push_slist_ex(/*head, entry,*/ lock)
- kspin_lock *lock;
+__fastcall static slist_entry *
+ntoskrnl_push_slist_ex(REGARGS2(slist_header *head,
+ slist_entry *entry), kspin_lock *lock)
{
- slist_header *head;
- slist_entry *entry;
slist_entry *oldhead;
uint8_t irql;
- __asm__ __volatile__ ("" : "=c" (head), "=d" (entry));
-
irql = FASTCALL2(hal_lock, lock, DISPATCH_LEVEL);
oldhead = ntoskrnl_pushsl(head, entry);
FASTCALL2(hal_unlock, lock, irql);
@@ -1007,16 +991,12 @@ ntoskrnl_push_slist_ex(/*head, entry,*/ lock)
return(oldhead);
}
-__stdcall static slist_entry *
-ntoskrnl_pop_slist_ex(/*head, lock*/ void)
+__fastcall static slist_entry *
+ntoskrnl_pop_slist_ex(REGARGS2(slist_header *head, kspin_lock *lock))
{
- slist_header *head;
- kspin_lock *lock;
slist_entry *first;
uint8_t irql;
- __asm__ __volatile__ ("" : "=c" (head), "=d" (lock));
-
irql = FASTCALL2(hal_lock, lock, DISPATCH_LEVEL);
first = ntoskrnl_popsl(head);
FASTCALL2(hal_unlock, lock, irql);
@@ -1024,62 +1004,42 @@ ntoskrnl_pop_slist_ex(/*head, lock*/ void)
return(first);
}
-__stdcall void
-ntoskrnl_lock_dpc(/*lock*/ void)
+__fastcall void
+ntoskrnl_lock_dpc(REGARGS1(kspin_lock *lock))
{
- kspin_lock *lock;
-
- __asm__ __volatile__ ("" : "=c" (lock));
-
while (atomic_cmpset_acq_int((volatile u_int *)lock, 0, 1) == 0)
/* sit and spin */;
return;
}
-__stdcall void
-ntoskrnl_unlock_dpc(/*lock*/ void)
+__fastcall void
+ntoskrnl_unlock_dpc(REGARGS1(kspin_lock *lock))
{
- kspin_lock *lock;
-
- __asm__ __volatile__ ("" : "=c" (lock));
-
atomic_store_rel_int((volatile u_int *)lock, 0);
return;
}
-__stdcall static uint32_t
-ntoskrnl_interlock_inc(/*addend*/ void)
+__fastcall static uint32_t
+ntoskrnl_interlock_inc(REGARGS1(volatile uint32_t *addend))
{
- volatile uint32_t *addend;
-
- __asm__ __volatile__ ("" : "=c" (addend));
-
atomic_add_long((volatile u_long *)addend, 1);
return(*addend);
}
-__stdcall static uint32_t
-ntoskrnl_interlock_dec(/*addend*/ void)
+__fastcall static uint32_t
+ntoskrnl_interlock_dec(REGARGS1(volatile uint32_t *addend))
{
- volatile uint32_t *addend;
-
- __asm__ __volatile__ ("" : "=c" (addend));
-
atomic_subtract_long((volatile u_long *)addend, 1);
return(*addend);
}
-__stdcall static void
-ntoskrnl_interlock_addstat(/*addend, inc*/)
+__fastcall static void
+ntoskrnl_interlock_addstat(REGARGS2(uint64_t *addend, uint32_t inc))
{
- uint64_t *addend;
- uint32_t inc;
uint8_t irql;
- __asm__ __volatile__ ("" : "=c" (addend), "=d" (inc));
-
irql = FASTCALL2(hal_lock, &ntoskrnl_global, DISPATCH_LEVEL);
*addend += inc;
FASTCALL2(hal_unlock, &ntoskrnl_global, irql);
@@ -1510,14 +1470,11 @@ ntoskrnl_objref(handle, reqaccess, otype, accessmode, object, handleinfo)
return(NDIS_STATUS_SUCCESS);
}
-__stdcall static void
-ntoskrnl_objderef(/*object*/void)
+__fastcall static void
+ntoskrnl_objderef(REGARGS1(void *object))
{
- void *object;
nt_objref *nr;
- __asm__ __volatile__ ("" : "=c" (object));
-
nr = object;
TAILQ_REMOVE(&ntoskrnl_reflist, nr, link);
free(nr, M_DEVBUF);
diff --git a/usr.sbin/ndiscvt/ndiscvt.8 b/usr.sbin/ndiscvt/ndiscvt.8
index 6ba8a5b..7c5294d 100644
--- a/usr.sbin/ndiscvt/ndiscvt.8
+++ b/usr.sbin/ndiscvt/ndiscvt.8
@@ -41,10 +41,13 @@ NDIS drivers for use with
.Fx
.Sh SYNOPSIS
.Nm
+.Op Fl O
.Op Fl i Ar inffile
.Fl s Ar sysfile
.Op Fl n Ar devname
.Op Fl o Ar outfile
+.Nm
+.Op Fl f Ar firmfile
.Sh DESCRIPTION
The
.Nm
@@ -144,10 +147,127 @@ The
module expects to find the driver data in a file called
.Pa ndis_driver_data.h ,
so it is recommended that this name be used.
+.It Fl O
+Generate both an
+.Pa ndis_driver_data.h
+file and
+an
+.Pa ndis_driver.data.o
+file. The latter file will contain a copy of the
+.Tn Windows\[rg]
+.Pa .SYS
+driver image encoded as a
+.Fx
+ELF object file
+.Po
+created with
+.Xr objcopy 1
+.Pc .
+Turning the
+.Tn Windows\[rg]
+driver image directly into an object code file saves disk space
+and compilation time.
+.It Fl f Ar firmfile
+A few NDIS drivers come with additional files that the core
+driver module will load during initialization time. Typically,
+these files contain firmware which the driver will transfer to
+the device in order to make it fully operational. In
+.Tn Windows\[rg] ,
+these files are usually just copied into one of the system
+directories along with the driver itself.
+.Pp
+In
+.Fx
+there are two mechanism for loading these files. If the driver
+is built as a loadable kernel module which is loaded after the
+kernel has finished booting
+.Po
+and after the root filesystem has
+been mounted
+.Pc ,
+the extra files can simply be copied to the
+.Pa /compat/ndis
+directory, and they will be loaded into the kernel on demand when the
+the driver needs them.
+.Pp
+If however the driver is required to bootstrap the system
+.Po
+i.e. if
+the NDIS-based network interface is to be used for diskless/PXE
+booting
+.Pc ,
+the files need to be pre-loaded by the bootstrap
+loader in order to be accessible, since the driver will need them
+before the root filesystem has been mounted. However, the bootstrap
+loader is only able to load files that are shared
+.Fx
+binary objects.
+.Pp
+The
+.Fl f
+flag can be used to convert an arbitrary file
+.Ar firmfile
+into shared object format
+.Po
+the actual conversion is done using
+the
+.Xr objcopy 1
+and
+.Xr ld 1
+commands
+.Pc .
+The resulting files can then be copied to the
+.Pa /boot/kernel
+directory, and can be pre-loaded directly from the boot loader
+prompt, or automatically by editing the
+.Xr loader.conf 5
+file. If desired, the files can also be loaded into memory
+at runtime using the
+.Xr kldload 8
+command.
+.Pp
+When an NDIS driver tries to open an external file, the
+.Xr ndisapi 9
+code will first search for a loaded kernel module that matches the
+name specified in the open request, and if that fails, it will then
+try to open the file from the
+.Pa /compat/ndis
+directory as well. Note that during kernel bootstrap, the ability
+to open files from
+.Pa /compat/ndis
+is disabled: only the module search will be performed.
+.Pp
+When using the
+.Fl f
+flag,
+.Nm
+will generate both a relocatable object file
+.Po
+with a
+.Pa .o
+extension
+.Pc
+and a shared object file
+.Po
+with a
+.Pa .ko
+extension
+.Pc
+. The shared object is the one that should be placed in
+the
+.Pa /boot/kernel
+directory. The relocatable object file is useful if the user wishes
+to create a completely static kernel image: the object file can be
+linked into the kernel directly along with the driver itself. Some
+editing of the kernel configuration files will be necessary in order
+to have the extra object included in the build.
.El
.Sh SEE ALSO
+.Xr kldload 8 ,
+.Xr ld 1 ,
.Xr ndis 4 ,
-.Xr ndisapi 9
+.Xr ndisapi 9 ,
+.Xr objcopy 1
.Sh HISTORY
The
.Nm
diff --git a/usr.sbin/ndiscvt/ndiscvt.c b/usr.sbin/ndiscvt/ndiscvt.c
index d1a29b3..8c78d54 100644
--- a/usr.sbin/ndiscvt/ndiscvt.c
+++ b/usr.sbin/ndiscvt/ndiscvt.c
@@ -42,7 +42,9 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <libgen.h>
#include <err.h>
+#include <ctype.h>
#include <compat/ndis/pe_var.h>
@@ -157,25 +159,130 @@ int insert_padding(imgbase, imglen)
static void
usage(void)
{
- fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> "
+ fprintf(stderr, "Usage: %s [-O] [-i <inffile>] -s <sysfile> "
"[-n devname] [-o outfile]\n", __progname);
+ fprintf(stderr, " %s -f <firmfile>\n", __progname);
+
exit(1);
}
+static void
+bincvt(char *sysfile, char *outfile, void *img, int fsize)
+{
+ char *ptr;
+ char tname[] = "/tmp/ndiscvt.XXXXXX";
+ char sysbuf[1024];
+ FILE *binfp;
+
+ mkstemp(tname);
+
+ binfp = fopen(tname, "a+");
+ if (binfp == NULL)
+ err(1, "opening %s failed", tname);
+
+ if (fwrite(img, fsize, 1, binfp) != 1)
+ err(1, "failed to output binary image");
+
+ fclose(binfp);
+
+ outfile = strdup(basename(outfile));
+ if (strchr(outfile, '.'))
+ *strchr(outfile, '.') = '\0';
+
+ snprintf(sysbuf, sizeof(sysbuf),
+ "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n",
+ tname, outfile);
+ printf("%s", sysbuf);
+ system(sysbuf);
+ unlink(tname);
+
+ ptr = tname;
+ while (*ptr) {
+ if (*ptr == '/' || *ptr == '.')
+ *ptr = '_';
+ ptr++;
+ }
+
+ snprintf(sysbuf, sizeof(sysbuf),
+ "objcopy --redefine-sym _binary_%s_start=%s_drv_data_start "
+ "--strip-symbol _binary_%s_size "
+ "--redefine-sym _binary_%s_end=%s_drv_data_end %s.o %s.o\n",
+ tname, sysfile, tname, tname, sysfile, outfile, outfile);
+ printf("%s", sysbuf);
+ system(sysbuf);
+
+ return;
+}
+
+static void
+firmcvt(char *firmfile)
+{
+ char *basefile, *outfile, *ptr;
+ char sysbuf[1024];
+
+ outfile = basename(firmfile);
+ basefile = strdup(outfile);
+
+ snprintf(sysbuf, sizeof(sysbuf),
+ "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n",
+ firmfile, outfile);
+ printf("%s", sysbuf);
+ system(sysbuf);
+
+ ptr = firmfile;
+ while (*ptr) {
+ if (*ptr == '/' || *ptr == '.')
+ *ptr = '_';
+ ptr++;
+ }
+ ptr = basefile;
+ while (*ptr) {
+ if (*ptr == '/' || *ptr == '.')
+ *ptr = '_';
+ else
+ *ptr = tolower(*ptr);
+ ptr++;
+ }
+
+ snprintf(sysbuf, sizeof(sysbuf),
+ "objcopy --redefine-sym _binary_%s_start=%s_start "
+ "--strip-symbol _binary_%s_size "
+ "--redefine-sym _binary_%s_end=%s_end %s.o %s.o\n",
+ firmfile, basefile, firmfile, firmfile,
+ basefile, outfile, outfile);
+ ptr = sysbuf;
+ printf("%s", sysbuf);
+ system(sysbuf);
+
+ snprintf(sysbuf, sizeof(sysbuf),
+ "ld -Bshareable -d -warn-common -o %s.ko %s.o\n",
+ outfile, outfile);
+ printf("%s", sysbuf);
+ system(sysbuf);
+
+ free(basefile);
+
+ exit(0);
+}
+
int
main(int argc, char *argv[])
{
- FILE *fp, *outfp;
- void *img;
- int n, fsize, cnt;
- unsigned char *ptr;
- int i;
- char *inffile = NULL, *sysfile = NULL, *outfile = NULL;
- char *dname = NULL;
- int ch;
-
- while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) {
+ FILE *fp, *outfp;
+ int i, bin = 0;
+ void *img;
+ int n, fsize, cnt;
+ unsigned char *ptr;
+ char *inffile = NULL, *sysfile = NULL;
+ char *outfile = NULL, *firmfile = NULL;
+ char *dname = NULL;
+ int ch;
+
+ while((ch = getopt(argc, argv, "i:s:o:n:f:O")) != -1) {
switch(ch) {
+ case 'f':
+ firmfile = optarg;
+ break;
case 'i':
inffile = optarg;
break;
@@ -188,12 +295,18 @@ main(int argc, char *argv[])
case 'n':
dname = optarg;
break;
+ case 'O':
+ bin = 1;
+ break;
default:
usage();
break;
}
}
+ if (firmfile != NULL)
+ firmcvt(firmfile);
+
if (sysfile == NULL)
usage();
@@ -253,6 +366,25 @@ main(int argc, char *argv[])
}
fprintf(outfp, "\n#ifdef NDIS_IMAGE\n");
+
+ if (bin) {
+ sysfile = strdup(basename(sysfile));
+ ptr = sysfile;
+ while (*ptr) {
+ if (*ptr == '.')
+ *ptr = '_';
+ ptr++;
+ }
+ fprintf(outfp,
+ "\nextern unsigned char %s_drv_data_start[];\n",
+ sysfile);
+ fprintf(outfp, "static unsigned char *drv_data = "
+ "%s_drv_data_start;\n\n", sysfile);
+ bincvt(sysfile, outfile, img, fsize);
+ goto done;
+ }
+
+
fprintf(outfp, "\nextern unsigned char drv_data[];\n\n");
fprintf(outfp, "__asm__(\".data\");\n");
@@ -282,6 +414,7 @@ main(int argc, char *argv[])
done:
fprintf(outfp, "#endif /* NDIS_IMAGE */\n");
+
if (fp != NULL)
fclose(fp);
fclose(outfp);
OpenPOWER on IntegriCloud