mirror of
https://github.com/reactos/reactos.git
synced 2026-05-23 07:40:09 +08:00
[BOOT] Add an ISO remastering script (#4988)
CORE-8872 This is useful in the context of e.g. 3rd-party testers who want to quickly add/remove/modify any file in a ReactOS ISO image and remastering it without the need of our whole build environment. remaster.cmd: Batch script. remaster.sh : Almost-POSIX-compatible shell script version.
This commit is contained in:
201
boot/remaster.cmd
Normal file
201
boot/remaster.cmd
Normal file
@@ -0,0 +1,201 @@
|
||||
::
|
||||
:: PROJECT: ReactOS ISO Remastering Script
|
||||
:: LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
:: PURPOSE: Allows easy remastering of customized ReactOS ISO images.
|
||||
:: Based on the boot/boot_images.cmake script in the ReactOS
|
||||
:: source tree. Requires a MKISOFS-compatible utility.
|
||||
:: COPYRIGHT: Copyright 2023-2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
||||
::
|
||||
|
||||
@echo off
|
||||
:: title ReactOS ISO Remastering Script
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
::
|
||||
:: Customizable settings
|
||||
::
|
||||
:: ISO image identifier names
|
||||
set ISO_MANUFACTURER="ReactOS Project"& :: For both the publisher and the preparer
|
||||
set ISO_VOLNAME="ReactOS"& :: For both the Volume ID and the Volume set ID
|
||||
|
||||
:: Image names of the MKISOFS and ISOHYBRID tools
|
||||
set MKISOFS=MKISOFS.EXE
|
||||
set ISOHYBRID=ISOHYBRID.EXE
|
||||
|
||||
|
||||
::
|
||||
:: Main script
|
||||
::
|
||||
cls
|
||||
echo *******************************************************************************
|
||||
echo * *
|
||||
echo * ReactOS ISO Remastering Script *
|
||||
echo * *
|
||||
echo *******************************************************************************
|
||||
echo.
|
||||
|
||||
:: Newline macro, see https://stackoverflow.com/a/6379940
|
||||
(set \n=^
|
||||
%=Don't remove this line=%
|
||||
)
|
||||
|
||||
|
||||
:: Verify that we have access to a temporary directory.
|
||||
:: See https://stackoverflow.com/a/21041546 for more details.
|
||||
if defined TEMP ( if exist "%TEMP%\" goto :TEMP0 )
|
||||
if defined TMP ( if exist "%TMP%\" goto :TEMP1 )
|
||||
echo No temporary directory exists on your system.
|
||||
echo Please create one and assign it to the TEMP environment variable.
|
||||
echo.
|
||||
goto :Quit
|
||||
:TEMP1
|
||||
set "TEMP=%TMP%"
|
||||
:TEMP0
|
||||
|
||||
|
||||
:: Try to auto-locate MKISOFS and if not, prompt the user for a directory.
|
||||
set TOOL_DIR=
|
||||
set TOOL_PATH=
|
||||
for /f "delims=" %%f in ('WHERE %MKISOFS% 2^>NUL') do (
|
||||
set "TOOL_DIR=%%~dpf" & if "!TOOL_DIR:~-1!"=="\" set "TOOL_DIR=!TOOL_DIR:~0,-1!"
|
||||
set "TOOL_PATH=%%f"
|
||||
goto :mkisofs_found
|
||||
)
|
||||
if not defined TOOL_PATH (
|
||||
set /p TOOL_DIR="Please enter the directory path where %MKISOFS% can be found:!\n!"
|
||||
echo.
|
||||
if "!TOOL_DIR:~-1!"=="\" set "TOOL_DIR=!TOOL_DIR:~0,-1!"
|
||||
set "TOOL_PATH=!TOOL_DIR!\%MKISOFS%"
|
||||
)
|
||||
:mkisofs_found
|
||||
set "MKISOFS=%TOOL_PATH%"
|
||||
|
||||
|
||||
set /p INPUT_DIR="Please enter the path of the directory tree to image into the ISO:!\n!"
|
||||
echo.
|
||||
set /p OUTPUT_ISO="Please enter the file path of the ISO image that will be created:!\n!"
|
||||
echo.
|
||||
|
||||
|
||||
:: Retrieve the full paths to the 'isombr', 'isoboot', 'isobtrt' and 'efisys' files
|
||||
set isombr_file=loader/isombr.bin
|
||||
set isoboot_file=loader/isoboot.bin
|
||||
set isobtrt_file=loader/isobtrt.bin
|
||||
set efisys_file=loader/efisys.bin
|
||||
|
||||
set ISOBOOT_PATH=%isoboot_file%
|
||||
::CHOICE /c 12 /n /m "Please choose the ISO boot file: 1) isoboot.bin ; 2) isobtrt.bin!\n![default: 1]: "
|
||||
CHOICE /c YN /n /m "Do you want the ReactOS media to wait for a key-press before booting [Y,N]? "
|
||||
echo.
|
||||
if errorlevel 2 set ISOBOOT_PATH=%isobtrt_file%
|
||||
|
||||
:: Enable (U)EFI boot support if possible: check the
|
||||
:: presence of %efisys_file% in the ISO directory tree.
|
||||
:: NOTE: Convert forward to backslashes.
|
||||
::ISO_EFI_BOOT_PARAMS
|
||||
set ISO_BOOT_EFI_OPTIONS=
|
||||
if exist "%INPUT_DIR%\%efisys_file:/=\%" (
|
||||
set "ISO_BOOT_EFI_OPTIONS=-eltorito-alt-boot -eltorito-platform efi -eltorito-boot %efisys_file% -no-emul-boot"
|
||||
)
|
||||
|
||||
:: Summary of the boot files.
|
||||
echo ISO boot file: '%ISOBOOT_PATH%'
|
||||
if defined ISO_BOOT_EFI_OPTIONS (
|
||||
echo EFI boot file: '%efisys_file%'
|
||||
)
|
||||
echo.
|
||||
|
||||
|
||||
set DUPLICATES_ONCE=
|
||||
CHOICE /c YN /n /m "Do you want to store duplicated files only once (reduces the size!\n!of the ISO image) [Y,N]? "
|
||||
echo.
|
||||
if %ERRORLEVEL% equ 1 set DUPLICATES_ONCE=-duplicates-once
|
||||
|
||||
|
||||
echo Creating the ISO image...
|
||||
echo.
|
||||
|
||||
:: Create a mkisofs sort file to specify an explicit ordering for the boot files
|
||||
:: to place them at the beginning of the image (makes ISO image analysis easier).
|
||||
:: See mkisofs/schilytools/mkisofs/README.sort and boot/boot_images.cmake script
|
||||
:: in the ReactOS source tree for more details.
|
||||
:: https://stackoverflow.com/a/29635767
|
||||
(
|
||||
::echo ${CMAKE_CURRENT_BINARY_DIR}/empty/boot.catalog 4
|
||||
echo boot.catalog 4
|
||||
:: NOTE: Convert forward to backslashes.
|
||||
echo %INPUT_DIR%\%isoboot_file:/=\% 3
|
||||
echo %INPUT_DIR%\%isobtrt_file:/=\% 2
|
||||
echo %INPUT_DIR%\%efisys_file:/=\% 1
|
||||
) > "%TEMP%\bootfiles.sort"
|
||||
|
||||
:: Finally, create the ISO image proper.
|
||||
"%MKISOFS%" ^
|
||||
-o "%OUTPUT_ISO%" -iso-level 4 ^
|
||||
-publisher %ISO_MANUFACTURER% -preparer %ISO_MANUFACTURER% ^
|
||||
-volid %ISO_VOLNAME% -volset %ISO_VOLNAME% ^
|
||||
-eltorito-boot %ISOBOOT_PATH% -no-emul-boot -boot-load-size 4 ^
|
||||
%ISO_BOOT_EFI_OPTIONS% ^
|
||||
-hide boot.catalog -sort "%TEMP%\bootfiles.sort" ^
|
||||
%DUPLICATES_ONCE% -no-cache-inodes "%INPUT_DIR%"
|
||||
:: -graft-points -path-list "some/directory/iso_image.lst"
|
||||
echo.
|
||||
|
||||
if errorlevel 1 (
|
||||
del "%TEMP%\bootfiles.sort"
|
||||
echo An error %ERRORLEVEL% happened while creating the ISO image "%OUTPUT_ISO%".
|
||||
goto :Quit
|
||||
) else (
|
||||
del "%TEMP%\bootfiles.sort"
|
||||
echo The ISO image "%OUTPUT_ISO%" has been successfully created.
|
||||
)
|
||||
echo.
|
||||
|
||||
|
||||
:: Check whether ISOHYBRID is also available and if so, propose to post-process
|
||||
:: the generated ISO image to allow hybrid booting as a CD-ROM or as a hard disk.
|
||||
set TOOL_PATH=
|
||||
for /f "delims=" %%f in ('WHERE "%TOOL_DIR%":%ISOHYBRID% 2^>NUL') do (
|
||||
set "TOOL_PATH=%%f" & goto :isohybrid_found)
|
||||
if not defined TOOL_PATH (
|
||||
for /f "delims=" %%f in ('WHERE %ISOHYBRID% 2^>NUL') do (
|
||||
set "TOOL_PATH=%%f"
|
||||
goto :isohybrid_found
|
||||
)
|
||||
if not defined TOOL_PATH (
|
||||
echo %ISOHYBRID% patching skipped.
|
||||
goto :Success
|
||||
)
|
||||
)
|
||||
:isohybrid_found
|
||||
set "ISOHYBRID=%TOOL_PATH%"
|
||||
|
||||
|
||||
CHOICE /c YN /n /m "Do you want to post-process the ISO image to allow hybrid booting!\n!as a CD-ROM or as a hard disk [Y,N]? "
|
||||
echo.
|
||||
if %ERRORLEVEL% neq 1 goto :Success
|
||||
|
||||
echo Patching the ISO image...
|
||||
|
||||
:: NOTE: Convert forward to backslashes.
|
||||
"%ISOHYBRID%" -b %INPUT_DIR%\%isombr_file:/=\% -t 0x96 "%OUTPUT_ISO%"
|
||||
echo.
|
||||
|
||||
if errorlevel 1 (
|
||||
echo An error %ERRORLEVEL% happened while patching the ISO image "%OUTPUT_ISO%".
|
||||
goto :Quit
|
||||
)
|
||||
:: else (
|
||||
:: echo The ISO image "%OUTPUT_ISO%" has been successfully patched.
|
||||
:: )
|
||||
:: echo.
|
||||
|
||||
|
||||
:Success
|
||||
echo Success^^!
|
||||
:Quit
|
||||
endlocal
|
||||
echo Press any key to quit...
|
||||
pause > NUL
|
||||
exit /b
|
||||
231
boot/remaster.sh
Normal file
231
boot/remaster.sh
Normal file
@@ -0,0 +1,231 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC3003,SC3045
|
||||
|
||||
##
|
||||
## PROJECT: ReactOS ISO Remastering Script
|
||||
## LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
## PURPOSE: Allows easy remastering of customized ReactOS ISO images.
|
||||
## Based on the boot/boot_images.cmake script in the ReactOS
|
||||
## source tree. Requires a MKISOFS-compatible utility.
|
||||
## COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
||||
##
|
||||
## POSIX shell compliance checker: https://www.shellcheck.net
|
||||
##
|
||||
|
||||
## echo -ne "\033]0;ReactOS ISO Remastering Script\007"
|
||||
|
||||
##
|
||||
## Customizable settings
|
||||
##
|
||||
## ISO image identifier names
|
||||
ISO_MANUFACTURER="ReactOS Project" # For both the publisher and the preparer
|
||||
ISO_VOLNAME="ReactOS" # For both the Volume ID and the Volume set ID
|
||||
|
||||
## Image names of the MKISOFS and ISOHYBRID tools
|
||||
MKISOFS=mkisofs
|
||||
ISOHYBRID=isohybrid
|
||||
|
||||
|
||||
##
|
||||
## Main script
|
||||
##
|
||||
clear
|
||||
echo "*******************************************************************************"
|
||||
echo "* *"
|
||||
echo "* ReactOS ISO Remastering Script *"
|
||||
echo "* *"
|
||||
echo "*******************************************************************************"
|
||||
echo
|
||||
|
||||
exit_script()
|
||||
{
|
||||
ERRLVL=${1:-$?} # Use parameter, otherwise default to $?
|
||||
[ "$ERRLVL" -eq 0 ] && echo "Success!"
|
||||
# shellcheck disable=SC3045
|
||||
read -n 1 -r -s -p $'Press any key to quit...\n'
|
||||
exit "$ERRLVL"
|
||||
}
|
||||
|
||||
##
|
||||
## Prompt the user for a choice.
|
||||
## Usage example:
|
||||
## choice YN "Yes or No [Y,N]? "
|
||||
##
|
||||
## Return in $REPLY the index of the reply in the choices list.
|
||||
##
|
||||
## See also:
|
||||
## https://stackoverflow.com/q/226703
|
||||
##
|
||||
choice()
|
||||
{
|
||||
## Normalize the choices list to lowercase, and prepare
|
||||
## the pattern to match for only one single character.
|
||||
CHOICE_LIST="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
CHOICE_PATTERN="^[$CHOICE_LIST]$"
|
||||
|
||||
## Echo prompt and wait for keypress
|
||||
shift 1
|
||||
# shellcheck disable=SC3037
|
||||
echo -n "$@"
|
||||
REPLY_LOWER=
|
||||
until # Adapted from https://unix.stackexchange.com/a/249036
|
||||
# shellcheck disable=SC3045
|
||||
read -N 1 -r -s
|
||||
REPLY_LOWER="$(echo "$REPLY" | tr '[:upper:]' '[:lower:]')"
|
||||
expr "$REPLY_LOWER" : "$CHOICE_PATTERN" 1>/dev/null
|
||||
do :; done
|
||||
echo "$REPLY"
|
||||
|
||||
## Return the index of the reply in the choices list
|
||||
#REPLY=$(expr index "$CHOICE_LIST" "$REPLY_LOWER")
|
||||
REPLY=${CHOICE_LIST%%"$REPLY_LOWER"*}
|
||||
#REPLY=$(( $(expr "$REPLY" : ".*")+1 ))
|
||||
REPLY=$(( ${#REPLY}+1 ))
|
||||
}
|
||||
|
||||
|
||||
## Verify that we have access to a temporary directory.
|
||||
for TMPDIR in "$TMPDIR" "$TEMP" "$TMP" "/tmp"; do
|
||||
[ -n "$TMPDIR" ] && [ -d "$TMPDIR" ] && break # Valid directory found
|
||||
done
|
||||
if [ -z "$TMPDIR" ] || [ ! -d "$TMPDIR" ]; then
|
||||
echo No temporary directory exists on your system.
|
||||
echo Please create one and assign it to the TMPDIR environment variable.
|
||||
echo
|
||||
exit_script 1
|
||||
fi
|
||||
|
||||
|
||||
## Try to auto-locate MKISOFS and if not, prompt the user for a directory.
|
||||
TOOL_DIR=
|
||||
TOOL_PATH=$(type -p $MKISOFS)
|
||||
if [ -z "$TOOL_PATH" ]; then
|
||||
read -e -r -p $'Please enter the directory path where '$MKISOFS$' can be found:\n' TOOL_DIR
|
||||
echo
|
||||
# Non-POSIX-compatible test: [ "${TOOL_DIR:(-1)}" = "/" ]
|
||||
[ "${TOOL_DIR#"${TOOL_DIR%?}"}" = "/" ] && TOOL_DIR=${TOOL_DIR%?}
|
||||
TOOL_PATH=$TOOL_DIR/$MKISOFS
|
||||
else
|
||||
# Get the directory without the '/filename' part (and doesn't include trailing /)
|
||||
TOOL_DIR=${TOOL_PATH%/*}
|
||||
fi
|
||||
MKISOFS=$TOOL_PATH
|
||||
|
||||
|
||||
read -e -r -p $'Please enter the path of the directory tree to image into the ISO:\n' INPUT_DIR
|
||||
echo
|
||||
read -e -r -p $'Please enter the file path of the ISO image that will be created:\n' OUTPUT_ISO
|
||||
echo
|
||||
|
||||
|
||||
## Retrieve the full paths to the 'isombr', 'isoboot', 'isobtrt' and 'efisys' files
|
||||
isombr_file=loader/isombr.bin
|
||||
isoboot_file=loader/isoboot.bin
|
||||
isobtrt_file=loader/isobtrt.bin
|
||||
efisys_file=loader/efisys.bin
|
||||
|
||||
#choice 12 $'Please choose the ISO boot file: 1) isoboot.bin ; 2) isobtrt.bin\n[default: 1]: '
|
||||
choice YN $'Do you want the ReactOS media to wait for a key-press before booting [Y,N]? '
|
||||
echo
|
||||
ISOBOOT_PATH=$isoboot_file
|
||||
if [ "$REPLY" -eq 1 ]; then
|
||||
ISOBOOT_PATH=$isoboot_file
|
||||
elif [ "$REPLY" -eq 2 ]; then
|
||||
ISOBOOT_PATH=$isobtrt_file
|
||||
fi
|
||||
|
||||
## Enable (U)EFI boot support if possible: check the
|
||||
## presence of '$efisys_file' in the ISO directory tree.
|
||||
#ISO_EFI_BOOT_PARAMS
|
||||
ISO_BOOT_EFI_OPTIONS=$([ -f "$INPUT_DIR/$efisys_file" ] && \
|
||||
echo "-eltorito-alt-boot -eltorito-platform efi -eltorito-boot $efisys_file -no-emul-boot")
|
||||
|
||||
## Summary of the boot files.
|
||||
echo "ISO boot file: '$ISOBOOT_PATH'"
|
||||
[ -n "$ISO_BOOT_EFI_OPTIONS" ] && echo "EFI boot file: '$efisys_file'"
|
||||
echo
|
||||
|
||||
|
||||
choice YN $'Do you want to store duplicated files only once (reduces the size\nof the ISO image) [Y,N]? '
|
||||
echo
|
||||
DUPLICATES_ONCE=$([ "$REPLY" -eq 1 ] && echo "-duplicates-once")
|
||||
|
||||
|
||||
echo "Creating the ISO image..."
|
||||
echo
|
||||
|
||||
## Create a mkisofs sort file to specify an explicit ordering for the boot files
|
||||
## to place them at the beginning of the image (makes ISO image analysis easier).
|
||||
## See mkisofs/schilytools/mkisofs/README.sort and boot/boot_images.cmake script
|
||||
## in the ReactOS source tree for more details.
|
||||
|
||||
## echo ${CMAKE_CURRENT_BINARY_DIR}/empty/boot.catalog 4
|
||||
cat > "$TMPDIR/bootfiles.sort" << EOF
|
||||
boot.catalog 4
|
||||
$INPUT_DIR/$isoboot_file 3
|
||||
$INPUT_DIR/$isobtrt_file 2
|
||||
$INPUT_DIR/$efisys_file 1
|
||||
EOF
|
||||
|
||||
## Finally, create the ISO image proper.
|
||||
#echo "Running command:
|
||||
#$MKISOFS \
|
||||
# -o \"$OUTPUT_ISO\" -iso-level 4 \
|
||||
# -publisher \"$ISO_MANUFACTURER\" -preparer \"$ISO_MANUFACTURER\" \
|
||||
# -volid \"$ISO_VOLNAME\" -volset \"$ISO_VOLNAME\" \
|
||||
# -eltorito-boot $ISOBOOT_PATH -no-emul-boot -boot-load-size 4 \
|
||||
# $ISO_BOOT_EFI_OPTIONS \
|
||||
# -hide boot.catalog -sort \"$TMPDIR/bootfiles.sort\" \
|
||||
# $DUPLICATES_ONCE -no-cache-inodes \"$INPUT_DIR\"
|
||||
#"
|
||||
$MKISOFS \
|
||||
-o "$OUTPUT_ISO" -iso-level 4 \
|
||||
-publisher "$ISO_MANUFACTURER" -preparer "$ISO_MANUFACTURER" \
|
||||
-volid "$ISO_VOLNAME" -volset "$ISO_VOLNAME" \
|
||||
-eltorito-boot $ISOBOOT_PATH -no-emul-boot -boot-load-size 4 \
|
||||
$ISO_BOOT_EFI_OPTIONS \
|
||||
-hide boot.catalog -sort "$TMPDIR/bootfiles.sort" \
|
||||
$DUPLICATES_ONCE -no-cache-inodes "$INPUT_DIR"; ERRLVL=$?
|
||||
## -graft-points -path-list "some/directory/iso_image.lst"
|
||||
echo
|
||||
rm "$TMPDIR/bootfiles.sort"
|
||||
|
||||
if [ "$ERRLVL" -ne 0 ]; then
|
||||
echo "An error $ERRLVL happened while creating the ISO image \"$OUTPUT_ISO\"."
|
||||
exit_script $ERRLVL
|
||||
fi
|
||||
echo "The ISO image \"$OUTPUT_ISO\" has been successfully created."
|
||||
echo
|
||||
|
||||
|
||||
## Check whether ISOHYBRID is also available and if so, propose to post-process
|
||||
## the generated ISO image to allow hybrid booting as a CD-ROM or as a hard disk.
|
||||
TOOL_PATH=$TOOL_DIR/$ISOHYBRID
|
||||
if [ -z "$TOOL_PATH" ] || [ ! -f "$TOOL_PATH" ]; then
|
||||
TOOL_PATH=$(type -p $ISOHYBRID)
|
||||
if [ -z "$TOOL_PATH" ]; then
|
||||
echo "$ISOHYBRID patching skipped."
|
||||
exit_script 0
|
||||
fi
|
||||
fi
|
||||
ISOHYBRID=$TOOL_PATH
|
||||
|
||||
|
||||
choice YN $'Do you want to post-process the ISO image to allow hybrid booting\nas a CD-ROM or as a hard disk [Y,N]? '
|
||||
echo
|
||||
[ "$REPLY" -ne 1 ] && exit_script 0
|
||||
|
||||
echo "Patching the ISO image..."
|
||||
|
||||
"$ISOHYBRID" -b "$INPUT_DIR/$isombr_file" -t 0x96 "$OUTPUT_ISO"; ERRLVL=$?
|
||||
echo
|
||||
|
||||
if [ "$ERRLVL" -ne 0 ]; then
|
||||
echo "An error $ERRLVL happened while patching the ISO image \"$OUTPUT_ISO\"."
|
||||
exit_script $ERRLVL
|
||||
## else
|
||||
## echo "The ISO image \"$OUTPUT_ISO\" has been successfully patched."
|
||||
fi
|
||||
echo
|
||||
|
||||
exit_script 0
|
||||
Reference in New Issue
Block a user