Reactos
at listview 231 lines 7.6 kB view raw
1#!/bin/sh 2# shellcheck disable=SC3003,SC3045 3 4## 5## PROJECT: ReactOS ISO Remastering Script 6## LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 7## PURPOSE: Allows easy remastering of customized ReactOS ISO images. 8## Based on the boot/boot_images.cmake script in the ReactOS 9## source tree. Requires a MKISOFS-compatible utility. 10## COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org> 11## 12## POSIX shell compliance checker: https://www.shellcheck.net 13## 14 15## echo -ne "\033]0;ReactOS ISO Remastering Script\007" 16 17## 18## Customizable settings 19## 20## ISO image identifier names 21ISO_MANUFACTURER="ReactOS Project" # For both the publisher and the preparer 22ISO_VOLNAME="ReactOS" # For both the Volume ID and the Volume set ID 23 24## Image names of the MKISOFS and ISOHYBRID tools 25MKISOFS=mkisofs 26ISOHYBRID=isohybrid 27 28 29## 30## Main script 31## 32clear 33echo "*******************************************************************************" 34echo "* *" 35echo "* ReactOS ISO Remastering Script *" 36echo "* *" 37echo "*******************************************************************************" 38echo 39 40exit_script() 41{ 42 ERRLVL=${1:-$?} # Use parameter, otherwise default to $? 43 [ "$ERRLVL" -eq 0 ] && echo "Success!" 44 # shellcheck disable=SC3045 45 read -n 1 -r -s -p $'Press any key to quit...\n' 46 exit "$ERRLVL" 47} 48 49## 50## Prompt the user for a choice. 51## Usage example: 52## choice YN "Yes or No [Y,N]? " 53## 54## Return in $REPLY the index of the reply in the choices list. 55## 56## See also: 57## https://stackoverflow.com/q/226703 58## 59choice() 60{ 61 ## Normalize the choices list to lowercase, and prepare 62 ## the pattern to match for only one single character. 63 CHOICE_LIST="$(echo "$1" | tr '[:upper:]' '[:lower:]')" 64 CHOICE_PATTERN="^[$CHOICE_LIST]$" 65 66 ## Echo prompt and wait for keypress 67 shift 1 68 # shellcheck disable=SC3037 69 echo -n "$@" 70 REPLY_LOWER= 71 until # Adapted from https://unix.stackexchange.com/a/249036 72 # shellcheck disable=SC3045 73 read -N 1 -r -s 74 REPLY_LOWER="$(echo "$REPLY" | tr '[:upper:]' '[:lower:]')" 75 expr "$REPLY_LOWER" : "$CHOICE_PATTERN" 1>/dev/null 76 do :; done 77 echo "$REPLY" 78 79 ## Return the index of the reply in the choices list 80 #REPLY=$(expr index "$CHOICE_LIST" "$REPLY_LOWER") 81 REPLY=${CHOICE_LIST%%"$REPLY_LOWER"*} 82 #REPLY=$(( $(expr "$REPLY" : ".*")+1 )) 83 REPLY=$(( ${#REPLY}+1 )) 84} 85 86 87## Verify that we have access to a temporary directory. 88for TMPDIR in "$TMPDIR" "$TEMP" "$TMP" "/tmp"; do 89 [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ] && break # Valid directory found 90done 91if [ -z "$TMPDIR" ] || [ ! -d "$TMPDIR" ]; then 92 echo No temporary directory exists on your system. 93 echo Please create one and assign it to the TMPDIR environment variable. 94 echo 95 exit_script 1 96fi 97 98 99## Try to auto-locate MKISOFS and if not, prompt the user for a directory. 100TOOL_DIR= 101TOOL_PATH=$(type -p $MKISOFS) 102if [ -z "$TOOL_PATH" ]; then 103 read -e -r -p $'Please enter the directory path where '$MKISOFS$' can be found:\n' TOOL_DIR 104 echo 105 # Non-POSIX-compatible test: [ "${TOOL_DIR:(-1)}" = "/" ] 106 [ "${TOOL_DIR#"${TOOL_DIR%?}"}" = "/" ] && TOOL_DIR=${TOOL_DIR%?} 107 TOOL_PATH=$TOOL_DIR/$MKISOFS 108else 109 # Get the directory without the '/filename' part (and doesn't include trailing /) 110 TOOL_DIR=${TOOL_PATH%/*} 111fi 112MKISOFS=$TOOL_PATH 113 114 115read -e -r -p $'Please enter the path of the directory tree to image into the ISO:\n' INPUT_DIR 116echo 117read -e -r -p $'Please enter the file path of the ISO image that will be created:\n' OUTPUT_ISO 118echo 119 120 121## Retrieve the full paths to the 'isombr', 'isoboot', 'isobtrt' and 'efisys' files 122isombr_file=loader/isombr.bin 123isoboot_file=loader/isoboot.bin 124isobtrt_file=loader/isobtrt.bin 125efisys_file=loader/efisys.bin 126 127#choice 12 $'Please choose the ISO boot file: 1) isoboot.bin ; 2) isobtrt.bin\n[default: 1]: ' 128choice YN $'Do you want the ReactOS media to wait for a key-press before booting [Y,N]? ' 129echo 130ISOBOOT_PATH=$isoboot_file 131if [ "$REPLY" -eq 1 ]; then 132 ISOBOOT_PATH=$isoboot_file 133elif [ "$REPLY" -eq 2 ]; then 134 ISOBOOT_PATH=$isobtrt_file 135fi 136 137## Enable (U)EFI boot support if possible: check the 138## presence of '$efisys_file' in the ISO directory tree. 139#ISO_EFI_BOOT_PARAMS 140ISO_BOOT_EFI_OPTIONS=$([ -f "$INPUT_DIR/$efisys_file" ] && \ 141 echo "-eltorito-alt-boot -eltorito-platform efi -eltorito-boot $efisys_file -no-emul-boot") 142 143## Summary of the boot files. 144echo "ISO boot file: '$ISOBOOT_PATH'" 145[ -n "$ISO_BOOT_EFI_OPTIONS" ] && echo "EFI boot file: '$efisys_file'" 146echo 147 148 149choice YN $'Do you want to store duplicated files only once (reduces the size\nof the ISO image) [Y,N]? ' 150echo 151DUPLICATES_ONCE=$([ "$REPLY" -eq 1 ] && echo "-duplicates-once") 152 153 154echo "Creating the ISO image..." 155echo 156 157## Create a mkisofs sort file to specify an explicit ordering for the boot files 158## to place them at the beginning of the image (makes ISO image analysis easier). 159## See mkisofs/schilytools/mkisofs/README.sort and boot/boot_images.cmake script 160## in the ReactOS source tree for more details. 161 162## echo ${CMAKE_CURRENT_BINARY_DIR}/empty/boot.catalog 4 163cat > "$TMPDIR/bootfiles.sort" << EOF 164boot.catalog 4 165$INPUT_DIR/$isoboot_file 3 166$INPUT_DIR/$isobtrt_file 2 167$INPUT_DIR/$efisys_file 1 168EOF 169 170## Finally, create the ISO image proper. 171#echo "Running command: 172#$MKISOFS \ 173# -o \"$OUTPUT_ISO\" -iso-level 4 \ 174# -publisher \"$ISO_MANUFACTURER\" -preparer \"$ISO_MANUFACTURER\" \ 175# -volid \"$ISO_VOLNAME\" -volset \"$ISO_VOLNAME\" \ 176# -eltorito-boot $ISOBOOT_PATH -no-emul-boot -boot-load-size 4 \ 177# $ISO_BOOT_EFI_OPTIONS \ 178# -hide boot.catalog -sort \"$TMPDIR/bootfiles.sort\" \ 179# $DUPLICATES_ONCE -no-cache-inodes \"$INPUT_DIR\" 180#" 181$MKISOFS \ 182 -o "$OUTPUT_ISO" -iso-level 4 \ 183 -publisher "$ISO_MANUFACTURER" -preparer "$ISO_MANUFACTURER" \ 184 -volid "$ISO_VOLNAME" -volset "$ISO_VOLNAME" \ 185 -eltorito-boot $ISOBOOT_PATH -no-emul-boot -boot-load-size 4 \ 186 $ISO_BOOT_EFI_OPTIONS \ 187 -hide boot.catalog -sort "$TMPDIR/bootfiles.sort" \ 188 $DUPLICATES_ONCE -no-cache-inodes "$INPUT_DIR"; ERRLVL=$? 189## -graft-points -path-list "some/directory/iso_image.lst" 190echo 191rm "$TMPDIR/bootfiles.sort" 192 193if [ "$ERRLVL" -ne 0 ]; then 194 echo "An error $ERRLVL happened while creating the ISO image \"$OUTPUT_ISO\"." 195 exit_script $ERRLVL 196fi 197echo "The ISO image \"$OUTPUT_ISO\" has been successfully created." 198echo 199 200 201## Check whether ISOHYBRID is also available and if so, propose to post-process 202## the generated ISO image to allow hybrid booting as a CD-ROM or as a hard disk. 203TOOL_PATH=$TOOL_DIR/$ISOHYBRID 204if [ -z "$TOOL_PATH" ] || [ ! -f "$TOOL_PATH" ]; then 205 TOOL_PATH=$(type -p $ISOHYBRID) 206 if [ -z "$TOOL_PATH" ]; then 207 echo "$ISOHYBRID patching skipped." 208 exit_script 0 209 fi 210fi 211ISOHYBRID=$TOOL_PATH 212 213 214choice 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]? ' 215echo 216[ "$REPLY" -ne 1 ] && exit_script 0 217 218echo "Patching the ISO image..." 219 220"$ISOHYBRID" -b "$INPUT_DIR/$isombr_file" -t 0x96 "$OUTPUT_ISO"; ERRLVL=$? 221echo 222 223if [ "$ERRLVL" -ne 0 ]; then 224 echo "An error $ERRLVL happened while patching the ISO image \"$OUTPUT_ISO\"." 225 exit_script $ERRLVL 226## else 227## echo "The ISO image \"$OUTPUT_ISO\" has been successfully patched." 228fi 229echo 230 231exit_script 0