# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-script_name="$(basename $0)"
+script_name="$(basename "$0")"
PREFIX_REG="::"
WIMLIB_VERSION=@VERSION@
-imagex=@IMAGEX_PROGNAME@
calc_columns () {
STAT_COL=80
cleanup() {
- if mountpoint -q "$mnt_dir" ; then
- @IMAGEX_PROGNAME@ unmount "$mnt_dir"
- fi
rm -rf "$tmp_dir"
}
-A, --waik-dir=DIR Get the boot files and boot.wim from the ISO of the
Windows Automated Installation Kit mounted on DIR
instead of from the Windows 7 or Windows 8 DVD.
+ This also works if the mounted ISO is for the
+ WAIK supplement rather than the WAIK itself.
-s, --start-script=FILE Add FILE to the root directory of Windows PE image
and adjust \Windows\System32\winpeshl.ini to
execute FILE when Windows PE starts up.
- -w, --wim=WIM Use WIM as the boot.wim file. Defaults to
- sources/boot.wim in the Windows DVD directory, or
- F1_WINPE.WIM from the WAIK if --waik-dir is
- specified.
+ -w, --wim=WIM Use WIM as the boot.wim file. This defaults to the
+ appropriate WIM file from the Windows DVD, WAIK,
+ or WAIK supplement.
-O, --overlay=DIR Adds all the files in DIR to the Windows PE image.
-t, --tmp-dir=DIR Use DIR as the temporary base of the ISO filesystem.
Defaults to making one using "mktemp -d".
}
version() {
- echo "$script_name (wimlib $WIMLIB_VERSION)"
+ echo "$script_name (distributed with wimlib $WIMLIB_VERSION)"
exit 0
}
windows_dir="$2"
windows_dir_specified=yes
if [ -n "$waik_dir" ]; then
- echo "ERROR: Cannot specify both --windows-dir and --waik-dir!"
+ echo 1>&2 "ERROR: Cannot specify both --windows-dir and --waik-dir!"
exit 1
fi
shift
-A|--waik-dir)
waik_dir="$2"
if [ -n "$windows_dir" ]; then
- echo "ERROR: Cannot specify both --windows-dir and --waik-dir!"
+ echo 1>&2 "ERROR: Cannot specify both --windows-dir and --waik-dir!"
exit 1
fi
shift
arch="AMD64"
arch_id="3"
else
- echo "ERROR: $2 is not a valid arch (x86/amd64)"
+ echo 1>&2 "ERROR: $2 is not a valid arch (x86/amd64)"
exit 1
fi
shift
break
;;
*)
- echo "Invalid option \"$1\""
+ echo 1>&2 "Invalid option \"$1\""
usage
exit 1
;;
done
if [ $# -ne 1 ]; then
- echo "You must specify the name of the image file to create!"
- echo "Run \"$script_name -h\" to see usage information."
+ echo 1>&2 "You must specify the name of the image file to create!"
+ echo 1>&2 "Run \"$script_name -h\" to see usage information."
exit 1
else
image="$1"
fi
if [ ! -d "$windows_dir" ]; then
if [ -z "$windows_dir_specified" ]; then
- cat << EOF
+ cat 1>&2 << EOF
ERROR: Could not find the directory that the Windows 7 or 8 ISO image is mounted
on! Please specify this directory using the --windows-dir option.
EOF
else
- echo "ERROR: Could not find the directory \"$windows_dir\"!"
+ echo 1>&2 "ERROR: Could not find the directory \"$windows_dir\"!"
fi
exit 1
fi
if [ ! -d "$windows_dir/sources" ]; then
- cat << EOF
+ cat 1>&2 << EOF
ERROR: The directory "$windows_dir" exists, but it seems that the Windows 7 or 8
ISO image is not mounted on it. Please mount the image to continue.
EOF
check_needed_programs() {
if [ -z "$waik_dir" -o -n "$modify_wim" ]; then
- if ! type -P @IMAGEX_PROGNAME@ &> /dev/null ; then
- cat << EOF
-ERROR: To make a customized image of Windows PE, we need the "$imagex" program
-from "wimlib" so that we can modify the boot.wim file. However, "$imagex"
+ if ! type -P wimlib-imagex &> /dev/null ; then
+ cat 1>&2 << EOF
+ERROR: To make a customized image of Windows PE, we need the wimlib-imagex program
+from "wimlib" so that we can modify the boot.wim file. However, wimlib-imagex
doesn't seem to be installed. Please install "wimlib" to continue.
EOF
exit 1
if [ $make = iso ]; then
if ! type -P mkisofs &> /dev/null ; then
- cat << EOF
+ cat 1>&2 << EOF
ERROR: To make a bootable ISO image of Windows PE, we need the "mkisofs"
program, but it doesn't seem to be installed. Please install the "cdrkit"
package to continue, or try omitting the --iso option to make a disk image
fi
elif [ $make = disk ] ; then
if ! type -P syslinux &> /dev/null ; then
- cat << EOF
+ cat 1>&2 << EOF
ERROR: To make a bootable disk image of Windows PE, we need the "syslinux"
program, but it doesn't seem to be installed. Please install the "syslinux"
package to continue, or try using the --iso option to make an ISO image instead
fi
if ! type -P mformat mcopy &> /dev/null; then
- cat << EOF
+ cat 1>&2 << EOF
ERROR: To make a bootable disk image of Windows PE, we need the "mformat" and
"mcopy" programs from the "mtools" package. These programs allow us to
format a FAT filesystem and copy files to it without needing root privileges.
fi
fi
- if [ -n "$waik_dir" ]; then
+ if [ -n "$waik_dir" ] && [ -f "$waik_dir"/wAIK${arch}.msi ]; then
if ! type -P cabextract &> /dev/null ; then
- cat << EOF
+ cat 1>&2 << EOF
ERROR: The boot files in the Windows Automated Installation Kit (WAIK) are
inside cabinet archives. To extract these files, we need the "cabextract"
program, but it doesn't seem to be installed. Please install "cabextract" to
get_primary_boot_files() {
if [ -n "$waik_dir" ]; then
# Get boot files from the WAIK.
-
stat_busy "Copying primary boot files from the Windows Automated Installation Kit ($waik_dir, $arch)"
- if [ $make = iso ]; then
- cabextract "$waik_dir"/wAIK${arch}.msi -F F_WINPE_${arch}_etfsboot.com -p \
- > "$tmp_dir"/etfsboot.com || stat_fail
+
+ if [ -f "$waik_dir"/wAIK${arch}.msi ]; then
+ if [ $make = iso ]; then
+ cabextract "$waik_dir"/wAIK${arch}.msi -F F_WINPE_${arch}_etfsboot.com -p \
+ > "$tmp_dir"/etfsboot.com || stat_fail
+ fi
+ cabextract "$waik_dir"/wAIK${arch}.msi -F F${arch_id}_BOOTMGR -p \
+ > "$tmp_dir"/bootmgr || stat_fail
+ cabextract "$waik_dir"/wAIK${arch}.msi -F F_WINPE_${arch}_boot.sdi -p \
+ > "$tmp_dir"/boot/boot.sdi || stat_fail
+ cabextract "$waik_dir"/wAIK${arch}.msi -F F_WINPE_${arch}_bcd -p \
+ > "$tmp_dir"/boot/bcd || stat_fail
+ # The WAIK supplement disc has a different structure
+ else
+ # Note: fuseiso, mount default to map=normal i.e. lowercase
+ if [ $make = iso ]; then
+ cp "$waik_dir"/${arch,,}/boot/etfsboot.com $tmp_dir/etfsboot.com || stat_fail
+ fi
+ cp "$waik_dir"/${arch,,}/bootmgr $tmp_dir/bootmgr || stat_fail
+ cp "$waik_dir"/${arch,,}/boot/boot.sdi $tmp_dir/boot/boot.sdi || stat_fail
+ cp "$waik_dir"/${arch,,}/boot/bcd $tmp_dir/boot/bcd || stat_fail
fi
- cabextract "$waik_dir"/wAIK${arch}.msi -F F${arch_id}_BOOTMGR -p \
- > "$tmp_dir"/bootmgr || stat_fail
- cabextract "$waik_dir"/wAIK${arch}.msi -F F_WINPE_${arch}_boot.sdi -p \
- > "$tmp_dir"/boot/boot.sdi || stat_fail
- cabextract "$waik_dir"/wAIK${arch}.msi -F F_WINPE_${arch}_bcd -p \
- > "$tmp_dir"/boot/bcd || stat_fail
stat_done
else
# Get boot files from the Windows ISO
# WIM file unspecified- grab it from the WAIK or the Windows DVD
if [ -n "$waik_dir" ]; then
# WAIK
- stat_busy "Extracting boot.wim from \"$waik_dir/WinPE.cab\""
- cabextract "$waik_dir/WinPE.cab" -F F${arch_id}_WINPE.WIM -p \
- > "$boot_wim" 2>/dev/null || stat_fail
+ if [ -f "$waik_dir/WinPE.cab" ]; then
+ stat_busy "Extracting boot.wim from \"$waik_dir/WinPE.cab\""
+ cabextract "$waik_dir/WinPE.cab" -F F${arch_id}_WINPE.WIM -p \
+ > "$boot_wim" 2>/dev/null || stat_fail
+ # WAIK supplement has different layout
+ else
+ stat_busy "Copying boot.wim from \"${waik_dir}/${arch,,}/winpe.wim\""
+ cp "$waik_dir"/${arch,,}/winpe.wim "$boot_wim" || stat_fail
+ chmod +w "$boot_wim"
+ fi
stat_done
else
# Windows DVD
remove_setup=yes
wim="$windows_dir/sources/boot.wim"
stat_busy "Exporting image from \"$wim\""
- "$imagex" export "$windows_dir"/sources/boot.wim 2 \
+ wimlib-imagex export "$windows_dir"/sources/boot.wim 2 \
--boot "$boot_wim" || stat_fail
stat_done
fi
fi
}
+# Make modifications to the WIM.
modify_boot_wim() {
boot_wim="$1"
- mnt_dir="$2"
-
- # Make modifications to the WIM.
- stat_busy "Mounting "$1" read-write"
-
- mkdir -p "$mnt_dir" || stat_fail
- "$imagex" mountrw "$boot_wim" "$mnt_dir"|| stat_fail
+ tmp_dir="$2"
- stat_done
+ exec 3>"$tmp_dir/__mkwinpeimg.update.cmds"
if [ -n "$remove_setup" ]; then
stat_busy "Renaming setup.exe to prevent it from bothering us"
- mv "$mnt_dir"/setup.exe{,.bkup} || stat_fail
- mv "$mnt_dir"/sources/setup.exe{,.bkup} || stat_fail
+ cat 1>&3 <<- EOF
+ rename /setup.exe /setup.exe.orig
+ rename /sources/setup.exe /sources/setup.exe.orig
+ EOF
stat_done
fi
if [ -n "$start_script" ]; then
- stat_busy "Setting \"$start_script\" as the script to be executed"\
- "when Windows PE boots"
- cp "$start_script" "$mnt_dir"|| stat_fail
- cat > "$mnt_dir/Windows/System32/winpeshl.ini" << EOF
-[LaunchApps]
-%SYSTEMDRIVE%\\$start_script
-EOF
+ stat_busy "Setting \"$start_script\" as the script to be executed when Windows PE boots"
+ start_script_base="$(basename "$start_script")"
+ cat > "$tmp_dir/__mkwinpeimg.winpeshl.ini" <<- EOF
+ [LaunchApps]
+ %SYSTEMDRIVE%\\$start_script_base
+ EOF
+ cat 1>&3 <<- EOF
+ add '$start_script' '/$start_script_base'
+ delete --force /Windows/System32/winpeshl.ini
+ add '$tmp_dir/__mkwinpeimg.winpeshl.ini' /Windows/System32/winpeshl.ini
+ EOF
stat_done
fi
if [ -n "$overlay" ]; then
stat_busy "Overlaying \"$overlay\" on the Windows PE filesystem"
- cp -r "$overlay"/* "$mnt_dir" || stat_fail
+ cat 1>&3 <<- EOF
+ add '$overlay' /
+ EOF
stat_done
fi
+ exec 3>&-
+
stat_busy "Rebuilding WIM with changes made"
- "$imagex" unmount --commit "$mnt_dir" || stat_fail
+ wimlib-imagex update "$boot_wim" --rebuild \
+ < "$tmp_dir/__mkwinpeimg.update.cmds" > /dev/null || stat_fail
stat_done
-
- rmdir "$mnt_dir"
}
make_iso_img() {
mkisofs -sysid "" -A "" -V "Microsoft Windows PE ($arch)" -d -N \
-b etfsboot.com -no-emul-boot -c boot.cat -hide etfsboot.com \
- -hide boot.cat -quiet -o "$image" "$tmp_dir" || stat_fail
+ -hide boot.cat -quiet -o "$image" "$tmp_dir" 1>&4 || stat_fail
stat_done
}
dd if=/dev/zero of="$image" count=$(( (image_size + 4095) / 4096)) \
bs=4096 &> /dev/null
- cat > "$mtool_conf" << EOF
-MTOOLS_SKIP_CHECK=1
-MTOOLS_FAT_COMPATIBILITY=1
-drive s:
- file="$image"
-EOF
+ cat > "$mtool_conf" <<- EOF
+ MTOOLS_SKIP_CHECK=1
+ MTOOLS_FAT_COMPATIBILITY=1
+ drive s:
+ file="$image"
+ EOF
export MTOOLSRC="$mtool_conf"
- mformat -h 255 -s 63 -T $(( image_size / 512)) s:
- mcopy -s "$tmp_dir"/* s:
+ mformat -h 255 -s 63 -T $(( image_size / 512)) s: || stat_fail
+ mcopy -s "$tmp_dir"/* s: || stat_fail
syslinux --install "$image"
- mcopy /usr/lib/syslinux/chain.c32 s:
- mcopy - 's:syslinux.cfg' << EOF
- DEFAULT winpe
- LABEL winpe
- COM32 chain.c32
- APPEND ntldr=/bootmgr
-EOF
+
+ syslinuxdir="/usr/lib/syslinux"
+
+ if [ -d "$syslinuxdir/bios" ]; then
+ biosdir="$syslinuxdir/bios"
+ else
+ biosdir="$syslinuxdir"
+ fi
+
+ mcopy "$biosdir/chain.c32" s: || stat_fail
+ if [ -e "$biosdir/libcom32.c32" ]; then
+ mcopy "$biosdir/libcom32.c32" s:
+ fi
+ if [ -e "$biosdir/libutil.c32" ]; then
+ mcopy "$biosdir/libutil.c32" s:
+ fi
+ mcopy - 's:syslinux.cfg' <<- EOF
+ DEFAULT winpe
+ LABEL winpe
+ COM32 chain.c32
+ APPEND ntldr=/bootmgr
+ EOF
rm -f "$mtool_conf"
stat_done
}
calc_columns
tmp_dir="$(mktemp -d)"
-mnt_dir="$tmp_dir"/.boot.wim.mount
process_command_line "$@"
+
+if [ "$image" = "-" ] ; then
+ # Writing image to standard output
+ if [ "$make" != iso ]; then
+ echo 1>&2 "ERROR: Writing image to standard output is only supported in --iso mode!"
+ exit 1
+ fi
+ # We can't print anything to standard output except the ISO image
+ # itself. Play with the file descriptors.
+
+ exec 4>&1 # 4 is now the original standard output.
+ exec 1>&2 # Anything that goes to standard output now, by default,
+ # actually goes to standard error.
+else
+ exec 4>&1 # 4 is now a copy of standard output
+fi
if [ -z "$waik_dir" ]; then
find_windows_dir
fi
get_boot_wim "$boot_wim"
if [ -n "$modify_wim" ]; then
- modify_boot_wim "$boot_wim" "$mnt_dir"
+ modify_boot_wim "$boot_wim" "$tmp_dir"
fi
if [ $make = iso ]; then
make_disk_img "$image"
fi
-echo "The image ($image) is $(stat -c %s "$image") bytes."
+if [ "$image" != "-" ]; then
+ echo "The image ($image) is $(stat -c %s "$image") bytes."
+fi