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 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" 190 191if [ -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 200fi 201 202if [ ${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="" 252else 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="" 259fi 260return 261} 262 263sysconv() { 264header 265echo " Driver file validation" 266 267if [ ! -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 281fi 282 283if [ ${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 305else 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="" 312fi 313return 314} 315 316ndiscvt() { 317header 318echo " Driver file conversion" 319echo "" 320echo " The script will now try to convert the .INF and .SYS files" 321echo " using the ndiscvt(1) utility. This utility can handle most" 322echo " .INF files; however, occasionally it can fail to parse some files" 323echo " due to subtle syntax issues: the .INF syntax is very complex," 324echo " and the Windows(r) parser will sometimes allow files with small" 325echo " syntax errors to be processed correctly which ndiscvt(1) will" 326echo " not. If the conversion fails, you may have to edit the .INF" 327echo " file by hand to remove the offending lines." 328echo "" 329echo -n " Press enter to try converting the files now: " 330read KEYPRESS 331if ! ${NDISCVT} -i ${INFPATH} -s ${SYSPATH} -O -o ${DNAME}.h > /dev/null; then 332 echo "CONVERSION FAILED" 333 exit 334else 335 echo "" 336 echo " Conversion was successful." 337 echo "" 338 echo -n " Press enter to continue... " 339 read KEYPRESS 340fi 341return 342} 343 344firmcvt() { 345 while : ; do 346header 347echo " Firmware file conversion" 348echo "" 349echo " If your driver uses additional firmware files, please list them" 350echo " below. When you're finished, just press enter to continue. (If your" 351echo " driver doesn't need any extra firmware files, just press enter" 352echo " to move to the next step.)" 353echo "" 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 384header 385echo "" 386echo " List of files converted firmware files:" 387echo "" 388for i in ${FRMLIST} 389do 390 echo " "$i 391done 392echo "" 393echo -n " Press enter to continue... " 394read KEYPRESS 395return 396} 397 398drvgen () { 399header 400echo " Kernel module generation" 401echo "" 402echo "" 403echo " The script will now try to generate the kernel driver module." 404echo " This is the last step. Once this module is generated, you should" 405echo " be able to load it just like any other FreeBSD driver module." 406echo "" 407echo " Press enter to compile the stub module and generate the driver" 408echo -n " module now: " 409read KEYPRESS 410echo "" 411echo -n " Generating Makefile... " 412echo ".PATH: ${PWD} ${STUBPATH}" > ${MAKEFILE} 413echo "KMOD= ${SYSBASE}" >> ${MAKEFILE} 414echo "SRCS+= ${STUBFILE} ${DNAME}.h bus_if.h device_if.h" >> ${MAKEFILE} 415echo "OBJS+=${FRMLIST} ${DNAME}.o" >> ${MAKEFILE} 416echo "CFLAGS+= \\" >> ${MAKEFILE} 417echo " -DDRV_DATA_START=ndis_${SYSBASE}_drv_data_start \\" >> ${MAKEFILE} 418echo " -DDRV_NAME=ndis_${SYSBASE} \\" >> ${MAKEFILE} 419echo " -DDRV_DATA_END=ndis_${SYSBASE}_drv_data_end" >> ${MAKEFILE} 420echo "CLEANFILES+= \\" >> ${MAKEFILE} 421echo " ${INFFILE} \\" >> ${MAKEFILE} 422echo " ${DNAME}.h \\" >> ${MAKEFILE} 423echo " ${DNAME}.o" >> ${MAKEFILE} 424echo ".include <bsd.kmod.mk>" >> ${MAKEFILE} 425if [ -f ${MAKEFILE} ]; then 426 echo "done." 427else 428 echo "generating Makefile failed. Exiting." 429 echo "" 430 exit 431fi 432echo -n " Building kernel module... " 433echo "" > bus_if.h 434echo "" > device_if.h 435if ! ${MAKE} -f ${MAKEFILE} depend > /dev/null; then 436 echo "build failed. Exiting." 437 echo "" 438 exit 439fi 440if ! ${MAKE} -f ${MAKEFILE} all > /dev/null; then 441 echo "build failed. Exiting." 442 echo "" 443 exit 444else 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 453fi 454echo -n " Cleaning up... " 455if ! ${MAKE} -f ${MAKEFILE} clean cleandepend > /dev/null; then 456 echo "cleanup failed. Exiting." 457 echo "" 458 exit 459else 460 echo "done." 461fi 462${RM} ${MAKEFILE} 463${MV} ${SYSBASE}.kmod ${SYSBASE}.ko 464echo "" 465echo " The file ${SYSBASE}.ko has been successfully generated." 466echo " You can kldload this module to get started." 467echo "" 468echo -n " Press return to exit. " 469read KEYPRESS 470echo "" 471echo "" 472return 473} 474 475convert_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 496ICONVPATH=/usr/local/bin/iconv 497NDISCVT=/usr/sbin/ndiscvt 498STUBPATH=/usr/share/misc 499STUBFILE=windrv_stub.c 500DNAME=windrv 501CP=/bin/cp 502MV=/bin/mv 503RM=/bin/rm 504TR=/usr/bin/tr 505FILE=/usr/bin/file 506EGREP=/usr/bin/egrep 507MAKE=/usr/bin/make 508BASENAME=/usr/bin/basename 509TOUCH=/usr/bin/touch 510MKTEMP=/usr/bin/mktemp 511 512MAKEFILE=`${MKTEMP} /tmp/Makefile.XXXXXX` 513INFFILE=`${MKTEMP} /tmp/ascii_inf.XXXXXX` 514 515INFPATH="" 516FRMLIST="" 517SYSPATH="" 518SYSBASE="" 519FRMBASE="" 520 521if [ -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 526fi 527 528while : ; 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 558done 559exit 560