如何修改安裝 ISO 並使其保持可啟動狀態?
我知道有很多類似的問題,但它們不夠具體。
我有一個 Windows 10 x64 安裝 ISO,我正在嘗試提取文件進行一些修改,然後從提取/修改的文件中創建一個新的 ISO。
它基本上工作得很好,但問題是我不知道如何讓它再次啟動 UEFI(在傳統/BIOS 模式下它啟動得很好)。
按照有關如何執行此操作的說明,我瀏覽了無數文章,但沒有一個適用於我的 Windows 10 ISO。這些文章中的大多數只提到了舊版本的 Windows,而那些提到 Windows 10 的文章並沒有說明他們是否讓它與目前的 x64 版本一起工作,以及他們是否能夠從它進行 UEFI 引導。(可能不是,因為它肯定不適合我。)
我最終試圖盡可能多地複制
isoinfo -d -i ./windows10.iso
輸出dumpet -i ./windows10.iso
。這是我所能得到的最接近的:(編輯:更新
-eltorito-alt-boot
為電信公司的建議)原始 ISO(isoinfo):
$ isoinfo -d -i ./original.iso CD-ROM is in ISO 9660 format System id: Volume id: CCCOMA_X64FRE_EN-US_DV9 Volume set id: CCCOMA_X64FRE_EN-US_DV9 Publisher id: MICROSOFT CORPORATION Data preparer id: MICROSOFT CORPORATION, ONE MICROSOFT WAY, REDMOND WA 98052, (425) 882-8080 Application id: CDIMAGE 2.56 (01/01/2005 TM) Copyright File id: Abstract File id: Bibliographic File id: Volume set size is: 1 Volume set sequence number is: 1 Logical block size is: 2048 Volume size is: 2411879 El Torito VD version 1 found, boot catalog is in sector 22 NO Joliet present NO Rock Ridge present Eltorito validation header: Hid 1 Arch 0 (x86) ID 'Microsoft Corporation' Key 55 AA Eltorito defaultboot header: Bootid 88 (bootable) Boot media 0 (No Emulation Boot) Load segment 0 Sys type 0 Nsect 8 Bootoff 202 514
修改後的 ISO (isoinfo):
$ isoinfo -d -i ./modified.iso CD-ROM is in ISO 9660 format System id: Volume id: CCCOMA_X64FRE_EN-US_DV9 Volume set id: CCCOMA_X64FRE_EN-US_DV9 Publisher id: Microsoft Corporation Data preparer id: MICROSOFT CORPORATION, ONE MICROSOFT WAY, REDMOND WA 98052, (425) 882-8080 Application id: CDIMAGE 2.56 (01/01/2005 TM) Copyright File id: Abstract File id: Bibliographic File id: Volume set size is: 1 Volume set sequence number is: 1 Logical block size is: 2048 Volume size is: 2411275 El Torito VD version 1 found, boot catalog is in sector 1506 NO Joliet present NO Rock Ridge present Eltorito validation header: Hid 1 Arch 0 (x86) ID 'Microsoft Corporation' Key 55 AA Eltorito defaultboot header: Bootid 88 (bootable) Boot media 0 (No Emulation Boot) Load segment 0 Sys type 0 Nsect 8 Bootoff 8CD 2253
上述 isoinfo 輸出之間的區別:
$ diff <(isoinfo -i ./original.iso) <(isoinfo -i ./modified.iso) 5c5 < Publisher id: MICROSOFT CORPORATION --- > Publisher id: Microsoft Corporation 14,15c14,15 < Volume size is: 2411879 < El Torito VD version 1 found, boot catalog is in sector 22 --- > Volume size is: 2411275 > El Torito VD version 1 found, boot catalog is in sector 1506 29c29 < Bootoff 202 514 --- > Bootoff 8CD 2253
原始 ISO(已轉儲):
$ dumpet -i ./original.iso Validation Entry: Header Indicator: 0x01 (Validation Entry) PlatformId: 0x00 (80x86) ID: "Microsoft Corporation" Checksum: 0x494c Key bytes: 0x55aa Boot Catalog Default Entry: Entry is bootable Boot Media emulation type: no emulation Media load segment: 0x0 (0000:7c00) System type: 0 (0x00) Load Sectors: 8 (0x0008) Load LBA: 514 (0x00000202) Section Header Entry: Header Indicator: 0x91 (Final Section Header Entry) PlatformId: 0xef (EFI) Section Entries: 1 ID: "" Boot Catalog Section Entry: Entry is bootable Boot Media emulation type: no emulation Media load address: 0 (0x0000) System type: 0 (0x00) Load Sectors: 1 (0x0001) Load LBA: 516 (0x00000204)
修改後的 ISO (dumpet):
$ dumpet -i ./modified.iso Validation Entry: Header Indicator: 0x01 (Validation Entry) PlatformId: 0x00 (80x86) ID: "Microsoft Corporation" Checksum: 0x494c Key bytes: 0x55aa Boot Catalog Default Entry: Entry is bootable Boot Media emulation type: no emulation Media load segment: 0x0 (0000:7c00) System type: 0 (0x00) Load Sectors: 8 (0x0008) Load LBA: 2253 (0x000008cd) Section Header Entry: Header Indicator: 0x91 (Final Section Header Entry) PlatformId: 0xef (EFI) Section Entries: 1 ID: "" Boot Catalog Section Entry: Entry is bootable Boot Media emulation type: no emulation Media load address: 0 (0x0000) System type: 0 (0x00) Load Sectors: 2984 (0x0ba8) Load LBA: 1507 (0x000005e3)
上述轉儲輸出之間的區別:
$ diff <(dumpet -i ./original.iso) <(dumpet -i ./modified.iso) 13c13 < Load LBA: 514 (0x00000202) --- > Load LBA: 2253 (0x000008cd) 24,25c24,25 < Load Sectors: 1 (0x0001) < Load LBA: 516 (0x00000204) --- > Load Sectors: 2984 (0x0ba8) > Load LBA: 1507 (0x000005e3)
我已經編寫了一個腳本,以使用我正在使用的相同 ISO 完全重現該問題:
#!/usr/bin/env bash ################################## # Download the Windows 10 x64 ISO WIN10_IMG_DESTINATION="./windows.iso" WIN10_IMG_ARCH="x64" if [ ! -f "${WIN10_IMG_DESTINATION}" ]; then 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://windows101tricks.com/1903-iso-32") else echo "Retrieving the x64 Windows 10 iso URL..." WINDOWS_10_ISO_URL=$(curl -LsI -o /dev/null -w %{url_effective} "https://windows101tricks.com/1903-iso-64") fi echo "Making sure the URL comes from a trusted Microsoft (sub)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_DESTINATION" else echo "URL validation failed. Please download the Windows 10 iso manually." exit 1 fi else echo "Windows 10 iso already exists. Skipping download..." fi # ################################## # Variable containing the path to the windows.iso WIN10_IMG="$WIN10_IMG_DESTINATION" TMP="./tmp" ISO_FILES="${TMP}/iso-files" ISO_MP="${TMP}/iso-mountpoint" # Remove ./tmp if it already exists, then create ./tmp/iso-files and ./tmp/iso-mountpoint rm -rf "${TMP}" mkdir -p "${ISO_FILES}" mkdir -p "${ISO_MP}" # Extract the files fromt he ISO to ./tmp/iso-files sudo mount -t udf "${WIN10_IMG}" "${ISO_MP}" sudo cp -Rva ${ISO_MP}/* "${ISO_FILES}" sudo umount "${ISO_MP}" # Make modifications to the Windows ISO #BOOT_DIR="${ISO_FILES}/efi/microsoft/boot" #sudo mv "${BOOT_DIR}/cdboot.efi" "${BOOT_DIR}/tmp.efi" #sudo mv "${BOOT_DIR}/cdboot_noprompt.efi" "${BOOT_DIR}/cdboot.efi" #sudo mv "${BOOT_DIR}/tmp.efi" "${BOOT_DIR}/cdboot_noprompt.efi" # Extract the boot.img (didn't help at all) #BOOT_SECTOR_LENGTH="$(isoinfo -d -i "${WIN10_IMG}" | grep "Nsect " | grep -o "[^ ]*$")" #STARTING_SECTOR="$(isoinfo -d -i ./vm-files/windows10.iso | grep "Bootoff " | grep -o "[^ ]*$")" #dd if="${WIN10_IMG}" of="${ISO_FILES}/boot.img" bs=2048 count="${BOOT_SECTOR_LENGTH}" skip="${STARTING_SECTOR}" # 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)" # Extract meta data : SYSTEM_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "System id: " | cut -d ' ' -f3-)" VOLUME_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Volume id: " | cut -d ' ' -f3-)" VOLUME_SET_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Volume set id: " | cut -d ' ' -f4-)" #PUBLISHER_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Publisher id: " | cut -d ' ' -f3-)" # Always uppercase PUBLISHER_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "ID '" | cut -d "'" -f2)" DATA_PREPARER_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Data preparer id: " | cut -d ' ' -f4-)" APPLICATION_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Application id: " | cut -d ' ' -f3-)" COPYRIGHT_FILE_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Copyright file id: " | cut -d ' ' -f4-)" ABSTRACT_FILE_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Abstract file id: " | cut -d ' ' -f4-)" BIBLIOGRAPHIC_FILE_ID="$(isoinfo -d -i "${WIN10_IMG}" | grep "Bibliographic file id: " | cut -d ' ' -f4-)" # Create a new ISO image using mkisofs # (.mkisofsrc is necessary, because some options are not available on the cli directly) rm ".mkisofsrc" echo "APPI=${APPLICATION_ID}" >> ".mkisofsrc" echo "COPY=${COPYRIGHT_FILE_ID}" >> ".mkisofsrc" echo "ABST=${ABSTRACT_FILE_ID}" >> ".mkisofsrc" echo "BIBL=${BIBLIOGRAPHIC_FILE_ID}" >> ".mkisofsrc" echo "PREP=${DATA_PREPARER_ID}" >> ".mkisofsrc" echo "PUBL=${PUBLISHER_ID}" >> ".mkisofsrc" echo "SYSI=${SYSTEM_ID}" >> ".mkisofsrc" echo "VOLI=${VOLUME_ID}" >> ".mkisofsrc" echo "VOLS=${VOLUME_SET_ID}" >> ".mkisofsrc" sudo rm "${WIN10_IMG}.tmp.iso" sudo mkisofs \ -no-emul-boot \ -b boot/etfsboot.com \ -boot-load-seg "${BOOT_LOAD_SEG}" \ -boot-load-size "${BOOT_LOAD_SIZE}" \ -eltorito-alt-boot \ -e efi/boot/bootx64.efi \ -no-emul-boot \ -iso-level 2 \ -boot-info-table \ -udf \ -D \ -N \ -relaxed-filenames \ -allow-lowercase \ -o "${WIN10_IMG}.tmp.iso" \ "${ISO_FILES}" rm ".mkisofsrc" # Print the variables that we gathered echo echo "Extracted meta data (form original image):" echo "BOOT_LOAD_SEG: ${BOOT_LOAD_SEG}" echo "BOOT_LOAD_SIZE: ${BOOT_LOAD_SIZE}" echo "-------" echo "SYSTEM_ID: ${SYSTEM_ID}" echo "VOLUME_ID: ${VOLUME_ID}" echo "VOLUME_SET_ID: ${VOLUME_SET_ID}" echo "PUBLISHER_ID: ${PUBLISHER_ID}" echo "DATA_PREPARER_ID: ${DATA_PREPARER_ID}" echo "APPLICATION_ID: ${APPLICATION_ID}" echo "COPYRIGHT_FILE_ID: ${COPYRIGHT_FILE_ID}" echo "ABSTRACT_FILE_ID: ${ABSTRACT_FILE_ID}" echo "BIBLIOGRAPHIC_FILE_ID: ${BIBLIOGRAPHIC_FILE_ID}" # Show difference between new and old image as reported by isoinfo echo echo "-------------- isoinfo diff -----------------" diff <(isoinfo -d -i "${WIN10_IMG}") <(isoinfo -d -i "${WIN10_IMG}.tmp.iso") # Show difference between new and old image as reported by dumpet echo echo " -------------- dumpet diff -----------------" diff <(dumpet -i "${WIN10_IMG}") <(dumpet -i "${WIN10_IMG}.tmp.iso") # Overwrite the original ISO with the new one #sudo rm "${WIN10_IMG}" #sudo mv "${WIN10_IMG}.tmp.iso" "${WIN10_IMG}"
為了擴展和說明@telcoM 上面提供的有用資訊,我提供了這個過程,它使我獲得了一個工作(即EFI 可引導
Wn10_20H2_v2_English_x64.iso
)ISO。我的意圖是拆分install.wim
文件以允許從 FAT32 USB 驅動器安裝並與Ventoy 一起使用簡單的 ISO 。快速概覽:
- 使用Schily 工具解決可能出現的
mkisofs
問題- 使用Wimlib拆分
wim
存檔- 使用 telcoM 的方法從 ISO 中提取啟動磁片映像。似乎對於使用實際的磁片映像至關重要。
boofx64.efi
其中包含的文件似乎與efi/boot/
目錄中的文件不同- ISO 建構過程是半自動化的,因為系統會提示使用者輸入磁片映像 LBA 和最終大小(大概總是 720 個扇區)
劇本:
#!/bin/bash # provide paths, no closing / ISO_IMAGE="/path/to/Win10.iso" ISO_IMAGE_OUT="/path/to/Win10_split.iso" WORKING_DIR="/home/user/working" echo "Paths set" echo "ISO_IMAGE $ISO_IMAGE" echo "WORKING DIRECTORY: $WORKING_DIR" # prerequisites # sudo apt-get install libxml2-dev ntfs-3g-dev libfuse-dev libattr1-dev dumpet # install schily tools http://schilytools.sourceforge.net/ # alias smake=/opt/schily/bin/smake # alias mkisofs=/opt/schily/bin/mkisofs # install wimlib https://wimlib.net/ # git clone git://wimlib.net/wimlib # cd wimlib # libtoolize --force # aclocaldc # autoheader # automake --force-missing --add-missing # autoconf # ./configure # sudo make install # gsudo ldconfig -v printf "\nRemoving/recreating the working directory\n" rm -r -d -f $WORKING_DIR mkdir $WORKING_DIR printf "\nMounting the ISO image\n" sudo mount -r -t udf $ISO_IMAGE /media/iso printf "\nCopying the ISO image contents to the working directory\n" cp -r /media/iso/* $WORKING_DIR chmod -R 755 $WORKING_DIR printf "\nUnmounting the ISO image\n" sudo umount /media/iso printf "\nSplitting the install.wim archive\n" wimsplit $WORKING_DIR/sources/install.wim $WORKING_DIR/sources/install.swm 2000 rm -d -f $WORKING_DIR/sources/install.wim printf "\nGetting the boot image LBA from the ISO\n----------\n" dumpet -i $ISO_IMAGE printf "\nShould be a integer number following the second 'Load LBA': " read LOAD_LBA printf "\n" dd if=$ISO_IMAGE bs=2048 skip=$LOAD_LBA count=1 > $WORKING_DIR/efi/win_efi_boot.img printf "\nNow we get the boot.img and check the right file size.\nThe below output should detect a 'DOS/MBR boot sector' and sectors size should be 2880 which would mean 2880 * 512 / 2048 = 720.\n----------\n" file $WORKING_DIR/efi/win_efi_boot.img printf "\nThat would make the input 720: " read LOAD_COUNT printf "\n" dd if=$ISO_IMAGE bs=2048 skip=$LOAD_LBA count=$LOAD_COUNT > $WORKING_DIR/efi/win_efi_boot.img printf "\nBuilding an image\n" /opt/schily/bin/mkisofs \ -no-emul-boot \ -b boot/etfsboot.com \ -boot-load-seg 0 \ -boot-load-size 8 \ -eltorito-alt-boot \ -no-emul-boot \ -b efi/win_efi_boot.img \ -boot-load-size 1 \ -iso-level 4 \ -UDF \ -o $ISO_IMAGE_OUT \ $WORKING_DIR/ printf "\n\nImage ready!\n\n"
輸出表明原始
dumpet
文件包含兩個 ElTorito 引導映像:一個用於 BIOS 樣式引導,另一個用於 UEFI。使用選項為 BIOS 指定第一個引導映像後mkisofs
,您需要使用-eltorito-alt-boot
和-eltorito-platform efi
選項來指定第二個引導映像。像這樣的東西:sudo mkisofs \ -no-emul-boot \ -b boot/etfsboot.com \ -boot-load-seg "${BOOT_LOAD_SEG}" \ -boot-load-size "${BOOT_LOAD_SIZE}" \ -eltorito-alt-boot \ -b <UEFI boot image name here> \ -eltorito-platform efi \ [...]
我不確定哪個文件可以用作 UEFI 啟動映像。
更新:我得到了一個原始的 Windows 10 ISO 映像,並做了一些實驗。在我的版本中,
Load LBA
UEFI 啟動項的值為 519。記住 CD-ROM 塊大小為 2048 字節,我轉儲了該塊:$ dd if=<silly_long_name>.iso bs=2048 skip=519 count=1 > win_efi_boot.dmp $ file win_efi_boot.dmp win_efi_boot.dmp: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "MSDOS5.0", root entries 224, sectors 2880 (volumes <=32 MB) , sectors/FAT 9, sectors/track 18, serial number 0xef56c0, label: "EFISECTOR ", FAT (12 bit), followed by FAT
看起來像 1.4 MB 磁片映像的開頭。2880 個磁片扇區 * 每個磁片扇區 512 字節 / 每個 CD-ROM 扇區 2048 字節 = 720 個 CD-ROM 扇區。我猜韌體只是忽略了該
Load Sectors
值,並查看 FAT 引導扇區以找到實際大小。dd if=<silly_long_name>.iso bs=2048 skip=519 count=720 of=win_efi_boot.img
是的,它包含一個 (v)FAT12 文件系統,只有一個文件:
\EFI\BOOT\BOOTX64.EFI
,大小為 936352 字節。$ sudo mount -o loop,ro win_efi_boot.img /mnt $ ls -l /mnt/EFI/BOOT/BOOTX64.EFI -rwxr-xr-x 1 root root 936352 Apr 11 2018 /mnt/EFI/BOOT/BOOTX64.EFI
我還對文件進行了十六進制轉儲
win_efi_boot.img
:文件結束後BOOTX64.EFI
,磁片映像的其餘部分都填充了所有零字節,所以我認為count=720
是準確的。因此,您應該能夠執行相同的操作以從原始 ISO(如 my
win_efi_boot.img
)中提取 UEFI 引導文件系統映像,並根據您的-e
選擇使用它。