]> wimlib.net Git - wimlib/blobdiff - programs/mkwinpeimg.in
mkwinpeimg: Make sure all error messages go to stderr
[wimlib] / programs / mkwinpeimg.in
index 805b2bd60a1e2fb94c0c772d7274d7ee496cdb7f..697ffb82cddd85c265d18708d31c75689146ccf2 100755 (executable)
@@ -18,7 +18,7 @@
 # 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@
@@ -94,13 +94,14 @@ Usage: $script_name [OPTIONS] IMAGE
   -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".
@@ -115,7 +116,7 @@ EOF
 }
 
 version() {
-       echo "$script_name (wimlib $WIMLIB_VERSION)"
+       echo "$script_name (distributed with wimlib $WIMLIB_VERSION)"
        exit 0
 }
 
@@ -147,7 +148,7 @@ process_command_line() {
                        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
@@ -155,7 +156,7 @@ process_command_line() {
                -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
@@ -191,7 +192,7 @@ process_command_line() {
                                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
@@ -208,7 +209,7 @@ process_command_line() {
                        break
                        ;;
                *)
-                       echo "Invalid option \"$1\""
+                       echo 1>&2 "Invalid option \"$1\""
                        usage
                        exit 1
                        ;;
@@ -217,8 +218,8 @@ process_command_line() {
        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"
@@ -235,17 +236,17 @@ find_windows_dir() {
        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
@@ -255,8 +256,8 @@ EOF
 
 check_needed_programs() {
        if [ -z "$waik_dir" -o -n "$modify_wim" ]; then
-               if ! type -P @IMAGEX_PROGNAME@ &> /dev/null ; then
-                       cat << EOF
+               if ! type -P "$imagex" &> /dev/null ; then
+                       cat 1>&2 << 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"
 doesn't seem to be installed.  Please install "wimlib" to continue.
@@ -267,7 +268,7 @@ EOF
 
        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
@@ -277,7 +278,7 @@ EOF
                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
@@ -287,7 +288,7 @@ EOF
                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.
@@ -297,9 +298,9 @@ EOF
                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
@@ -314,18 +315,29 @@ EOF
 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
@@ -350,9 +362,16 @@ get_boot_wim() {
                # 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
@@ -389,13 +408,13 @@ modify_boot_wim() {
 
        if [ -n "$start_script" ]; then
                stat_busy "Setting \"$start_script\" as the script to be executed when Windows PE boots"
-               cp "$start_script" "$tmp_dir/$start_script"
+               start_script_base="$(basename "$start_script")"
                cat > "$tmp_dir/__mkwinpeimg.winpeshl.ini" <<- EOF
                        [LaunchApps]
-                       %SYSTEMDRIVE%\\$start_script
+                       %SYSTEMDRIVE%\\$start_script_base
                EOF
                cat 1>&3 <<- EOF
-                       add '$tmp_dir/$start_script' '/$start_script'
+                       add '$start_script' '/$start_script_base'
                        delete --force /Windows/System32/winpeshl.ini
                        add '$tmp_dir/__mkwinpeimg.winpeshl.ini' /Windows/System32/winpeshl.ini
                EOF
@@ -427,7 +446,7 @@ 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
 }
@@ -454,11 +473,26 @@ make_disk_img() {
 
        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:
+
+       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
@@ -472,6 +506,22 @@ make_disk_img() {
 calc_columns
 tmp_dir="$(mktemp -d)"
 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
@@ -504,4 +554,6 @@ elif [ $make = disk ]; 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