diff options
-rw-r--r-- | sys/compat/ndis/hal_var.h | 8 | ||||
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 23 | ||||
-rw-r--r-- | sys/compat/ndis/ndis_var.h | 5 | ||||
-rw-r--r-- | sys/compat/ndis/ntoskrnl_var.h | 4 | ||||
-rw-r--r-- | sys/compat/ndis/pe_var.h | 41 | ||||
-rw-r--r-- | sys/compat/ndis/subr_hal.c | 33 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 139 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 139 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/ndiscvt.8 | 122 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/ndiscvt.c | 155 |
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); |