!BAT

:: DPMS.bat by chenall and modified by SSi  x86 ONLY (PE option not tested)

:: www.rmprepusb.com

:: WARNING: Do not change or remove any code unless you test with all the TEST CASES below
::          Some code may appear 'unnecessary' but may actually be required!
::          Be aware that there is a wide variety of .ini, .oem and .inf files!!!

:: HISTORY
:: 1.00 2013-07-04 First E2B Upgrade Pack Release SSi - includes correct driver name, Config sections and dual disk auto-load
:: 1.01 2013-07-12 Bugfix for scsi=(none0 if name began with a number, added copy+cat entry for .cpl, .reg, .exe files, 15sec select driver timeout (was 9)
:: 1.02 2014-01-04 FORCEFIRA code portion (if / i "%def%" == "firadisk") removed
:: 1.03 2014-03-20 Tweaked to cope with new Driverpack INI format
:: 1.04 2014-04-01 New chkpci, now only picks xp/2k/2k3 driver
:: 1.05 2014-04-06 Support for winnt.sif and winnt.sif.cmd

:: Function: To make an F6 XP driver floppy in memory to match the current hardware
:: Action:   Get MassStorage PCI ID, find all INF/SYS/CAT files, make txtsetup.oem file - copy all to virtual floppy disk in memory

:: Note: if more than one OEM + one RAM driver is required, the user MUST press F6 and add each one manually
::       it is NOT POSSIBLE to add multiple drivers automatically via txtsetup.oem!!!!

:: Usage /DPMS.bat 0   - (fd0) = OEM F6 floppy
::       /DPMS.bat 1   - (fd1) = OEM F6 floppy 
::       /DPMS.bat 2   - (fd1) = OEM F6 floppy - (fd0) blank (if no FIRA)
::       /DPMS.bat     -  same as DPMS 2

:: Typical usage: set FIRA=2 ;; call DPMS.bat
:: This will make 1 or two floppies - fd0 will be the firadisk default driver, fd1 will be the OEM driver (if any)

:: If no OEM driver:
:: If %FIRA% = 1 then adds firadisk32 as fd0 if "0" param used or fd1 if "1" param used
:: if %FIRA% = 2 then adds firadisk32(default)+winvblock32 as fd0 if "0" param used or fd1 if "1" param used
:: if %FIRA% = 3 then as FIRA=2 but default ramdisk driver will be wvblk32

:: %OSTYPE% = xp or 2k or 2k3  - only finds driver for that OST%

:: When using FIRA + OEM, both disks are identical, only default driver in txtsetup.oem is different.

:: Examples
::     FIRA=1 DPMS2.bat 2
::     If OEM PCI driver found  fd0=default=firadisk fd1=default=OEM
::     If no OEM driver found   fd0=default=firadisk
::
::     FIRA=1 DPMS2.bat 1
::     If OEM PCI driver found  fd0=none             fd1=default=OEM  (fd1=fd0)
::     If no OEM driver found   fd0=default=firadisk fd1=default=firadisk
::
::     FIRA=1 DPMS2.bat 0
::     If OEM PCI driver found  fd0=default=OEM      fd1 not present
::     If no OEM driver found   fd0=default=firadisk fd1 not present
::
::     FIRA=3 DPMS2.bat 2
::     If OEM PCI driver found  fd0=default=firadisk fd1=default=OEM
::     If no OEM driver found   fd0=default=firadisk fd1=WinVBlk

:: TXTSETUP.OEM FORMAT
:: ====================
:: [Defaults]            scsi= ID
:: [scsi]                ID = "description"
:: [Files.scsi.ID]       driver=disk,filename, SERVICE name used for other sections,   inf=disk,filename   catalog=dsk.filename
:: [Config.DEVICEKEY]   (DEVICEKEY name is taken from driver=<disk>,<DRIVERFILENAME.sys>,<DEVICEKEY> line)    value=subkeyname,valuename, valuetype, value
:: [HardwareIDs.scsi.ID] must be present for automatic installation  id = "<DEVICEID>" , "<DRIVERFILENAME>"  (DEVICEID must match description in INF file)
::                       DRIVERFILENAME must match filename of driver e.g. iastor7 and iastor7.sys
:: Note: any file specified in a dll= and Catalog= line will just be copied to the hard disk during text-mode setup (this can be driver files)

setlocal
debug off
checkrange 20130521:-1 read 0x8278 || echo Please use grub4dos-0.4.5c-2013-05-21 or above! && exit 1
root %~dp0
if exist %~dp0DRIVERPACK.INI && goto :DPMS_START


:dpms.iso
if /i "%~nx1"=="dpms.iso" && shift 1 && root %~dp1
map /DPMS.ISO (0xdf) || map --mem /DPMS.ISO (0xdf)
map --hook
root (0xdf)
if exist (0xdf)/DRIVERPACK.INI && goto :DPMS_START
map --unmap=0xdf
map --rehook
exit 1


:DPMS_START
:: clear all variables but keep FIRA and debug switch
set * && set FIRA=%FIRA% && set DD=%DD% && set TESTCASE=%TESTCASE% && set OSTYPE=%OSTYPE% && set WINNT=%WINNT%

if /i "%1"=="pe" set WINPE=1 && shift 1 ! if /i "%2"=="pe" set WINPE=1
clear
::setcursor
call Fn.5 0 2
echo $[0102]DPMS2: Auto-detect SCSI/RAID/SATA Drivers [chenall & SSi] 2014-04-01

insmod FAT
insmod INIFILE
map --floppies=2
map --unmap=0,1 && map --rehook

:: make 2.88MB floppy as device (8)
:: Note: 'fat mkfs (8)'  makes a FAT16 disk with 63 hds and 255 spt!
map --mem (md)+5760 (8)
map --hook
:: initialize memory area as write (8) won't work for some strange reason!
echo -e \0\0\0\0\0\0\0\0\0\0\0\0 > (8)+40
write (8)+1 \xeb\xfe
:: bugfix for chenall's patch  = 0x90 - should be \x09 or \9!
write --offset=0xc   (8) \2\2\1\0\2\xf0\0\x80\x16\xf0\x09\0\x24\0\2
write --offset=0x26  (8)+1 \x29DPMSchenall.netFAT12
write --offset=0x1fe (8)+2 \x55\xAA\xf0\xff\xff

fat mkfile size=8192 (8)/chkpci.pci
:: 2011 version of chkpci has -u switch, searches through ini file for PCI IDs which match hardware we are on
:: 2014 version has -w switch for OS type
set OT=
::echo OSTYPE=%OSTYPE% FIRA=%FIRA%
if not "%OSTYPE%"=="" set OT=-w:%OSTYPE%
if not "%OSTYPE%"=="xp" goto :chk
if not "%OSTYPE%"=="2k" goto :chk
if not "%OSTYPE%"=="2k3" goto :chk
set OT=
:chk
if not "%OT%"=="" echo -e $[0102]Looking for %OSTYPE% drivers only...
CHKPCI %OT% -u /DRIVERPACK.INI > (8)/chkpci.pci
::echo Using command: CHKPCI %OT% -u /DRIVERPACK.INI
set OT=



:: ------------------ TEST CASES (uncomment one line to force a specific ID) -----
:: M4 has 64 in name
::set TESTCASE="PCI\VEN_11AB&DEV_6440"="mv64xx" ; D/M/M4 "mv64xx.sys" "Marvell 64xx/63xx SAS"
::: I7 ****  FORCE ICH7
::set TESTCASE="PCI\VEN_8086&DEV_3B29&CC_0106"="iastor7" ; D/M/I7 "iastor7.sys" "Intel ICH7"
:: I4  ***** FORCE I4 (multiple Config lines)
::set TESTCASE="PCI\VEN_8086&DEV_1D02&CC_0106"="iastorA" ; D/M/I4 "iastorA.sys" "Intel C60"
:: I4a ***** FORCE I4 (multiple Config lines)
::set TESTCASE="PCI\VEN_8086&DEV_1D60&CC_0106"="iastorS" ; D/M/I4 "iastorS.sys" "Intel C60 SATA MODE"
:: *** NO OEM DRIVER **
::set TESTCASE=NONE
:: V   VMWARE SCSI with [Config.VMSCSI] section (note: PCI ID is not in txtsetup.oem!)
::set TESTCASE="PCI\VEN_104B&DEV_1040"="VMSCSI" ; D/M/V "VMSCSI.sys" "VMWARE SCSI"
:: IT2 with two config lines
::set TESTCASE="PCI\VEN_1283&DEV_8212"="ITEATAPI" ; D/M/IT "iteatapi.sys" "ITE IT8211 ATA ATAPI"
:: AM8
::set TESTCASE="PCI\VEN_1022&DEV_7801&CC_0106"="ahcix80x"    ; D/M/AM8 "ahcix868.sys" "AMD AHCI Compatible RAID SB8xx (WXP)"
:: SS
::set TESTCASE="PCI\VEN_1039&DEV_1182"="SISRAID2" ; D/M/SS "SISRAID2.sys" "SIS 182/1182 RAID"
:: AS  (contains dll_
::set TESTCASE="PCI\VEN_1B21&DEV_0602"="asahxp32" ; D/M/AS "asahxp32.sys" "Asmedia 106x SATA Controller"
:: S1 (contains dll= and Note)
::set TESTCASE="PCI\VEN_1095&DEV_0680&SUBSYS_36801095"="pnp680r" ; D/M/S1 "pnp680r.sys" "Silicon Image 0680 Ultra-133 Medley ATA Raid"
:: L  (has txtsetup(xxxx).oem instead of txtsetup.oem!)
::set TESTCASE="PCI\VEN_1000&DEV_0030"="symmpiv" ; D/M/L "symmpi.sys" "LSI Logic SAS 3000/VMware v10 (WXP)"


if exist TESTCASE echo -e $[0104]TESTCASE OVERRIDE = %TESTCASE%
if exist TESTCASE echo -n && echo -e %TESTCASE% > (8)/chkpci.pci
 
:: ---------- END OF TEST SECTION -------


cat --hex --length=1 (8)/chkpci.pci | set a=
set a=%a:~10,2%
if "%a%"=="00" echo $[0104]*** INFO: NO MATCHING PCI IDs IN DRIVERPACK.INI FILE. ***

:: (md)0x300 has content for txtsetup.oem file
echo -n -e \0\0\0\0\0\0\0\0\0\0\0\0\0\0 > (md)0x300+8
:: start section for the driver
echo [Disks] >> (md)0x300+8
echo d1="DPMS F6 Installation Disk by Chenall & Steve6375 (diskx)",\diskx,\  >> (md)0x300+8

:: -- GET PCI DRIVER ---

set pci.max=0
set skip=0
call :find_pci

:: 1=PCI\VEN_8086&DEV_2829&CC_0106  2=iastor3 3=; 4=D/M/I3 5=iastor3.sys 6=<description>
if exist FIRA if %FIRA%>=1 call :chkpci PCI\firadisk firadisk ; FIRA firadisk.sys "FiraDisk Driver (32-bit)"
if exist FIRA if %FIRA%>=2 call :chkpci ROOT\WINVBLOCK WinVBlock ; WINV wvblk32.sys "WinVBlock Driver (32-bit)"

if exist (0xd1)+1 && map --unmap=0xd1 && map --rehook
::if %pci.max%==0 && goto :NoDriver

echo
echo $[0102]NT5_x86-32-bit Drivers from DPMS (driverpack.net)




call :fd_%1 %1

if "%DD%"=="1" echo -e \nfd0\n---
if "%DD%"=="1" ls (0)/ > nul && ls (0)/ ! if "%DD%"=="1"  echo -e \x20(none)
if "%DD%"=="1" echo -e \nfd1\n---
if "%DD%"=="1" ls (1)/ > nul && ls (1)/ ! if "%DD%"=="1" echo -e \x20(none)
if "%DD%"=="1" echo -e \n

::unmap 8 and 0xdf
map --unmap=8,0xdf
map --rehook
endlocal

:: Take a backup
errorcheck off
debug off
if exist %~dp0oem0.txt cat (0)/txtsetup.oem > %~dp0oem0.txt ! echo -e \0\0 > %~dp0oem0.txt
if exist %~dp0oem1.txt cat (1)/txtsetup.oem > %~dp0oem1.txt ! echo -e \0\0 > %~dp0oem1.txt
if exist %~dp0dir0.txt ls (0)/ > %~dp0dir0.txt ! echo -e \0\0 > %~dp0dir0.txt
if exist %~dp0dir1.txt ls (1)/ > %~dp0dir1.txt ! echo -e \0\0 > %~dp0dir1.txt
errorcheck on

:: remove modules from memory
delmod fat > nul
delmod inifile > nul

goto :eof



:: ---------------------------------  END Of MAIN ROUTINE -------------------------------------------




:: ------ FLOPPY 0/1 ------

:fd_0
:fd_1
:: %1 has 0 or 1
set def=1
set max=%pci.max%

:: if we just have firadisk and winvblock then don't ask as will be forced to winvblock
if "%FIRA%"=="3" if %pci.max%==2 goto :mm0
if "%FIRA%"=="2" if %pci.max%<=2 goto :mm0
:: if more than 1 driver ask (default is OEM driver)
if %max%>=2 call :sel_driver
:: %1 is pci name e.g. %pci.1%=iastor3 , %2 is floppy device number - e.g. 1
:mm0
call :make_oem %def% %1 1
exit

:: ------ FLOPPY _/2 ------

:fd_
:fd_2
if "%DD%"=="1" echo PCI.MAX=%pci.max%
set def=1
set max=%pci.max%
if "%FIRA%"=="1" set /a max=%pci.max%-1
if "%FIRA%"=="2" set /a max=%pci.max%-2
if "%FIRA%"=="3" set /a max=%pci.max%-2

:: if two or more OEM drivers - choose a default, %max% has the max range
if %max%>=2 call  :sel_driver

:: %1 is pci name e.g. %pci.1%=iastor3 , %2 is floppy device number - e.g. 1  %3 is number of floppies to make
::echo def=%def%
call :make_oem %def% 1 2
if %pci.max%==1 && goto :BLANK_FD0

:: disk 1 must be either firadisk or winvblock
if "%FIRA%">="1" set FORCEFIRA=1
:: default is driver 2 but may be overridden with firadisk/winvblock
call :make_oem 2 0 2
exit


:: ------ SELECT DRIVER ------

:sel_driver
echo -e -n \t\tPlease select a default driver [timeout=%pci.1%] (1-%max%): \r
pause --wait=15
if %@retval%==1 && set def=1 ! set /a def=%@retval%-48
:: if ENTER is hit (13-48), set def as 1
if %def%==-35 set def=1
checkrange 1:%max% calc %def% || goto %0
call set g=%^pci.%def%%%
echo -e -n \t \x20                                                                    \x20\r
exit


:: ------------------------ FIND_PCI  ------------------------

:find_pci
::Go though found PCI devices and call chkpci for each one
:: even if no pci ID, call chkpci once to get the winvblk/fira drivers
cat --locate=\n --skip=%skip% --number=1 (8)/chkpci.pci > nul || call :chkpci && exit
set /a len=%?%-%skip%
cat --skip=%skip% --length=%len% (8)/chkpci.pci | call :chkpci=
set /a skip=%skip%+1+%len%
set len=
goto :find_pci


:: ------ NO DRIVER FOUND ------

:NoDriver
echo $[0104] No driver found
:Err_quit
map --unmap=8,0xdf
map --rehook
pause --wait=2
exit 1

:: --------------------- CHKPCI ------

:chkpci

:: 1="PCI\VEN_8086&DEV_3B29&CC_0106" 2="iastor7" 3=; 4=D/M/I7 5="iastor7.sys" 6="Intel ICH7"

:: Note: %6 already has quotes - do not enclose with more quotes or it doesn't work!
call Fn.11 %6 "WXP" && goto :chkp
call Fn.11 "%6" "WXP" && goto :chkp
:: If DriverPack.ini file description has not WXP and has W2K/W2K3 then skip it
call Fn.11 %6 "W2K" && exit
call Fn.11 "%6" "W2K" && exit
:: lower case in some INI files too!
call Fn.11 %6 "w2k" && exit
call Fn.11 "%6" "w2k" && exit
:chkp

setlocal
if not "%3"==";" && exit


::NOTE: to ensure no quote marks use %~ instead of %

if "%DD%">="2" echo chkpci: 1=%1 2=%2 3=%3 4=%4 5=%5 6=%6

:: replace - with / for new INI file syntax - e.g. [I-5] means I/5
echo -e !BAT\nset a=%~4 > (md)0x320+1
cat --locate=- --replace=/ (md)0x320+1 > nul
call (md)0x320+1 > nul
::set /u root=%~4
set /u root=%a%

if "%DD%"=="1" echo ROOT IS %root%
root %@root%/%root%
set /u sysfile=/%~5
if not exist (8)/%sysfile% && echo -n -e Copying %~5,\x20 && fat copy %sysfile% (8) > nul || echo -e $[0104] \nERROR: DRIVERPACK.INI: Could not find %root%/%~5 && pause
echo -e \r\n[scsi] >> (md)0x300+8
echo %~2=%6 >> (md)0x300+8

:: --- [HardwareIds.scsi.xxx section ---

echo -e \r\n[HardwareIds.scsi.%~2] >> (md)0x300+8
echo -n %~1 > (md)0x200+2
set /a p_hwid=0x40000

:: the service name MUST match the driver name 
:: set SERVICE name to 12345678 for now - must change this later to match the driver xx.sys name!
call :addids 12345678#####

:: must set ID for driver= line as was not PCI device so it doesn't have one!
if /i "%2"=="WINVBLOCK" set id=wvblk32.sys
if /i "%1"=="FIRADISK" set id=firadisk.sys


:: --- [Files.scsi.xxx section -----

echo -e \r\n[Files.scsi.%~2] >> (md)0x300+8

:: SYSx will hold the name of any driver.sys files we find in the /D/M/xxx driver folder
set SYS=
set SYS1=
set SYS2=
set SYS3=
set CONF=
:: DNAME is driver name from DriverPack INI - e.g. iastor3
set DNAME=%2
:: search all INF find in driver folder - look for %id% PCI match, copy any files mentioned, make inf/catalog/driver entries
if not exist WINPE ls | call :check_inf=

if exist (8)/%~5 set DPSYS=%~5 && goto :skpsys





:: ---- NEEDED ???????

echo -e $[0104] DP.INI SYS FILE NOT IN %root%

:: INF file may have had iastor.sys and DriverPack.ini may have had iastor7.sys  !!!!
call Fn.0 %~5 | set DPSYS=
:: Use driver in inf file if only just one and sys file was copied to floppy
if "%SYS1%%%SYS2%%%SYS3%"=="" if exist (8)/%SYS% set DPSYS=%SYS%
:: make sure the file exists (it should!)
if exist (8)/%~5    if not exist (8)/%DPSYS% set DPSYS=%~5
if exist (8)/%SYS%  if not exist (8)/%DPSYS% set DPSYS=%SYS%
if exist (8)/%SYS1% if not exist (8)/%DPSYS% set DPSYS=%SYS1%
if exist (8)/%SYS2% if not exist (8)/%DPSYS% set DPSYS=%SYS2%
if exist (8)/%SYS3% if not exist (8)/%DPSYS% set DPSYS=%SYS3%

:: if there was just one driver.sys file in the INF file then that must be the right one!
if "%SYS1%%%SYS2%%%SYS3%"=="" goto :skpsys

:: DPSYS has best guess - see if same as one of the driver files in the DP INI file
if /i "%~5"=="%DPSYS%" goto :skpsys
if /i "%~5"=="%SYS%"  set DPSYS=%SYS% && goto :skpsys
if /i "%~5"=="%SYS1%" set DPSYS=%SYS1% && goto :skpsys
if /i "%~5"=="%SYS2%" set DPSYS=%SYS2% && goto :skpsys
if /i "%~5"=="%SYS3%" set DPSYS=%SYS3% && goto :skpsys

echo $[0104]***   WARNING: Multiple drivers found in INF file(s) for %2 (%~5)!   ***
:cs
if exist SYS  echo -e $[0104]\x20        1     = %SYS%
if exist SYS1 echo -e $[0104]\x20        2     = %SYS1%
if exist SYS2 echo -e $[0104]\x20        3     = %SYS2%
if exist SYS3 echo -e $[0104]\x20        4     = %SYS3%
set a=1
set /p ask= Which is the correct driver for this device : 
set /a ask=%ask%-1 > nul
if "%ask%"<="0" set ask=
call set a=%^SYS%ask%%%
if not "%a%"=="" set DPSYS=%a% || goto :cs
echo
set a=
set ask=





:skpsys
::id="PCI\cccc","iastor7" 
::Service name must match driver name e.g. id="PCI\cccc","iastor7"  = isator7.sys
::Replace "12345678" with "driver" - name is max of 8 characters as drivers cannot exceed 8.3

if "%DD%"=="1" echo :skpsys DPSYS=%DPSYS%
:: chop to 8 characters and remove any quotes
call Fn.0 0 %DPSYS:~0,8%. | set svc=
:: find . if any
call Fn.11 "%svc%." "." 
set l=%@retval%
:: find end of string
call Fn.11 "%svc%!" "!"
:: get number of characters from . to end
set /a l=%@retval%-%l%
:: trim the string so we just have the driver name
call set drvname=%svc:~0,-%l%%%
call set svc=%svc:~0,-%l%%%
if "%DD%"=="1" echo svc=[%svc%]
cat --locate=12345678 --replace=%svc%\x22\r\n; (md)0x300+8

:: add driver
echo driver=d1,%DPSYS%,%~2 >> (md)0x300+8

:: --- Catalogue - make sure the driver files are copied to HDD by Setup ------

if "%DD%"=="1" echo DPSYS=%DPSYS% SYS=%SYS% SYS1=%SYS1% SYS2=%SYS2% SYS3=%SYS3% DPDRIVER=%~5
:: Make sure all sys files are copied over to the hard disk by Setup by using a catalog entry!
if not "%SYS%"==""   if /i not "%SYS%"=="%DPSYS%"  if exist /%SYS%   echo catalog=d1,%SYS% >> (md)0x300+8
if not "%SYS1%"==""  if /i not "%SYS1%"=="%DPSYS%" if exist /%SYS1%  echo catalog=d1,%SYS1% >> (md)0x300+8
if not "%SYS2%"==""  if /i not "%SYS2%"=="%DPSYS%" if exist /%SYS2%  echo catalog=d1,%SYS2% >> (md)0x300+8
if not "%SYS3%"==""  if /i not "%SYS3%"=="%DPSYS%" if exist /%SYS3%  echo catalog=d1,%SYS3% >> (md)0x300+8
if not "%DPSYS%"=="" if exist /%DPSYS% echo catalog=d1,%DPSYS% >> (md)0x300+8
if not "%~5"=="" if /i not "%~5"=="%DPSYS%" if exist /%~5 echo catalog=d1,%~5 >> (md)0x300+8

::Special Bodge for FiraDisk - add cmd and devcon so removes driver after XP install completes
if /i "%DPSYS%"=="firadisk.sys" if exist /devcon.exe echo catalog=d1,devcon.exe >> (md)0x300+8 && if not exist (8)/devcon.exe fat copy /devcon.exe (8) > nul | echo -n 
if /i "%DPSYS%"=="firadisk.sys" if exist /firadisk.cmd echo catalog=d1,firadisk.cmd >> (md)0x300+8 && if not exist (8)/firadisk.cmd fat copy /firadisk.cmd (8) > nul | echo -n 


:: if WINNT specified, copy it over
if not exist WINNT goto :skpsif
errorcheck off
if not exist (8)/%WINNT% fat copy ()/_ISO/WINDOWS/XP/%WINNT% (8)
if not exist (8)/WINNT.SIF fat ren (8)/%WINNT% WINNT.SIF
:: see if a winnt.sif.cmd file exists which will run at end of Setup GUI stage
if exist ()/_ISO/WINDOWS/XP/%WINNT%.cmd cat ()/_ISO/WINDOWS/XP/%WINNT%.cmd > ()/_ISO/e2b/firadisk/RUNXP.cmd
::ls (8)/
set FNM=
:skpsif

:: --- [Config.xxx section ------

:: Now do [CONFIG.xxx] section if there was one
if "%CONF%"=="" goto :skipcfg
echo -e \r\n[Config.%~2] >> (md)0x300+8
cat (md)0x1D999+3 >> (md)0x300+8
:skipcfg

:chkpci_winpe
endlocal && set /a pci.max=%pci.max%+1 && set DPSYS=%DPSYS%

echo $[0106]  DRIVER %pci.max%  $[0107]= %~1 $[0105]Name=%~2 
echo $[0105]  Location=/%4 $[0107]Driver=%DPSYS% (DPackName=%~5)
echo $[0105]  Description=%6
set pci.%pci.max%=%~2

exit


:: -------------- ADD_IDS ----------------

:addids

:: %p_hwid% has PCI\VEN_8086&DEV_2829&&CC_0106  for example

::call func strtok  - look for first value deliited by comma
call Fn.13 %p_hwid% ","

call Fn.0 0 "id="%s","%1"" %p_hwid% | echo >> (md)0x300+8
call Fn.0 0 %p_hwid% | set id=
:: BUGFIX SSi - was 4,16 - cut off last digit but 17 characters is too long for cat command
:: was VEN_8086&DEV_282   now EN_8086&DEV2829 
:: set id=%id:~4,16%  ERROR
set id=%id:~5,16%

:addins_next
:: look for next value delimited by comma
call Fn.13 0 "," || exit
call Fn.0 0 "id="%s","%1"" %@retval% | echo >> (md)0x300+8
goto :addins_next

:: ------ BLANK_FD0 ------

:BLANK_FD0
echo -n λώ > (md)0x200+2
write --offset=0xb (md)0x200+3 \x00\x02\x01\x01\x00\x01\x70\x00\x10\x00\xfd\x01\x00\x08\x00\x01
write 0x401FE 0xAA55
write 0x40200 0xfffffe
map --mem (md)0x200+2 (fd0)
exit

:: ---------------------- CHECK_INF ------------------------------------------

:: Requires %id% to be set the the PCI ID of the device.

:check_inf
:: COPY ALL SYS FILES AND CAT FILES mentioned in any INF file with matching ID
shift
if "%DD%"=="1" echo check_inf: %0 
if "%~0"=="" exit
if /i "%~x0"==".oem" call :check_oem %0
if /i "%~x0"==".inf" || goto :check_inf
:: If we have an INF file look for PCI ID
if "%DD%"=="1" echo Checking %~0 for %id%
cat --locatei=%id% --number=1 /%0 > nul || goto :check_inf
echo -n Found %~nx0 and copying 
:: We have INF file with our PCI ID in it

:: Copy all the sys files mentioned in INF - try to avoid duplicate INF entries
set PREVINF=
inifile /%0 [SourceDisksFiles] | call :copyfiles= 
inifile /%0 [SourceDisksFiles.x86] | call :copyfiles=
::inifile /%0  [SourceDisksFiles.amd64] | call :copyfiles=

:: copy all cat files
inifile /%0 [Version] CatalogFile | call :copyfiles %0= 
inifile /%0 [Version] CatalogFile.NTx86 | call :copyfiles %0=
::inifile /%0 [Version] CatalogFile.NTamd64 | call :copyfiles %0=
echo
:: go through all the files...
goto :check_inf



:: ----------- CHECK_OEM ------------------

:check_oem
:: check txtsetup.oem in the DPMS drivers folder for [Config.xxx] section
:: get value lines from [Config section
if "%DD%">="2" echo AT CHECK_OEM %1 DNAME=%DNAME%
:: in our txtsetup.oem, the driver=d1,xxxxx.sys,DriverKey  must match with the [Confif.DriverKey] name

:: clear memory areas we are going to use as temp storage
echo -e \x20\x20\x20\x20\x00 > (md)0x1D999+3
echo -e \x20\x20\x20\x20\x00 > (md)0x1D900+3
::remove quotes from string
call Fn.0 0 %DNAME% | set DNAME=

:: try by looking in scsi section - find matching ID - find driver= and find driverkey (e.g. driver=d1,SisRaid2.sys,SISRAID2) - look for [Config.SYSRAID2]
inifile /%~1 [scsi] | call :find_oem_id=%~1 
if "%CONF%"=="1" exit


:: the above **should** work, but if bad .oem file try other methods!

:: try [default] entry next
if "%DD%">="2" echo CHECK_OEM: Trying [DEFAULTS] section in %1
inifile /%1 [Defaults] scsi | set TDEF=
if "%DD%"=="1" echo TDEF=%TDEF% ID=%id%
:: now find Files.scsi driver
inifile /%1 [Files.scsi.%TDEF%] driver | set CS=
call :get3rd
set get3rd=%CS%
if "%DD%"=="1" echo get3rd=%get3rd%
:: check the Default is for our ID
inifile /%1 [HardwareIDs.scsi.%TDEF%] > (md)0x1D900+3
cat --locatei=%id% (md)0x1D900+3 > nul && inifile /%1 [Config.%get3rd%] > nul && inifile /%1 [Config.%get3rd%] >> (md)0x1D999+3 && echo Added [Config.%get3rd%] Section from [HardwareIDs.scsi.%TDEF%] && set CONF=1 && exit

::If still none found...
::look for Config section with same name as driver (often it is not!)
if "%DD%">="2" echo At CHECK_OEM Looking for [Config.%DNAME%]
inifile /%1 [Config.%DNAME%] > nul && inifile /%1 [Config.%DNAME%] >> (md)0x1D999+3 && echo Added [Config.%DNAME%] Section to txtsetup.oem && set CONF=1 && exit

:: If no Config of drivername found, look for first one with PnPInterfaces and use that!
if "%DD%">="2" echo No [Config.%DNAME%] found - searching for any [Config section with PnPInterface entry...
:: abort if no PnPInterface
cat --locatei=[config. --number=1 /%1 > nul || exit
cat --locatei=value --skip=%?% --number=1 /%1 > nul || exit
cat --locatei=PnPInterface --skip=%?% --number=1 /%1 > nul || exit
:: Found [config value PnPInterface - go back to find config characters
set /a st=%?%-10 > nul
:: go back 10 characters at a time until we find the start of the section
set lp=0
:psrch
if %st%<=0 exit
cat --locatei=[config.  --length=20 --number=1 --skip=%st% /%1 > nul && set lp=1
set tmp=%?%
if "%lp%"=="0" set /a st=%st%-10 && goto :psrch
set st=%tmp%
set lp=
set tmp=
:: %st% has start of a [Config section with PnPInterface within 300 characters

:fndcfg
if "%DD%"=="1" echo st=%st% && cat --length=30 --skip=%st% /%1
::cat --length=60 --skip=%st% /%1
::echo
cat --locatei=PnPInterface --skip=%st% --number=1 /%1 > nul || exit
:: find start of next section
cat --locate=[ --number=1 --skip=%?% /%1 > nul
set /a l=%?%-%st%
cat --locatei=PnPInterface --skip=%st% --length=%l% /%1 > nul && goto :gotcfg
set /a st=%st%+%l%+1 > nul
::echo st=%st% ... looping to :fndcfg
goto :fndcfg

:gotcfg
::cat --length=60 --skip=%st% /%1
cat --locatei=value --skip=%st% --number=1 /%1 > nul
set /a st=%?%+0 > nul
cat --locate=[ --skip=%st% --number=1 /%1 > nul
set /a l=%?%-%st% > nul
:: get section into (md)0x1D999
if "%DD%"=="1" cat --skip=%st% --length=%l% /%1
cat --skip=%st% --length=%l% /%1 > (md)0x1D999+3
:: signal we have a valid CONF section
set CONF=1
if "%DD%"=="1" echo
echo Added [Config] Section to txtsetup.oem
if "%DD%"=="1" cat (md)0x1D999+3
if "%DD%"=="1" echo
set l=
set st=
exit

:add_cat
:: %1 %2 %3 has entries
if "%1"=="" exit
echo %1
if exist /%1 echo FOUND %1
shift
goto :add_cat



:find_oem_id
:: %1 is filename %2-%n possible driver sections
:: [scsi]
:: xxxxxx= "ssssss"
::or
:: xxxxxx = "sssss" , DDDDDD
:: So %3 could be next scsi entry or some name! - see /D/M/IT2/txtsetup.oem for example of problem file!

if "%DD%">="2" echo FIND_OEM_ID: 1=%1 2=%2 3=%3 
set dd=%1
:foid_lp
if "%DD%"=="1" echo FOID_LP: 1=%1 2=%2 3=%3
set CS=%~2
call :clean_st
set dd2=%CS%
set CS=%~3
call :clean_st
set dd3=%CS%
set CS=

::if "%DD%"=="1" echo DDD dd2=%dd2% && cat (md)0x1d900+1 && echo 
if "%dd2%"=="" exit
if "%DD%"=="1" echo FOID_LP: Check valid extension name %dd2% in /%dd%

inifile /%dd% [HardwareIds.scsi.%dd2%] > nul || shift && goto :foid_lp

set /u dd2=%dd2%
set /u dd3=%dd3%
if "%DD%">="2" echo FOID_LP: Looking for non-XP x86 names in "%dd2%" and "%dd3%"
call Fn.11 "%dd2%" "XP" && goto :gotfoxp
call Fn.11 "%dd3%" "XP" && goto :gotfoxp
call Fn.11 "%dd2%" "2K3" && shift && goto :foid_lp
call Fn.11 "%dd3%" "2K3" && shift && goto :foid_lp
call Fn.11 "%dd2%" "2003" && shift && goto :foid_lp
call Fn.11 "%dd3%" "2003" && shift && goto :foid_lp
call Fn.11 "%dd2%" "2000" && shift && goto :foid_lp
call Fn.11 "%dd3%" "2000" && shift && goto :foid_lp
call Fn.11 "%dd3%" "VISTA" && shift && goto :foid_lp
call Fn.11 "%dd2%" "VISTA" && shift && goto :foid_lp
call Fn.11 "%dd3%" "2000" && shift && goto :foid_lp
goto :gotfoxp
::check for 64-bit driver but if says 32bit then probably ok!
call Fn.11 "%dd2%" "32" && goto :gotfoxp
call Fn.11 "%dd2%" "32" && goto :gotfoxp
call Fn.11 "%dd2%" "64" && shift && goto :foid_lp
call Fn.11 "%dd3%" "64" && shift && goto :foid_lp

:gotfoxp
if "%DD%">="2" echo FIND_OEM_ID @:GOTFOXP @%dd2%@ @%3@
inifile /%dd% [HardwareIds.scsi.%dd2%] > (md)0x1D900+3
cat --locatei=%id% (md)0x1D900+3 > nul || shift && goto :foid_lp
if "%DD%"=="1" echo FOID_LP: Found HW ID %?% at offset %dd% in [HardwareIds.scsi.%dd2%]
inifile /%dd% [Files.scsi.%dd2%] driver | set CS=
call :get3rd
set get3rd=%CS%
if "%get3rd%"=="" if "%DD%">="2" echo No DriverKey specified on driver= line in %dd%! && exit
:: check the Default is for our ID
if "%DD%"=="1" inifile /%dd% [HardwareIDs.scsi.%dd2%]
inifile /%dd% [HardwareIDs.scsi.%dd2%] > (md)0x1D900+3
cat --locatei=%id% (md)0x1D900+3 > nul && inifile /%dd% [Config.%get3rd%] > nul && inifile /%dd% [Config.%get3rd%] >> (md)0x1D999+3 && echo Added [Config.%get3rd%] Section from [HardwareIDs.scsi.%dd2%] && set CONF=1 && exit
if "%DD%">="2" echo :FIND_OEM_ID FAILED TO %id% for [Config.%get3rd%] SECTION
set dd2=
set dd3=
exit

:separate
:: CS = input string - e.g. sdsdssd,sss sdssds , sdsddssd sddsssd sssss
exit

:get3rd
if "%DD%"=="1" echo get3rd %get3rd%
:: separate into parameters
:: write string and add comma to end and EOS byte
write (md)0x1D900+1 %CS%\x00
:: put space where any spaces
cat --locate=, --replace=\x20 (md)0x1D900+1
cat (md)0x1D900+1 | set CS=
::echo CS=%CS% - calling g3...
echo %CS% | call :g3=
::echo CS=%CS%
exit

:g3
set CS=%~3
exit



:clean_st
:: CS has string to clean - we want first single word
:: clean string - it may have " or spaces or , or spaces at the end
::if "%DD%"=="1" echo CLEAN_ST CS=%CS%
:: write string and add comma to end and EOS byte
write (md)0x1D900+1 %CS%,\x00\x00\x00\x00
:: put spaces where any commas
cat --locate=, --replace=\x20 (md)0x1D900+1
:: put EOS where any spaces
cat --locate=\x20 --replace=\x00 (md)0x1D900+1
:: put space where any quotes
cat --locate=\x22 --replace=\x20 (md)0x1D900+1
cat (md)0x1D900+1 | set CS=
:: get rid of any space at end
call Fn.0 0 %CS% | set CS=
exit


:: --------------------- COPYFILES to (8) ------

:copyfiles
if "%~1"=="" exit
shift
if "%~x0"=="" && goto :copyfiles
if "%DD%"=="1" echo copyfiles:  %0
set /u filename=/%0
call :%~x0 %0 && if not exist (8)/%0  && echo -e -n %~nx0 \x20 && fat copy %filename% (8) > nul  || echo -n -e $[0104]\nERROR: CANNOT FIND %filename% \n && set err=1 && pause 
goto :copyfiles


:.inf
::set INF=%1 - avoid duplicates
if "%PREVINF%"=="%1" exit
echo inf=d1,%1 >> (md)0x300+8
set PREVINF=%1
exit

:.cpl
echo catalog=d1,%1 >> (md)0x300+8
exit

:.reg
echo catalog=d1,%1 >> (md)0x300+8
exit

:.exe
echo catalog=d1,%1 >> (md)0x300+8
exit

:.cat
echo catalog=d1,%1 >> (md)0x300+8
exit

:.dll
echo dll=d1,%1 >> (md)0x300+8
exit

:.sys
:: %1 has sys filename - make sure not 64-bit!
call Fn.11 "%1" "64.sys" && exit
:: make sure we get Setup to copy all sys files over to HDD
echo catalog=d1,%1 >> (md)0x300+8

::collect driver.sys names in SYS/1/2/3
::if not exist SYS  if %s1%==0 set SYS=%1 && exit but get rid of any quote marks
if not exist SYS  if %s1%==0 call Fn.0 0 %~1 | set SYS= && exit
if not exist SYS1 if %s1%==0 call Fn.0 0 %~1 | set SYS1= && exit
if not exist SYS2 if %s1%==0 call Fn.0 0 %~1 | set SYS2= && exit
if not exist SYS3 if %s1%==0 call Fn.0 0 %~1 | set SYS3= && exit
:: not need to add
set s1=
exit



:: ----------------------------- MAKE TXTSETUP.OEM FILE ---------------------------
:: %1 is .pci.NUMBER
:: %2 is floppy #

:make_oem
:: %1 is pci name e.g. %pci.1%=iastor3
:: %2 is floppy device number - e.g. 1 then 0
:: %3 is total number of floppies

if "%DD%"=="1" call echo MAKE_OEM: pci_name=%1 fd%2 total_fd=%3 pci.%1=%^pci.%1% FIRA=%FIRA%

if "%pci.%1%"=="" exit
:: map floppy 0 or 1
map --mem (8)+1 (%2)
map --rehook

:: get default driver name (no quotes)

:: bugfix if name begins with a number Fn.0 0 gives no output!
::call Fn.0 0 %pci.%1% | set def=
echo  %pci.%1% > (md)0x331+1
cat --locate=\x22 --replace=\x20 (md)0x331+1
cat (md)0x331+1 | set def=


:: DISK 1 = OEM or Fira
:: DISK 0 = OEM or Fira or winvblock

:: FORCEFIRA means this disk MUST be a ramdisk driver (fira or winvblock)
if "%FORCEFIRA%"=="1" if /i not "%def%"=="Firadisk%" if /i not "%def%"=="WinVblock%" set def=firadisk
:: if we asked for winv and only one disk then use Winv
if "%FIRA%"=="3" if "%3"=="1" set def=WinVBlock
:: if we ask for winv and 2 disks - change to winvblock
if "%FIRA%"=="3" if "%3"=="2" if "%FORCEFIRA%"=="1" set def=WinVBlock
:: reset for next time
set FORCEFIRA=

if "%def%"=="" set def=(none)
echo $[0105]    (fd%2) $[0107]default=$[0106]%def%

:: if Defaults section exists then change it, else add one 
cat --locate="END - ###" (md)0x300+8 > nul || echo -e -n \r\n[Defaults]\r\nscsi=%def%\r\n;### - END - ### >> (md)0x300+8
cat --locate="END - ###" (md)0x300+8 > nul && cat --locatei=[Defaults] --replace="[Defaults]\r\nscsi=%def%\r\n;### - END - ###\r\n;" (md)0x300+8

:: WRITE OUT TO TXTSETUP.OEM
fat copy (md)0x300+8 (%2)/txtsetup.oem

:: SET disk tag file in txtsetup.oem
cat --locate=,\\diskx,\\ --replace=,\\disk1,\\ (%2)/txtsetup.oem > nul
::label the txtsetup.oem file (text displayed to user if problem)
::use diskd for driver disk and diskf for firadisk or diskw for winvblock
set lb=D
if /i "%def%"=="firadisk" set lb=F
if /i "%def%"=="WinVBlock"  set lb=W
cat --locate=(diskx) --replace=(disk%lb%) (%2)/txtsetup.oem > nul 

:: tag file is always disk1 on both disks
fat mkfile (%2)/disk1


:: SENSE CHECK
ls (%2)/ | call :chk_fls=

exit


:chk_fls
:: check files on the disk
set chkinf=
set chksys=
set chkcat=
if /i "%1"=="" goto :chk1
if /i "%~n1"=="firadisk" shift &&  goto :chk_fls
if /i "%~n1"=="winvblk" shift &&  goto :chk_fls
if /i "%~n1"=="wvblk32" shift &&  goto :chk_fls
if /i "%DD%"=="1" echo CHK_FLS: Checking %1
if /i "%~x1"==".inf" set chkinf=1
if /i "%~x1"==".cat" set chkcat=1
if /i "%~x1"==".sys" set chksys=1
shift
goto :chk_fls
:chk1
:: if all are missing then probably no PCI ID was found!
if not "%chkinf%-%chksys%-%chkcat%"=="1-1-1" exit
if not "%chkinf%"=="1" echo -e -n $[0104] ERROR: NO OEM DRIVER .INF FILE FOUND\n
if not "%chksys%"=="1" echo -e -n $[0104] ERROR: NO OEM DRIVER .SYS FILE FOUND\n
if not "%chkcat%"=="1" echo -e -n $[0104] WARNING: NO OEM DRIVER .CAT FILE FOUND\n
::if "%chksys%%%chkcat%%%chkinf%"=="" echo
exit


