@echo off
REM ==============================================================
REM start=DS PXE fixup for WinPE 3
REM Version=7.5
if defined debug (echo on) else (echo off)
if not defined echo (set dbg=rem) else (set dbg=)

REM ==============================================================
REM All Parameters are in the form "tag=value".
REM	{tag}   = {value}
REM
REM The following items are supported:
REM	pxePath = Path to root of PXE server (eg c:\PXE\Images)
REM	optID   = PXE menu Option original ID (eg 131)
REM	optRID  = PXE menu Option redirected ID (eg 131)
REM	optPath = PXE menu Option path (eg MenuOption131\x86pc)
REM	optName = PXE menu Option name (eg MenuOption131)
REM	pxeName = PXE server name
REM	pxeIP   = PXE server IP address list (multiple items separated by ",")
REM	dsName  = DS server name (if known)
REM	dsIP    = DS server IP
REM
REM Additional options:
REM	debug   = {true | t | 1} to enable debug mode
REM	echo    = {true | t | 1} to turn on echo
REM
REM In order to pass values in this format, the "tag=value" pair must be
REM passed in "" symbols (ie. "tag=value") to prevent the "=" from being removed.
REM --------------------------------------------------------------
setlocal EnableDelayedExpansion EnableExtensions

@echo [%time% %date:~4%] =================================================
@echo [%time% %date:~4%] Begin PXEfixup.bat (%~f0)...
@echo [%time% %date:~4%] =================================================


@rem --------------------------------------------
@rem Check command line options
@rem --------------------------------------------
call :get-tagged-params v_ %*
%dbg% set v_

if defined v_debug (set dbg=) else (set dbg=rem)
if defined v_echo  (echo on)  else (echo off)

@%dbg% echo cmdline=%*
@%dbg% echo 1=%1
@%dbg% echo 2=%2
@%dbg% echo 3=%3
@%dbg% echo 4=%4
@%dbg% echo 5=%5
@%dbg% echo 6=%6
@%dbg% echo 7=%7
@%dbg% echo 8=%8
@%dbg% echo 9=%9
rem @%dbg% for /l %%i in (1,1,25) do if not "!%%i" == "" echo %%i=!%%i

set pxe_pth=%v_pxePath%
set img_oid=%v_optID%
set img_rid=%v_optRID%
set img_pth=%v_optPath%
set img_fil=%v_optName%
set pxe_nam=%v_pxeName%
set pxe_ips=%v_pxeIP%
set ds_nam=%v_dsName%
set ds_ip=%v_dsIP%

if "%pxe_nam%%pxe_ips%" == "" if not "%v_pxe%" == "" call :get-server-ip "%v_pxe%" pxe_nam pxe_ips
if "%ds_nam%%ds_ip%"    == "" if not "%v_ds%" == ""  call :get-server-ip "%v_ds%"  ds_nam  ds_ip

if "%pxe_pth%" == "" set pxe_pth=..\..
if "%img_oid%" == "" set img_oid=131
if "%img_rid%" == "" set img_rid=131
if "%img_pth%" == "" set img_pth=MenuOption131\x86pc
if "%img_fil%" == "" set img_fil=MenuOption131

if "%pxe_pth:~-1%" == "\" set pxe_pth=%pxe_pth:~0,-1%
if "%img_pth:~-1%" == "\" set img_pth=%img_pth:~0,-1%


@rem --------------------------------------------
@rem Set current working directory
@rem --------------------------------------------
@echo Current directory is "%cd%"
rem cd %~d0
rem cd %~p0
@echo.  Setting directory to "%~d0%~p0"
cd /d %~d0%~p0


@rem --------------------------------------------
@rem Process parameters
@rem --------------------------------------------
set bcd_root=%pxe_pth%
set std_pth=boot

set bcd_nam=pxeboot.bcd
set bcd_pth=

@rem set bcd_pth=%std_pth%

set sdi_nam=boot.sdi
set sdi_pth=%img_pth%\boot

set wim_nam=boot.wim
set wim_pth=%img_pth%\sources

@%dbg% echo pxe_pth=%pxe_pth%
@%dbg% echo img_oid=%img_oid%
@%dbg% echo img_rid=%img_rid%
@%dbg% echo img_pth=%img_pth%
@%dbg% echo img_fil=%img_fil%
@%dbg% echo PXE_nam=%PXE_nam%
@%dbg% echo PXE_ips=%PXE_ips%
@%dbg% echo DS_nam=%DS_nam%
@%dbg% echo DS_IP=%DS_IP%
@%dbg% echo.
@%dbg% echo bcd_pth=%bcd_pth%
@%dbg% echo sdi_pth=%sdi_pth%
@%dbg% echo wim_pth=%wim_pth%
@%dbg% echo.


@rem --------------------------------------------
@rem Begin operations
@rem --------------------------------------------
@echo Processing configuration
@rem echo Processing configuration at "%std_pth%"


@rem --------------------------------------------
@rem Create PXE settings file
@rem --------------------------------------------
call :CreatePXESet "pxeset.ini"


@rem --------------------------------------------
@rem Create and configure local bcd file
@rem --------------------------------------------
@rem call :CreateBCD "%bcd_pth%\%bcd_nam%" "%sdi_pth%\%sdi_nam%" "%wim_pth%\%wim_nam%"
call :CreateBCD "%bcd_nam%" "%sdi_pth%\%sdi_nam%" "%wim_pth%\%wim_nam%"


@rem --------------------------------------------
@rem Copy font files to <PXEroot> font folder
@rem --------------------------------------------
call :CopyFonts "%pxe_pth%"


@rem --------------------------------------------
@rem Prepare the .0 file
@rem --------------------------------------------
call :PrepareDotZero "%img_fil%.0"


@rem --------------------------------------------
@rem Call user script
@rem --------------------------------------------
if exist "%~dp0usrfixup.bat" call "%~dp0usrfixup.bat" %*


@rem --------------------------------------------
@rem Show BCD file
@rem --------------------------------------------
@echo BCD file contents...
@rem bcdedit /store "%bcd_pth%\%bcd_nam%" /enum all
bcdedit /store "%bcd_nam%" /enum all



@rem --------------------------------------------
@rem Done
@rem --------------------------------------------
@echo [%time% %date:~4%] =================================================
@echo [%time% %date:~4%] End PXEfixup.bat (%~f0)
@echo [%time% %date:~4%] =================================================
endlocal
goto :eof





REM ==============================================================
REM CreatePXESet=create PXEset.ini file
REM	1 = Path to pxeset.ini file to create
REM --------------------------------------------------------------
:CreatePXESet

@echo Create PXE settings file
if exist "%~1" del /f /q "%~1"
@(
  echo [PXE]
  echo PXE_SERVER=%pxe_nam%
  echo PXE_IP=%pxe_ips%
  echo PXE_BOOTPATH=!img_pth:"=!
  echo PXE_OID=%img_oid%
  echo PXE_RID=%img_rid%
) >>"%~1"

goto :eof


REM ==============================================================
REM CopyFonts=Copy font files to <PXEroot> font folder
REM	1 = Path to <PXEroot> folder
REM --------------------------------------------------------------
:CopyFonts
setlocal EnableDelayedExpansion EnableExtensions
set dst_pth=%~1

set fnt_pth=boot\fonts
set efi_fnt_pth=efi\microsoft\boot\fonts

@echo Copying font files to "%dst_pth%\%fnt_pth%"...
if not exist "%dst_pth%\%fnt_pth%\wgl4_boot.ttf" (
  @echo.  Font wgl4_boot.ttf not found at "%dst_pth%\%fnt_pth%"

  if not exist "%dst_pth%\%fnt_pth%" md "%dst_pth%\%fnt_pth%" >nul
  if exist "%fnt_pth%\wgl4_boot.ttf"  copy /y "%fnt_pth%\wgl4_boot.ttf"  "%dst_pth%\%fnt_pth%" >nul

  if not exist "%dst_pth%\%fnt_pth%\wgl4_boot.ttf" (
    @echo.  Font wgl4_boot.ttf still not not found at "%dst_pth%\%fnt_pth%"
  ) else (
    @echo.  Font wgl4_boot.ttf now available at "%dst_pth%\%fnt_pth%"
  )

) else (
  @echo.  Font wgl4_boot.ttf already at "%dst_pth%\%fnt_pth%"
)

@echo Copying font files to "%dst_pth%\%efi_fnt_pth%"...
if not exist "%dst_pth%\%efi_fnt_pth%\wgl4_boot.ttf" (
  @echo.  Font wgl4_boot.ttf not found at "%dst_pth%\%efi_fnt_pth%"

  if not exist "%dst_pth%\%efi_fnt_pth%" md "%dst_pth%\%efi_fnt_pth%" >nul
  if exist "%fnt_pth%\wgl4_boot.ttf"  copy /y "%fnt_pth%\wgl4_boot.ttf"  "%dst_pth%\%efi_fnt_pth%" >nul

  if not exist "%dst_pth%\%efi_fnt_pth%\wgl4_boot.ttf" (
    @echo.  Font wgl4_boot.ttf still not not found at "%dst_pth%\%efi_fnt_pth%"
  ) else (
    @echo.  Font wgl4_boot.ttf now available at "%dst_pth%\%efi_fnt_pth%"
  )

) else (
  @echo.  Font wgl4_boot.ttf already at "%dst_pth%\%efi_fnt_pth%"
)

endlocal
goto :eof


REM ==============================================================
REM CreateBCD=create BCD file
REM	1 = Path to bcd file (boot\bcd)
REM	2 = Path to sdi file (boot\boot.sdi)
REM	3 = Path to wim file (sources\boot.wim)
REM	4 = Set to anything to add {dbgsettings} section
REM --------------------------------------------------------------
:CreateBCD
setlocal EnableDelayedExpansion EnableExtensions

set bcd_fil=%~1& set bcd_nam=%~n1
set sdi_fil=%~2
set wim_fil=%~3
set add_dbg=%~4
set guid=e217309d-dead-beef-a315-001372be0d01

@echo Creating BCD file at "%bcd_fil%"...

@rem --------------------------------------------
@rem Rename old BCD file
@rem --------------------------------------------
if exist "%bcd_fil%" (
  @echo.  Rename old BCD file "%bcd_fil%" to "%bcd_fil%.old"
  if exist "%bcd_fil%.old" del /f /q "%bcd_fil%.old"
  rename "%bcd_fil%" "%bcd_fil%.old"
)

@rem --------------------------------------------
@rem Create new BCD file
@rem --------------------------------------------
@echo.  Create new BCD file
if exist "%bcd_fil%" del /f /q "%bcd_fil%"
bcdedit /createstore "%bcd_fil%"

@rem --------------------------------------------
@rem Create ramdisk options in BCD file
@rem --------------------------------------------
@echo.  Create Ramdisk Options
bcdedit /store "%bcd_fil%" /create {ramdiskoptions} /d "Ramdisk Options"
bcdedit /store "%bcd_fil%" /set    {ramdiskoptions} ramdisksdidevice boot
bcdedit /store "%bcd_fil%" /set    {ramdiskoptions} ramdisksdipath "\%sdi_fil%"
bcdedit /store "%bcd_fil%" /set    {ramdiskoptions} custom:36000009 No
bcdedit /store "%bcd_fil%" /set    {ramdiskoptions} custom:3600000a Yes

@rem --------------------------------------------
@rem Create windows boot loader options in BCD file
@rem --------------------------------------------
@echo.  Create Windows Boot Loader Options
bcdedit /store "%bcd_fil%" /create {%guid%} /d "PXE WinPE 2 Boot Image" /application osloader
bcdedit /store "%bcd_fil%" /set    {%guid%} systemroot \Windows
bcdedit /store "%bcd_fil%" /set    {%guid%} detecthal Yes
bcdedit /store "%bcd_fil%" /set    {%guid%} winpe Yes
bcdedit /store "%bcd_fil%" /set    {%guid%} osdevice ramdisk="[boot]\%wim_fil%",{ramdiskoptions}
bcdedit /store "%bcd_fil%" /set    {%guid%} device   ramdisk="[boot]\%wim_fil%",{ramdiskoptions}

@rem --------------------------------------------
@rem Create windows boot manager options in BCD file
@rem --------------------------------------------
@echo.  Create Windows Boot Manager Options
bcdedit /store "%bcd_fil%" /create {bootmgr} /d "WinPE 2 Boot Manager"
bcdedit /store "%bcd_fil%" /set    {bootmgr} timeout 5
bcdedit /store "%bcd_fil%" /set    {bootmgr} displayorder {%guid%}
bcdedit /store "%bcd_fil%" /set    {bootmgr} default {%guid%}
bcdedit /store "%bcd_fil%" /set    {bootmgr} nointegritychecks yes

@rem --------------------------------------------
@rem Create EMS/SAC entries in BCD file
@rem --------------------------------------------
@echo.  Enable EMS Options
bcdedit /store "%bcd_fil%" /ems     {default} on
bcdedit /store "%bcd_fil%" /bootems {default} on

@rem --------------------------------------------
@rem Create debugger options in BCD file
@rem --------------------------------------------
if defined add_dbg (
  @echo.  Create remote Debugger Options
  bcdedit /store "%bcd_fil%" /create {dbgsettings} /d "Debugger Settings"
  bcdedit /store "%bcd_fil%" /set    {dbgsettings} debugtype serial
  bcdedit /store "%bcd_fil%" /set    {dbgsettings} baudrate 115200
  bcdedit /store "%bcd_fil%" /set    {dbgsettings} debugport 1
  bcdedit /store "%bcd_fil%" /set    {bootmgr}     inherit {dbgsettings}
)

endlocal
goto :eof



REM ==============================================================
REM PrepareDotZero=prepare Dot Zero file
REM	1 = Destination file name for Dot Zero file
REM --------------------------------------------------------------
:PrepareDotZero
setlocal EnableDelayedExpansion EnableExtensions

set dot_zero=%~1

@echo Preparing Dot Zero file %dot_zero% ...

@rem Remove all dummy Dot Zero files (whose size is <= 10 bytes)
if exist "*.0" for %%f in ("*.0") do if %%~zf leq 100 ( @echo.  Remove placeholder Dot Zero file "%%~f" & del /f /q "%%~f" )

@rem Backup existing Dot Zero file
if exist "%dot_zero%" (
  @echo.  Backup existing Dot Zero file "%dot_zero%" to "%dot_zero%.old"
  if exist "%dot_zero%.old" del /f /q "%dot_zero%.old"
  rename "%dot_zero%" "%dot_zero%.old"
)

@rem Rename the boot loader file to be the Dot Zero file
if not exist "%dot_zero%" (
  @rem Use the first Dot Zero file that is found
  @rem This list is in the prefered order, and any later renames will be skipped
  for %%f in ("pxeboot.n12")  do call :RenameFile "%%~f" "%dot_zero%"
  for %%f in ("pxeboot.com")  do call :RenameFile "%%~f" "%dot_zero%"
  for %%f in ("WINPE2x86.0")  do call :RenameFile "%%~f" "%dot_zero%"
  for %%f in ("WINPE2x64.0")  do call :RenameFile "%%~f" "%dot_zero%"
  for %%f in ("WINPE2ia64.0") do call :RenameFile "%%~f" "%dot_zero%"
) else (
  @echo.  The Dot Zero file "%dot_zero%" already exists
)

@rem restore old Dot Zero file if there is no Dot Zero file
if not exist "%dot_zero%" if exist "%dot_zero%.old" (
  @echo.  No Dot Zero file found - Restore old Dot Zero file "%dot_zero%.old" to "%dot_zero%"
  rename "%dot_zero%.old" "%dot_zero%"
)

if not exist "%dot_zero%" @echo.  ERROR: No Dot Zero file "%dot_zero%" found!

endlocal
goto :eof



REM ==============================================================
REM RenameFile=rename file
REM	1 = Source file name to rename
REM	2 = Destination file name
REM --------------------------------------------------------------
:RenameFile
setlocal EnableDelayedExpansion EnableExtensions

set src_fil=%~1
set dst_fil=%~2

rem echo.  Looking for "%src_fil%"...

if not exist "%src_fil%" (
  echo.  Tried "%src_fil%" - no file found
  endlocal
  goto :eof
)

rename "%src_fil%" "%dst_fil%" 2>nul
if %errorlevel% equ 0 (
  copy /y "%dst_fil%" "%src_fil%.old" >nul 2>nul
  @echo. *Rename "%src_fil%" to "%dst_fil%"
) else if %errorlevel% equ 1 (
    if exist "%dst_fil%" @echo.  Skipping "%src_fil%" - "%dst_fil%" already exists
) else (
  @echo.  ERROR: Error %errorlevel% renaming "%src_fil%" to "%dst_fil%"
)

endlocal
goto :eof



REM ==============================================================
REM get-server-ip=Get server and IP address(es)
REM	1 = Combined server/IP string
REM	2 = Env variable to return sevrer name in
REM	3 = Env variable to return server ip(s) in
REM	return = Env variables set with server and ip address
REM --------------------------------------------------------------
:get-server-ip
setlocal EnableDelayedExpansion EnableExtensions

set esvr=svr& if not "%~2" == "" set esvr=%~2
set eips=ips& if not "%~3" == "" set eips=%~3

call :tokenize "%~1" "|" v_

%dbg% echo server name="%v_01%"
%dbg% echo server IPs="%v_02%"

endlocal & set %esvr%=%v_01%& set %eips%=%v_02%
goto :eof



REM ==============================================================
REM get-tagged-params=Get tagged parameters
REM	1 = Env variable prefix for parameter values
REM	2... = Parameters in form tag=value
REM	return = Env variables prefixed with parameter 1
REM --------------------------------------------------------------
:get-tagged-params
set pfx=%~1
shift /1

:get-tagged-loop
if "%~1" == "" goto get-tagged-done
for /f "delims== tokens=1*" %%v in ("%~1") do set %pfx%%%v=%%w& set single=%%w
if "%single%" == "" for /f "delims== tokens=1*" %%v in ("%~1=%~2") do shift /1 & set %pfx%%%v=%%w
shift /1
goto get-tagged-loop

:get-tagged-done
set single=
set pfx=
goto :eof



REM ==============================================================
REM tokenize=Separate tokens on a delimiter
REM	1 = String to tokenize
REM	2 = Delimiter to tokenize on
REM	3 = Env variable prefix for tokens
REM	return = Env variables prefixed with %3
REM --------------------------------------------------------------
:tokenize
set dlm=^|& if not "%~2" == "" set dlm=^%~2
set pfx=v_& if not "%~3" == "" set pfx=%~3

for /l %%i in (1,26,1) do set %pfx%%%i=& set %pfx%0%%i=
for /f "delims=%dlm% tokens=1-25*" %%a in ("%~1") do (
  set %pfx%01=%%a
  set %pfx%02=%%b
  set %pfx%03=%%c
  set %pfx%04=%%d
  set %pfx%05=%%e
  set %pfx%06=%%f
  set %pfx%07=%%g
  set %pfx%08=%%h
  set %pfx%09=%%i
  set %pfx%10=%%j
  set %pfx%11=%%k
  set %pfx%12=%%l
  set %pfx%13=%%m
  set %pfx%14=%%n
  set %pfx%15=%%o
  set %pfx%16=%%p
  set %pfx%17=%%q
  set %pfx%18=%%r
  set %pfx%19=%%s
  set %pfx%20=%%t
  set %pfx%21=%%u
  set %pfx%22=%%v
  set %pfx%23=%%w
  set %pfx%24=%%x
  set %pfx%25=%%y
  set %pfx%26=%%z
)

set dlm=
set pfx=

goto :eof