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