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