]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/ndiscvt/ndisgen.sh
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / ndiscvt / ndisgen.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2005
4 #       Bill Paul <wpaul@windriver.com>.  All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 # 3. All advertising materials mentioning features or use of this software
15 #    must display the following acknowledgement:
16 #       This product includes software developed by Bill Paul.
17 # 4. Neither the name of the author nor the names of any co-contributors
18 #    may be used to endorse or promote products derived from this software
19 #    without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
22 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 # ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
25 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 # THE POSSIBILITY OF SUCH DAMAGE.
32 #
33 # $FreeBSD$
34 #
35
36 header () {
37 clear
38 echo "  =================================================================="
39 echo "  ------------------ Windows(r) driver converter -------------------"
40 echo "  =================================================================="
41 echo ""
42 }
43
44 mainmenu() {
45 header
46 echo "  This script is designed to guide you through the process"
47 echo "  of converting a Windows(r) binary driver module and .INF"
48 echo "  specification file into a FreeBSD ELF kernel module for use"
49 echo "  with the NDIS compatibility system."
50 echo ""
51 echo "  The following options are available:"
52 echo ""
53 echo "  1] Learn about the NDIS compatibility system"
54 echo "  2] Convert individual firmware files"
55 echo "  3] Convert driver"
56 echo "  4] Exit"
57 echo ""
58 echo -n "       Enter your selection here and press return: "
59 read KEYPRESS
60 return
61 }
62
63
64 help1 () {
65 header
66 echo "                          General information"
67 echo ""
68 echo "  The NDIS compatibility system is designed to let you use Windows(r)"
69 echo "  binary drivers for networking devices with FreeBSD, in cases where"
70 echo "  a native FreeBSD driver is not available due to hardware manufacturer"
71 echo "  oversight or stupidity. NDIS stands for Network Driver Interface"
72 echo "  Standard, and refers to the programming model used to write Windows(r)"
73 echo "  network drivers. (These are often called \"NDIS miniport\" drivers.)"
74 echo ""
75 echo "  In order to use your network device in NDIS compatibility mode,"
76 echo "  you need the Windows(r) driver that goes with it. Also, the driver"
77 echo "  must be compiled for the same architecture as the release of FreeBSD"
78 echo "  you have installed. At this time, the i386 and amd64 architectures"
79 echo "  are both supported. Note that you cannot use a Windows/i386 driver"
80 echo "  with FreeBSD/amd64: you must obtain a Windows/amd64 driver."
81 echo ""
82 echo -n "       Press return to continue... "
83 read KEYPRESS
84 return
85 }
86
87 help2() {
88 header
89 echo "                          Where to get drivers"
90 echo ""
91 echo "  If you purchased your network card separately from your computer,"
92 echo "  there should have been a driver distribution CD included with the"
93 echo "  card which contains Windows(r) drivers. The NDIS compatibility"
94 echo "  system is designed to emulate the NDIS API of a couple of different"
95 echo "  Windows(r) releases, however it works best with drivers designed"
96 echo "  for NDIS 5.0 or later. Drivers distributed for Windows 2000 should"
97 echo "  work; however, for best results you should use a driver designed"
98 echo "  for Windows XP or Windows Server 2003."
99 echo ""
100 echo "  If your card was supplied with your computer, or is a built-in device,"
101 echo "  drivers may have been included on a special driver bundle CD shipped"
102 echo "  with the computer."
103 echo ""
104 echo "  If you don't have a driver CD, you should be able to find a driver"
105 echo "  kit on the card or computer vendor's web site."
106 echo ""
107 echo -n "       Press return to continue... "
108 read KEYPRESS
109 return
110 }
111
112 help3 () {
113 header
114 echo "                          What files do I need?"
115 echo ""
116 echo "  In most cases, you will need only two files: a .INF file and a .SYS"
117 echo "  file. The .INF file is a text file used by the Windows(r) installer to"
118 echo "  perform the driver installation. It contains information that tells"
119 echo "  the installer what devices the driver supports and what registry keys"
120 echo "  should be created to control driver configuration. The .SYS file"
121 echo "  is the actual driver executable code in Windows(r) Portable Executable"
122 echo "  (PE) format. Note that sometimes the .INF file is supplied in Unicode"
123 echo "  format. Unicode .INF files must be converted to ASCII form with the"
124 echo "  iconv(1) utility before this installer script can use them."
125 echo "  Occasionally, a driver may require firmware or register setup"
126 echo "  files that are external to the main .SYS file. These are provided"
127 echo "  on the same CD with the driver itself, and sometimes have a .BIN"
128 echo "  extension, though they can be named almost anything. You will need"
129 echo "  these additional files to make your device work with the NDIS"
130 echo "  compatibility system as well."
131 echo ""
132 echo -n "       Press return to continue... "
133 read KEYPRESS
134 return
135 }
136
137 help4 () {
138 header
139 echo "                          How does it all work?"
140 echo ""
141 echo "  The installer script uses the ndiscvt(1) utility to convert the .INF,"
142 echo "  .SYS and optional firmware files into a FreeBSD kernel loadable module"
143 echo "  (.ko) file. This module can be loaded via the kldload(8) utility or"
144 echo "  loaded automatically via the /boot/loader.conf file. The ndiscvt(1)"
145 echo "  utility extracts the device ID information and registry key data"
146 echo "  from the .INF file and converts it into a C header file. It also uses"
147 echo "  the objcopy(1) utility to convert the .SYS file and optional firmware"
148 echo "  files into ELF objects. The header file is compiled into a small C"
149 echo "  stub file which contains a small amount of code to interface with"
150 echo "  the FreeBSD module system. This stub is linked together with the"
151 echo "  converted ELF objects to form a FreeBSD kernel module. A static ELF"
152 echo "  object (.o) file is also created. This file can be linked into a"
153 echo "  static kernel image for those who want/need a fully linked kernel"
154 echo "  image (possibly for embedded bootstrap purposes, or just plain old"
155 echo "  experimentation)."
156 echo ""
157 echo -n "       Press return to continue... "
158 read KEYPRESS
159 return
160 }
161
162 help5 () {
163 header
164 echo "                          Prerequisites"
165 echo ""
166 echo "  Converting a driver requires the following utilities:"
167 echo ""
168 echo "  - The FreeBSD C compiler, cc(1) (part of the base install)."
169 echo "  - The FreeBSD linker, ld(1) (part of the base install)."
170 echo "  - The objcopy(1) utility (part of the base install)."
171 echo "  - The ndiscvt(1) utility (part of the base install)."
172 echo ""
173 echo "  If you happen to end up with a .INF file that's in Unicode format,"
174 echo "  then you'll also need:"
175 echo ""
176 echo "  - The iconv(1) utility."
177 echo ""
178 echo "  If you have installed the X Window system or some sort of desktop"
179 echo "  environment, then iconv(1) should already be present. If not, you"
180 echo "  will need to install the libiconv package or port."
181 echo ""
182 echo -n "       Press return to continue... "
183 read KEYPRESS
184 return
185 }
186
187 infconv () {
188 header
189 echo "                  INF file validation"
190
191 if [ -z "$INFPATH" ]; then
192         echo ""
193         echo ""
194         echo "  A .INF file is most often provided as an ASCII file, however"
195         echo "  files with multilanguage support are provided in Unicode format."
196         echo "  Please type in the path to your .INF file now."
197         echo ""
198         echo -n "       > "
199         read INFPATH
200 fi
201
202 if [ ${INFPATH} ] && [ -e ${INFPATH} ]; then 
203         INFTYPE=`${EGREP} -i -c "Signature|.S.i.g.n.a.t.u.r.e" ${INFPATH}`
204         if [ ${INFTYPE} -le 0 ]; then
205                 echo ""
206                 echo "  I don't recognize this file format. It may not be a valid .INF file."
207                 echo ""
208                 echo -n "       Press enter to try again, or ^C to quit. "
209                 read KEYPRESS
210                 INFPATH=""
211                 return
212         fi
213
214         INFTYPE=`${EGREP} -i -c "Class.*=.*Net" ${INFPATH}`
215         if [ ${INFTYPE} -gt 0 ]; then
216                 echo ""
217                 echo "  This .INF file appears to be ASCII."
218                 echo ""
219                 echo -n "       Press return to continue... "
220                 read KEYPRESS
221                 return
222         fi
223
224         INFTYPE=`${EGREP} -i -c ".C.l.a.s.s.*=.*N.e.t" ${INFPATH}`
225         if [ ${INFTYPE} -gt 0 ]; then
226                 echo ""
227                 echo "  This .INF file appears to be Unicode."
228                 if [ -e ${ICONVPATH} ]; then
229                         echo "  Trying to convert to ASCII..."
230                         ${ICONVPATH} -f utf-16 -t utf-8 ${INFPATH} > ${INFFILE}
231                         INFPATH=${INFFILE}
232                         echo "  Done."
233                         echo ""
234                         echo -n "       Press return to continue... "
235                         read KEYPRESS
236                 else
237                         echo "  The iconv(1) utility does not appear to be installed."
238                         echo "  Please install this utility or convert the .INF file"
239                         echo "  to ASCII and run this utility again."
240                         echo ""
241                         exit
242                 fi
243                 return
244         fi
245
246         echo ""
247         echo "  I don't recognize this file format. It may not be a valid .INF file."
248         echo ""
249         echo -n "       Press enter to try again, or ^C to quit. "
250         read KEYPRESS
251         INFPATH=""
252 else
253         echo ""
254         echo "  The file '${INFPATH}' was not found."
255         echo ""
256         echo -n "       Press enter to try again, or ^C to quit. "
257         read KEYPRESS
258         INFPATH=""
259 fi
260 return
261 }
262
263 sysconv() {
264 header
265 echo "                  Driver file validation"
266
267 if [ ! -r "$SYSPATH" ]; then
268         echo ""
269         echo ""
270         echo "  Now you need to specify the name of the Windows(r) driver .SYS"
271         echo "  file for your device. Note that if you are running FreeBSD/amd64,"
272         echo "  then you must provide a driver that has been compiled for the"
273         echo "  64-bit Windows(r) platform. If a 64-bit driver is not available"
274         echo "  for your device, you must install FreeBSD/i386 and use the"
275         echo "  32-bit driver instead."
276         echo ""
277         echo "  Please type in the path to the Windows(r) driver .SYS file now."
278         echo ""
279         echo -n "       > "
280         read SYSPATH
281 fi
282
283 if [ ${SYSPATH} ] && [ -e ${SYSPATH} ]; then
284         SYSTYPE=`${FILE} ${SYSPATH}`
285
286         case ${SYSTYPE} in
287         *Windows*)
288                 echo ""
289                 echo "  This .SYS file appears to be in Windows(r) PE format."
290                 echo ""
291                 echo -n "       Press return to continue... "
292                 read KEYPRESS
293                 SYSBASE=`${BASENAME} ${SYSPATH} | ${TR} '.' '_'`
294                 ;;
295         *)
296                 echo ""
297                 echo "  I don't recognize this file format. It may not be a valid .SYS file."
298                 echo ""
299
300                 echo -n "       Press enter to try again, or ^C to quit. "
301                 read KEYPRESS
302                 SYSPATH=""
303                 ;;
304         esac
305 else
306         echo ""
307         echo "  The file '${SYSPATH}' was not found."
308         echo ""
309         echo -n "       Press enter to try again, or ^C to quit. "
310         read KEYPRESS
311         SYSPATH=""
312 fi 
313 return
314 }
315
316 ndiscvt() {
317 header
318 echo "                  Driver file conversion"
319 echo ""
320 echo "  The script will now try to convert the .INF and .SYS files"
321 echo "  using the ndiscvt(1) utility. This utility can handle most"
322 echo "  .INF files; however, occasionally it can fail to parse some files"
323 echo "  due to subtle syntax issues: the .INF syntax is very complex,"
324 echo "  and the Windows(r) parser will sometimes allow files with small"
325 echo "  syntax errors to be processed correctly which ndiscvt(1) will"
326 echo "  not. If the conversion fails, you may have to edit the .INF"
327 echo "  file by hand to remove the offending lines."
328 echo ""
329 echo -n "       Press enter to try converting the files now: "
330 read KEYPRESS
331 if ! ${NDISCVT} -i ${INFPATH} -s ${SYSPATH} -O -o ${DNAME}.h > /dev/null; then
332         echo "CONVERSION FAILED"
333         exit
334 else
335         echo ""
336         echo "  Conversion was successful."
337         echo ""
338         echo -n "       Press enter to continue... "
339         read KEYPRESS
340 fi
341 return
342 }
343
344 firmcvt() {
345         while : ; do
346 header
347 echo "                  Firmware file conversion"
348 echo ""
349 echo "  If your driver uses additional firmware files, please list them"
350 echo "  below. When you're finished, just press enter to continue. (If your"
351 echo "  driver doesn't need any extra firmware files, just press enter"
352 echo "  to move to the next step.)"
353 echo ""
354                 echo -n "       > "
355                 read FIRMPATH
356
357                 if [ ${FIRMPATH} ]; then
358                         if [ ! -e ${FIRMPATH} ]; then
359                                 echo ""
360                                 echo "  The file '${FIRMPATH}' was not found"
361                                 echo ""
362                                 echo -n "       Press enter to try again, or ^C to quit. "
363                                 read KEYPRESS
364                                 continue
365                         fi
366                         if ! ${NDISCVT} -f ${FIRMPATH} > /dev/null; then
367                                 echo ""
368                                 echo "CONVERSION FAILED"
369                         else
370                                 echo ""
371                                 echo "  Conversion was successful."
372                                 echo ""
373                                 FRMBASE=`${BASENAME} ${FIRMPATH}`
374                                 FRMBASE="${FRMBASE}.o"
375                                 FRMLIST="${FRMLIST} ${FRMBASE}"
376                         fi
377                         echo -n "       Press enter to continue... "
378                         read KEYPRESS
379                 else
380                         break
381                 fi
382         done
383
384 header
385 echo ""
386 echo "  List of files converted firmware files:"
387 echo ""
388 for i in ${FRMLIST}
389 do
390         echo "  "$i
391 done
392 echo ""
393 echo -n "       Press enter to continue... "
394 read KEYPRESS
395 return
396 }
397
398 drvgen () {
399 header
400 echo "                  Kernel module generation"
401 echo ""
402 echo ""
403 echo "  The script will now try to generate the kernel driver module."
404 echo "  This is the last step. Once this module is generated, you should"
405 echo "  be able to load it just like any other FreeBSD driver module."
406 echo ""
407 echo "  Press enter to compile the stub module and generate the driver"
408 echo -n "       module now: "
409 read KEYPRESS
410 echo ""
411 echo -n "       Generating Makefile... "
412 echo ".PATH:  ${PWD} ${STUBPATH}"                               >  ${MAKEFILE}
413 echo "KMOD= ${SYSBASE}"                                         >> ${MAKEFILE}
414 echo "SRCS+= ${STUBFILE} ${DNAME}.h bus_if.h device_if.h"       >> ${MAKEFILE}
415 echo "OBJS+=${FRMLIST} ${DNAME}.o"                              >> ${MAKEFILE}
416 echo "CFLAGS+=  \\"                                             >> ${MAKEFILE}
417 echo "  -DDRV_DATA_START=ndis_${SYSBASE}_drv_data_start \\"             >> ${MAKEFILE}
418 echo "  -DDRV_NAME=ndis_${SYSBASE} \\"                          >> ${MAKEFILE}
419 echo "  -DDRV_DATA_END=ndis_${SYSBASE}_drv_data_end"                    >> ${MAKEFILE}
420 echo "CLEANFILES+=      \\"                                     >> ${MAKEFILE}
421 echo "  ${INFFILE} \\"                                          >> ${MAKEFILE}
422 echo "  ${DNAME}.h \\"                                          >> ${MAKEFILE}
423 echo "  ${DNAME}.o"                                             >> ${MAKEFILE}
424 echo ".include <bsd.kmod.mk>"                                   >> ${MAKEFILE}
425 if [ -f ${MAKEFILE} ]; then
426         echo "done."
427 else
428         echo "generating Makefile failed. Exiting."
429         echo ""
430         exit
431 fi
432 echo -n "       Building kernel module... "
433 echo "" > bus_if.h
434 echo "" > device_if.h
435 if ! ${MAKE} -f ${MAKEFILE} depend > /dev/null; then
436         echo "build failed. Exiting."
437         echo ""
438         exit
439 fi
440 if ! ${MAKE} -f ${MAKEFILE} all > /dev/null; then
441         echo "build failed. Exiting."
442         echo ""
443         exit
444 else
445         if [ -f ${SYSBASE}.ko ]; then
446                 ${MV} ${SYSBASE}.ko ${SYSBASE}.kmod
447                 echo "done."
448         else
449                 echo "build failed. Exiting."
450                 echo ""
451                 exit
452         fi
453 fi
454 echo -n "       Cleaning up... "
455 if ! ${MAKE} -f ${MAKEFILE} clean cleandepend > /dev/null; then
456         echo "cleanup failed. Exiting."
457         echo ""
458         exit
459 else
460         echo "done."
461 fi
462 ${RM} ${MAKEFILE}
463 ${MV} ${SYSBASE}.kmod ${SYSBASE}.ko
464 echo ""
465 echo "  The file ${SYSBASE}.ko has been successfully generated."
466 echo "  You can kldload this module to get started."
467 echo ""
468 echo -n "       Press return to exit. "
469 read KEYPRESS
470 echo ""
471 echo ""
472 return
473 }
474
475 convert_driver () {
476         while : ; do
477                 infconv
478                 if [ ${INFPATH} ]; then
479                         break
480                 fi
481         done
482
483         while : ; do
484                 sysconv
485                 if [ ${SYSPATH} ]; then
486                         break
487                 fi
488         done
489
490         ndiscvt
491         firmcvt
492         drvgen
493         return
494 }
495
496 ICONVPATH=/usr/local/bin/iconv
497 NDISCVT=/usr/sbin/ndiscvt
498 STUBPATH=/usr/share/misc
499 STUBFILE=windrv_stub.c
500 DNAME=windrv
501 CP=/bin/cp
502 MV=/bin/mv
503 RM=/bin/rm
504 TR=/usr/bin/tr
505 FILE=/usr/bin/file
506 EGREP=/usr/bin/egrep
507 MAKE=/usr/bin/make
508 BASENAME=/usr/bin/basename
509 TOUCH=/usr/bin/touch
510 MKTEMP=/usr/bin/mktemp
511
512 MAKEFILE=`${MKTEMP} /tmp/Makefile.XXXXXX`
513 INFFILE=`${MKTEMP} /tmp/ascii_inf.XXXXXX`
514
515 INFPATH=""
516 FRMLIST=""
517 SYSPATH=""
518 SYSBASE=""
519 FRMBASE=""
520
521 if [ -r "$1" -a -r "$2" ]; then
522         # Looks like the user supplied .INF and .SYS files on the command line
523         INFPATH=$1
524         SYSPATH=$2
525         convert_driver && exit 0
526 fi
527
528 while : ; do
529         mainmenu
530         case ${KEYPRESS} in
531         1)
532                 help1
533                 help2
534                 help3
535                 help4
536                 help5
537                 ;;
538         2)
539                 firmcvt
540                 ;;
541         3)
542                 convert_driver
543                 ;;
544         4)
545                 header
546                 echo ""
547                 echo "  Be seeing you!"
548                 echo ""
549                 exit
550                 ;;
551         *)
552                 header
553                 echo ""
554                 echo -n "       Sorry, I didn't understand that. Press enter to try again: "
555                 read KEYPRESS
556                 ;;
557         esac
558 done
559 exit