当您启动 Windows 10 ISO 时,您将收到以下误导性提示: 为什么会产生误导?因为在您实际上已经从 Windows ISO 启动之后,此消息来自 Windows ISO 本身。此提示是一项功能,旨在防止您意外启动 Windows 映像。
现在,我有一个非常具体的用例,该提示使我无法自动创建和安装基于 UEFI 的 Windows 10 VM。
noprompt
因此,我进行了一些挖掘,在 Windows 上,您可以通过在启动项上指定映像来创建 Windows ISO,无需提示,如下所示:
$setfsboot="C:\01_TEMP\ISO\etfsboot.com"
$sefisys ="C:\01_TEMP\ISO\efisys_noprompt.bin"
Oscdimg -bootdata:2#p0,eb$setfsboot#pEF,e,b$sefisys -u1
-udfver102 C:\winpe_amd64\media C:\winpe_amd64\winpeamd64.iso
快速解释
-bootdata:2#p0,eb$setfsboot#pEF,e,b$sefisys
2
表示有2个启动项#
分隔器p0,eb$setfsboot
是默认启动项(用于旧版 BIOS 启动)#
分隔器pEF,e,b$sefisys
是后备启动项(用于 UEFI 启动)
现在我尝试使用 mkisofs 在 Linux 上实现同样的目标,这非常棘手,因为只是为了制作可 UEFI 启动的 Windows ISO,您需要上游版本mkisofs
(请参阅mkey 的这篇文章) (可得到这里.)Linux 发行版附带的版本mkisofs
显然缺乏一些功能,并且其中存在从未修复的古老错误。
我尝试删除efi/microsoft/boot/cdboot.efi
然后重命名efi/microsoft/boot/cdboot_noprompt.efi
为efi/microsoft/boot/cdboot.efi
以欺骗 ISO,但不幸的是这没有用。
目前我使用以下代码直接从 ISO 中提取启动映像:
BOOT_LOAD_SEG="$(dumpet -i "${WIN10_IMG}" | grep "Media load segment: " | cut -d ':' -f2 | cut -d ' ' -f2)"
BOOT_LOAD_SIZE="$(dumpet -i "${WIN10_IMG}" | grep "Load Sectors: " | grep -o "[^:]*$" | cut -d ' ' -f2 | head -1)"
EFI_STARTING_SECTOR="$(dumpet -i "${WIN10_IMG}" | grep "Load LBA: " | grep -o "[^:]*$" | cut -d ' ' -f2 | tail -1)"
echo "EFI_STARTING_SECTOR: $EFI_STARTING_SECTOR"
sudo dd if="${WIN10_IMG}" of="${TMP}/efi.dmp" bs=2048 count=1 skip="${EFI_STARTING_SECTOR}"
EFI_BOOT_LOAD_SIZE="$(file "${TMP}/efi.dmp" | grep -oP 'sectors (\d+)' | cut -d ' ' -f2)"
echo "EFI_BOOT_LOAD_SIZE: ${EFI_BOOT_LOAD_SIZE}"
sudo dd if="${WIN10_IMG}" of="${ISO_FILES}/efi/win_efi_boot.img" bs=2048 count="${EFI_BOOT_LOAD_SIZE}" skip="${EFI_STARTING_SECTOR}"
在上面的最后一个命令中,提取的图像被放置在包含从 ISO 提取的文件的文件夹中。
然后使用-eltorito-boot "efi/win_efi_boot.img"
标志 for mkisofs
,我告诉它使用它作为启动项。
我编写了一个脚本,可以自动设置您需要的一切,以便达到我现在的水平。如果您查看STEP 5
脚本,您可以看到我尝试更改文件名,但我认为,我可能必须更改STEP 4
,但我只是不知道如何更改。
#!/usr/bin/env bash
#You might have to install a few dependencies for schily tools to compile.
#On Fedora this did the trick for me: `sudo dnf install e2fsprogs-devel imake gcc-c++`
############ STEP 1 download Windows 10 ISO from Microsoft ##############
WIN10_IMG="$(pwd)/windows10.iso"
WIN10_IMG_ARCH="x64"
if [ ! -f "$WIN10_IMG" ]; then # if the windows10.iso has not been downloaded yet
if [[ "$WIN10_IMG_ARCH" == "x86" ]] || [[ "$WIN10_IMG_ARCH" == "i386" ]] ; then
echo "Retrieving the x86 Windows 10 iso URL..."
WINDOWS_10_ISO_URL=$(curl -LsI -o /dev/null -w %{url_effective} "https://tb.rg-adguard.net/dl.php?go=7e583fea") # This strange looking URL actually redirects to a legit software-download.microsoft.com URL
else
echo "Retrieving the x64 Windows 10 iso URL..."
WINDOWS_10_ISO_URL=$(curl -LsI -o /dev/null -w %{url_effective} "https://tb.rg-adguard.net/dl.php?go=3dd1ce66") # This strange looking URL actually redirects to a legit software-download.microsoft.com URL
fi
echo "Download URL: $WINDOWS_10_ISO_URL"
echo "Making sure the URL comes from a trusted Microsoft domain..."
if [[ $WINDOWS_10_ISO_URL == https://software-download.microsoft.com/* ]] ; then
echo "Downloading the Windows 10 installation iso..."
wget "$WINDOWS_10_ISO_URL" -O "$WIN10_IMG"
else
echo "URL validation failed. Please download the Windows 10 iso manually."
exit 1
fi
fi
#########################################################################
############## STEP 2 download and build the schily tools ###############
SCHILY_VERSION="2021-06-07"
SCHILY_ARCHIVE="schily-${SCHILY_VERSION}.tar.bz2"
SCHILY_DIR="./schily-tools"
if [ ! -f "${SCHILY_DIR}/mkisofs/OBJ/x86_64-linux-gcc/mkisofs" ]; then # if the mkisofs of Schily Tools has not been built yet
sudo rm -rf "${SCHILY_DIR}"
wget "https://altushost-swe.dl.sourceforge.net/project/schilytools/${SCHILY_ARCHIVE}" -O "${SCHILY_ARCHIVE}"
tar -xf "${SCHILY_ARCHIVE}"
rm "${SCHILY_ARCHIVE}"
mv "schily-${SCHILY_VERSION}" "${SCHILY_DIR}"
cd "${SCHILY_DIR}"
./Gmake.linux
cd ..
if [ ! -f "${SCHILY_DIR}/mkisofs/OBJ/x86_64-linux-gcc/mkisofs" ]; then
echo "Building Schily Tools failed"
exit 1
fi
fi
#########################################################################
################# STEP 3 Extract the files from the ISO #################
TMP="./tmp"
ISO_FILES="${TMP}/iso-files"
ISO_MP="${TMP}/iso-mountpoint"
if [ ! -f "${ISO_FILES}/setup.exe" ]; then # If the Windows ISO hasn't been extracted yet
sudo rm -rf "${TMP}"
mkdir -p "${ISO_FILES}"
mkdir -p "${ISO_MP}"
sudo mount -t udf "${WIN10_IMG}" "${ISO_MP}"
sudo cp -Rva ${ISO_MP}/* "${ISO_FILES}"
sudo umount "${ISO_MP}"
fi
#########################################################################
################## STEP 4 Extract the EFI boot image ####################
# Extract boot load segment address and size
BOOT_LOAD_SEG="$(dumpet -i "${WIN10_IMG}" | grep "Media load segment: " | cut -d ':' -f2 | cut -d ' ' -f2)"
BOOT_LOAD_SIZE="$(dumpet -i "${WIN10_IMG}" | grep "Load Sectors: " | grep -o "[^:]*$" | cut -d ' ' -f2 | head -1)"
EFI_STARTING_SECTOR="$(dumpet -i "${WIN10_IMG}" | grep "Load LBA: " | grep -o "[^:]*$" | cut -d ' ' -f2 | tail -1)"
echo "EFI_STARTING_SECTOR: $EFI_STARTING_SECTOR"
sudo dd if="${WIN10_IMG}" of="${TMP}/efi.dmp" bs=2048 count=1 skip="${EFI_STARTING_SECTOR}"
EFI_BOOT_LOAD_SIZE="$(file "${TMP}/efi.dmp" | grep -oP 'sectors (\d+)' | cut -d ' ' -f2)"
echo "EFI_BOOT_LOAD_SIZE: ${EFI_BOOT_LOAD_SIZE}"
sudo dd if="${WIN10_IMG}" of="${ISO_FILES}/efi/win_efi_boot.img" bs=2048 count="${EFI_BOOT_LOAD_SIZE}" skip="${EFI_STARTING_SECTOR}"
#########################################################################
######## STEP 5 Make changes to the files extracted from the ISO ########
# Make some arbitrary changes to the iso files
#sudo rm -rf "${ISO_FILES}/efi/microsoft/boot/cdboot.efi"
#sudo mv "${ISO_FILES}/efi/microsoft/boot/cdboot_noprompt.efi" "${ISO_FILES}/efi/microsoft/boot/cdboot.efi"
#sudo rm -rf "${ISO_FILES}/efi/microsoft/boot/efisys.bin"
#sudo mv "${ISO_FILES}/efi/microsoft/boot/efisys_noprompt.bin" "${ISO_FILES}/efi/microsoft/boot/efisys.bin"
#########################################################################
###### STEP 6 Build a new ISO using the extracted/modified files ########
sudo rm -f "${WIN10_IMG}.tmp.iso"
sudo "${SCHILY_DIR}/mkisofs/OBJ/x86_64-linux-gcc/mkisofs" \
-no-emul-boot \
-b boot/etfsboot.com \
-boot-load-seg "${BOOT_LOAD_SEG}" \
-boot-load-size "${BOOT_LOAD_SIZE}" \
-eltorito-alt-boot \
-no-emul-boot \
-eltorito-boot "efi/win_efi_boot.img" \
-boot-load-size 1 \
-iso-level 4 \
-UDF \
-o "${WIN10_IMG}.tmp.iso" \
"${ISO_FILES}"
#########################################################################
############ STEP 7 Remove the files exxtracted from the ISO ############
#sudo rm -f "${TMP}"
#########################################################################
答案1
可以将iso修改为efi-boot而不提示如下:
7z x windows.iso -oiso-unpack
mkisofs -b boot/etfsboot.com -no-emul-boot -c BOOT.CAT -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -v -V "Custom" -udf -boot-info-table -eltorito-alt-boot -eltorito-boot efi/microsoft/boot/efisys_noprompt.bin -no-emul-boot -o install.iso -allow-limited-size iso-unpack
注意:这需要 schilytools 中的 mkisofs(由于许可问题,未针对大多数发行版打包)或 genisoimage 中的替代二进制文件(针对大多数发行版打包)。无法使用替代二进制 xorriso,因为它不支持 UDF。
答案2
您尚未分享任何有关您尝试失败的位置/方式的错误消息。
您正在做的扰乱 UEFI 启动过程的方法似乎距离您所说的想要做的事情还有很长的路要走。
大多数进行大型虚拟机部署的地方要么使用某种预先构建且经过验证的模板映像,该映像被克隆以生成新的 Win10 实例,要么执行 OEM 风格无人值守安装使用 Windows PE 创建.WIM
文件来构建环境并选择选项。
您为 OSCdimg 链接的部分只是授权硬件制造商可用于新硬件部署的工具之一。我敢打赌,除了重新创建 ISO 映像之外,它还执行与 Linux 中的 efibootmgr 类似的功能。它的部分功能是对生成的文件进行签名,我不明白为什么 MS 会在该目录中包含一个公共证书文件,这将允许他们在没有网络访问的情况下对其二进制文件进行签名验证。
附录:阅读了一些 EFI 规范(你也应该阅读)。你有没有想过告诉 mkisofs 使用
-eltorito-boot efi\microsoft\boot\cdboot_noprompt.efi
我不确定 uefi 想要它的目录分隔符的哪种方式,因为根据规范它应该支持 FAT 并且在我拥有的编辑器中查看 ISO,有一个 UDF 分区这就是我得到那条路的地方。
我从以下方面得到了一些很好的见解: https://www.happyassassin.net/posts/2014/01/25/uefi-boot-how-does-that-actually-work-then/