Repacking a Debian ISO with its original boot equipment
This page describes how to determine the ISO 9660 production command that was used when a Debian ISO image was packed up, and how to derive a command to replay this production. This is not trivial because of the special preparations which are needed to boot via the firmware of various computer architectures.
Contents
-
Repacking a Debian ISO with its original boot equipment
- What is a bootable ISO 9660 image ?
- Learn about the actually used ISO production command
- Remove the unneeded Jigdo production options
- Determine those options which need to be adapted on amd64 or i386
- CPU architectures other than i386 and amd64, older ISOs, Debian Live
- What to do if no file /.disk/mkisofs exists
- Methods to overwrite, delete, or add files
- See also:
- External Links
What is a bootable ISO 9660 image ?
It is a list of bytes which form a readily formatted read-only filesystem. The bytes may be brought on some medium like DVD or USB stick, or they may be exposed to the operating system as loop device. In all these cases the filesystem can be mounted and will show a tree of directories and files.
To be bootable by computer firmware, such an ISO image has to bear special entry points where the firmware can learn about the next step to do. This next step is normally the start of a bootloader system, which offers the user a menu of operating systems and is able to start the chosen one.
The entry points on i386 and amd64 systems are: El Torito, MBR, GPT. Similar entry points are defined for other architectures. The topic is wide and can be confusing. This article concentrates on achieving the same boot equipment as in the original ISO without much curiosity about how this equipment actually works.
Learn about the actually used ISO production command
The Debian installation ISO images contain a file
/.disk/mkisofs
which recorded this shell command. For example in debian-9.3.0-amd64-netinst.iso
xorriso -as mkisofs -r -checksum_algorithm_iso md5,sha1,sha256,sha512 -V 'Debian 9.3.0 amd64 n' -o /srv/cdbuilder.debian.org/dst/deb-cd/out/2amd64/debian-9.3.0-amd64-NETINST-1.iso -jigdo-jigdo /srv/cdbuilder.debian.org/dst/deb-cd/out/2amd64/debian-9.3.0-amd64-NETINST-1.jigdo -jigdo-template /srv/cdbuilder.debian.org/dst/deb-cd/out/2amd64/debian-9.3.0-amd64-NETINST-1.template -jigdo-map Debian=/srv/cdbuilder.debian.org/src/ftp/debian/ -jigdo-exclude boot1 -md5-list /srv/cdbuilder.debian.org/src/deb-cd/tmp/2amd64/stretch/md5-check -jigdo-min-file-size 1024 -jigdo-exclude 'README*' -jigdo-exclude /doc/ -jigdo-exclude /md5sum.txt -jigdo-exclude /.disk/ -jigdo-exclude /pics/ -jigdo-exclude 'Release*' -jigdo-exclude 'Packages*' -jigdo-exclude 'Sources*' -J -J -joliet-long -cache-inodes -isohybrid-mbr syslinux/usr/lib/ISOLINUX/isohdpfx.bin -b isolinux/isolinux.bin -c isolinux/boot.cat -boot-load-size 4 -boot-info-table -no-emul-boot -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus boot1 CD1
"xorriso" is the program that was used to pack up the ISO. The other words are xorriso command "-as" and its arguments, which are partly compatible with options and arguments of programs "mkisofs" and "genisoimage".
In older Debian ISOs or with architecture "powerpc" you will find "genisoimage" or even "mkisofs" as producer. Most of those runs can be performed by "xorriso -as mkisofs" too, but architecture "powerpc" needs option "-hfs", which xorriso's emulation does not offer.
Remove the unneeded Jigdo production options
The content of file /.disk/mkisofs looks discouraging until we decide that we need no Jigdo files but only the complete ISO image. So we can omit all options which begin by -jigdo together with their subsequent arguments. Further we do not need the jigdo-related options -checksum_algorithm_iso and -md5-list with their arguments.
The remaining shell command is then:
xorriso -as mkisofs \ -r -V 'Debian 9.3.0 amd64 n' \ -o /srv/cdbuilder.debian.org/dst/deb-cd/out/2amd64/debian-9.3.0-amd64-NETINST-1.iso \ -J -J -joliet-long -cache-inodes \ -isohybrid-mbr syslinux/usr/lib/ISOLINUX/isohdpfx.bin \ -b isolinux/isolinux.bin \ -c isolinux/boot.cat \ -boot-load-size 4 -boot-info-table -no-emul-boot \ -eltorito-alt-boot \ -e boot/grub/efi.img \ -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus \ boot1 CD1
Determine those options which need to be adapted on amd64 or i386
Many of these options can be re-used unchanged. But some need to be adapted to the situation that the ISO image is not exactly the same as the hard disk of Debian's production computers. Further we hardly want the new ISO image file to have the same name as the original.
For this purpose we roughly need to understand what the options do. The options of xorriso's mkisofs emulation are described in the man page of xorrisofs(1). It is available online as https://www.gnu.org/software/xorriso/man_1_xorrisofs.html
In above example we have
-r sets ownership and permissions of the files in the ISO. We keep it.
-V 'Debian 9.3.0 amd64 n' sets the filesystem's name. We keep it for now.
-o /srv... sets the name of the new ISO image file. We need a new file path here. E.g. "$HOME"/"debian-9.3.0-amd64-modified.iso"
-J -J -joliet-long enables production of a Joliet tree for use on systems by Microsoft Inc. We keep them, although the double -J is redundant.
-cache-inodes is ignored by xorriso. A remnant of using genisoimage. We keep it.
-isohybrid-mbr .../isohdpfx.bin installs an MBR at the start of the ISO image. This enables booting from USB stick via legacy BIOS. We need to extract the first 432 bytes of the ISO into a disk file and give that file as argument to our -isohybrid-mbr option.
-b isolinux/isolinux.bin marks the file /isolinux/isolinux.bin in the ISO as EL Torito boot image for legacy BIOS. This enables booting from CD, DVD or BD media. We keep it.
-c isolinux/boot.cat publishes the El Torito boot catalog as data file in the ISO. This is purely ornamental. We keep it.
-boot-load-size 4 -boot-info-table -no-emul-boot are additional options for the BIOS boot image. We keep them.
-eltorito-alt-boot ends the definition of the BIOS boot image. We keep it.
-e boot/grub/efi.img marks the file /boot/grub/efi.img in the ISO as EL Torito boot image for EFI. This enables booting from CD, DVD or BD media. We keep it.
-no-emul-boot is a necessary addtitional option to -e. We keep it.
-isohybrid-gpt-basdat causes the creation of a partition of type 0xef in the MBR partition table. It also causes production of a GPT which stays invalid, nevertheless, because of the existence of the MBR partition. The MBR partition marks the -e boot image as EFI System Partition. This is needed for booting via EFI from USB stick. We keep it.
-isohybrid-apm-hfsplus causes production of an Apple Partition Map with a partition entry for the -e boot image. It is useless, though, because no HFS+ filesystem image is present which would be used by some Macs as boot entry point. We keep it just because we only make necessary changes here.
boot1 CD1 were two directories on the original production machine. The file trees which were underneath these directories are now stored in the ISO. We replace this by our mount point or extracted ISO- root directory and maybe by a few files which we want to map into the new ISO image.
This assessment yields the following script for repacking the ISO from local directory "$HOME/iso_unpacked_and_modified":
# The example names get mapped to their roles here orig_iso="$HOME"/debian-9.3.0-amd64-netinst.iso new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-9.3.0-amd64-modified.iso mbr_template=isohdpfx.bin # Extract MBR template file to disk dd if="$orig_iso" bs=1 count=432 of="$mbr_template" # Create the new ISO image xorriso -as mkisofs \ -r -V 'Debian 9.3.0 amd64 n' \ -o "$new_iso" \ -J -J -joliet-long -cache-inodes \ -isohybrid-mbr "$mbr_template" \ -b isolinux/isolinux.bin \ -c isolinux/boot.cat \ -boot-load-size 4 -boot-info-table -no-emul-boot \ -eltorito-alt-boot \ -e boot/grub/efi.img \ -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus \ "$new_files"
CPU architectures other than i386 and amd64, older ISOs, Debian Live
The equipment of the ISOs matches the expectations of the firmwares which shall boot them. i386 and amd64 boot by either legacy BIOS or EFI. Their ISOs are nowadays equipped like the example above. But older ones may lack equipment for EFI or for BIOS booting from USB stick.
Other architectures have different needs. But all their ISOs are supposed to have a /.disk/mkisofs file.
arm64 release 9.4.0
After removing the jigdo-related options, there remain
xorriso -as mkisofs \ -r -V 'Debian 9.4.0 arm64 n' \ -o /srv/.../debian-9.4.0-arm64-NETINST-1.iso \ -J -joliet-long -cache-inodes \ -e boot/grub/efi.img \ -no-emul-boot \ -append_partition 2 0xef /srv/.../efi.img \ -partition_cyl_align all \ CD1
Most of them we know from above "amd64" example. We need to invent a name for the new ISO. No need for extracting an MBR template, as there is none. And no need for legacy BIOS preparations, as there is no PC-BIOS on ARM64.
Not yet explained options are:
-append_partition 2 0xef /srv/.../efi.img appends the file "efi.img" from hard disk to the end of the emerging ISO image. It will appear in MBR partition 2 with type 0xef. We need to extract partition 2 from the ISO.
-partition_cyl_align all causes alignment of the end the partitions to full legacy cylinder size. That size and the benefit of aligning to it is somewhat obscure. We keep it.
CD1 was the directory on the original production machine. We will replace this by our mount point or extracted ISO- root directory and maybe by a few files which we want to map into the new ISO image.
Partition extraction can be done by looking up the start block and number of blocks in the partition table of the original ISO, and by using dd to create a file on the local disk. In our example, fdisk reports about the partitions in the ISO:
$ /sbin/fdisk -l debian-9.4.0-arm64-netinst.iso ... Device Boot Start End Sectors Size Id Type debian-9.4.0-arm64-netinst.iso1 0 411647 411648 201M 83 Linux debian-9.4.0-arm64-netinst.iso2 411648 413695 2048 1M ef EFI (FAT-12/
So start block is 411648 and size is 2048. The dd run would thus be:
dd if=debian-9.4.0-arm64-netinst.iso bs=512 skip=411648 count=2048 \ of="$HOME"/efi.img
The resulting file "$HOME"/efi.img is supposed to be recognizable as FAT filesystem image.
The following script for repacking the ISO from local directory "$HOME/iso_unpacked_and_modified" can extract the partition if orig_iso is a single word.
orig_iso="$HOME"/debian-9.4.0-arm64-netinst.iso # If orig_iso is not a single word, you must set auto_extract_efi to 0 # and extract efi_img manually before running this script. auto_extract_efi=1 efi_img="$HOME"/efi.img new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-9.4.0-arm64-modified.iso # If enabled: extract EFI partition image part_img_ready=1 if test "$auto_extract_efi" = 1 then start_block=$(/sbin/fdisk -l "$orig_iso" | fgrep "$orig_iso"2 | \ awk '{print $2}') block_count=$(/sbin/fdisk -l "$orig_iso" | fgrep "$orig_iso"2 | \ awk '{print $4}') if test "$start_block" -gt 0 -a "$block_count" -gt 0 2>/dev/null then dd if="$orig_iso" bs=512 skip="$start_block" count="$block_count" \ of="$efi_img" else echo "Cannot read plausible start block and block count from fdisk" >&2 part_img_ready=0 fi fi # Create the new ISO image if not partition extraction failed test "$part_img_ready" = 1 && \ xorriso -as mkisofs \ -r -V 'Debian 9.4.0 arm64 n' \ -o "$new_iso" \ -J -joliet-long -cache-inodes \ -e boot/grub/efi.img \ -no-emul-boot \ -append_partition 2 0xef "$efi_img" \ -partition_cyl_align all \ "$new_files"
ppc64el release 9.4.0
After removing the jigdo-related options:
xorriso -as mkisofs \ -r -V 'Debian 9.4.0 ppc64el n' \ -o /srv/.../debian-9.4.0-ppc64el-NETINST-1.iso \ -J -joliet-long -cache-inodes \ -chrp-boot-part \ CD1
Only one boot-specific option was used:
-chrp-boot-part causes an MBR partition of type 0x96 which marks the block range of the ISO. We keep it.
Together with the generic need for a new ISO name and a modified input tree, the repacking script is then:
new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-9.4.0-ppc64el-modified.iso # Create the new ISO image xorriso -as mkisofs \ -r -V 'Debian 9.4.0 ppc64el n' \ -o "$new_iso" \ -J -joliet-long -cache-inodes \ -chrp-boot-part \ "$new_files"
mips64el release 9.4.0
After removing the jigdo-related options:
xorriso -as mkisofs \ -r -V 'Debian 9.4.0 m64el n' \ -o /srv/.../debian-9.4.0-mips64el-NETINST-1.iso \ -J -joliet-long -cache-inodes \ CD1
There are no boot-specific options at all. So:
new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-9.4.0-mips64el-modified.iso # Create the new ISO image xorriso -as mkisofs \ -r -V 'Debian 9.4.0 m64el n' \ -o "$new_iso" \ -J -joliet-long -cache-inodes \ "$new_files"
powerpc release 6.0.5
After removing the jigdo-related options:
/home/debian-cd/build/debian-cd.squeeze/../genisoimage \ -joliet-long -r \ -V 'Debian 6.0.5 ppc 1' \ -o /org/.../debian-6.0.5-powerpc-BC-1.iso \ --iso-level 4 \ --netatalk -hfs -probe \ -map /home/debian-cd/build/debian-cd.squeeze/data/hfs.map \ -hfs-parms MAX_XTCSIZE=2656248 \ --chrp-boot \ -part -no-desktop \ -hfs-bless CD1/install \ -hfs-volid Debian/PowerPC_squeeze \ CD1
Sorry, i cannot really explain what all this Apple/HFS stuff means. We keep what we do not understand.
--iso-level 4 causes production of the rarely used ISO-9660:1999 fileystem tree. We keep it.
--chrp-boot is not directly related to HFS but rather causes an MBR partition of type 0x96 which marks the block range of the ISO. We keep it.
-map /home/debian-cd/build/debian-cd.squeeze/data/hfs.map gives genisoimage a mapping file which defines HFS creator and type info for the file classes listed in hard disk file "hfs.map". This file is not stored in the ISO. We have to get one from the debian-cd package.
-hfs-bless CD1/install marks the directory "/install" in the ISO as blessed. According to man genisoimage it has to be prepended by the path which was used to bring its parent directory into the ISO. We have to prepend a new path.
orig_iso="$HOME"/debian-6.0.5-powerpc-businesscard.iso new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-6.0.5-powerpc-modified.iso hfs_map_url=https://sources.debian.org/data/main/d/debian-cd/3.1.21/data/hfs.map hfs_map_file=hfs.map # Download HFS type/creator map file of debian-cd package wget "$hfs_map_url" # Create the new ISO image genisoimage \ -joliet-long -r \ -V 'Debian 6.0.5 ppc 1' \ -o "$new_iso" \ --iso-level 4 \ --netatalk -hfs -probe \ -map "$hfs_map_file" \ -hfs-parms MAX_XTCSIZE=2656248 \ --chrp-boot \ -part -no-desktop \ -hfs-bless "$new_files"/install \ -hfs-volid Debian/PowerPC_squeeze \ "$new_files"
sparc64 version 9.0
No Jigdo options were used. But we have a surplus "-checksum_algorithm_iso" which we remove.
xorriso -as mkisofs \ -r \ -V 'Debian 9.0 sparc64 1' \ -o /srv/debian-cd-test/debian-9.0-sparc64-NETINST-1.iso \ -G boot1/boot/isofs.b \ -B ... \ boot1 CD1
- boot1/boot/isofs.b submits the hard disk file "isofs.b" as content of the ISO 9660 System Area. We need to extract it from the ISO.
-B ... lets all 8 SUN Disk Label partitions mark the range of the emerging ISO image. We keep it.
orig_iso="$HOME"/debian-9.0-sparc64-NETINST-1.iso new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-9.0-sparc64-modified.iso sys_area_file=isofs.b # Extract System Area content to a disk file dd if="$orig_iso" bs=2048 count=16 of="$sys_area_file" # Create the new ISO image xorriso -as mkisofs \ -r \ -V 'Debian 9.0 sparc64 1' \ -o "$new_iso" \ -G "$sys_area_file" \ -B ... \ "$new_files"
kfreebsd amd64 version 7.9.0
/home/93sam/xorriso -as mkisofs \ -r -V 'Debian 7.9.0 f-amd64 1' \ -o /org/.../debian-7.9.0-kfreebsd-amd64-NETINST-1.iso \ -J -joliet-long \ -b boot/grub/grub_eltorito \ -c boot/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -cache-inodes \ boot1 CD1
All options have been explained already. Not much change is needed.
new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-7.9.0-kfreebsd-amd64-modified.iso # Create the new ISO image xorriso -as mkisofs \ -r -V 'Debian 7.9.0 f-amd64 1' \ -o "$new_iso" \ -J -joliet-long \ -b boot/grub/grub_eltorito \ -c boot/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -cache-inodes \ "$new_files"
hppa version 7.0
xorriso -as mkisofs \ -r \ -V 'Debian 7.0 hppa 1' \ -o /srv/.../debian-7.0-hppa-NETINST-1.iso \ -hppa-cmdline '0/vmlinux initrd=0/ramdisk panic_timeout=60 panic=-1 mirror/protocol=http preseed/url=http://parisc.osuosl.org/debian/preseed.cfg mirror/http/proxy__=http://proxy:8080' \ -hppa-kernel-32 install/vmlinux-3.14-1-parisc \ -hppa-kernel-64 install/vmlinux-3.14-1-parisc64-smp \ -hppa-bootloader install/iplboot \ -hppa-ramdisk install/initrd.gz \ CD1
To our great luck, the argument of option -hppa-cmdline is fully opaque to the ISO production and the arguments of the other -hppa-* options are file paths inside the ISO image. So only the generic changes are needed:
new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-7.0-hppa-modified-1.iso # Create the new ISO image xorriso -as mkisofs \ -r \ -V 'Debian 7.0 hppa 1' \ -o "$new_iso" \ -hppa-cmdline '0/vmlinux initrd=0/ramdisk panic_timeout=60 panic=-1 mirror/protocol=http preseed/url=http://parisc.osuosl.org/debian/preseed.cfg mirror/http/proxy__=http://proxy:8080' \ -hppa-kernel-32 install/vmlinux-3.14-1-parisc \ -hppa-kernel-64 install/vmlinux-3.14-1-parisc64-smp \ -hppa-bootloader install/iplboot \ -hppa-ramdisk install/initrd.gz \ "$new_files"
amd64 release 5.0.4
/home/.../genisoimage \ -r -V 'Debian 5.0.4 amd64 Bin-1' \ -o /org/.../debian-504-amd64-NETINST-1.iso \ -J -J -joliet-long -cache-inodes \ -b isolinux/isolinux.bin \ -c isolinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ boot1 CD1
No booting from USB stick, no EFI, not much need for change.
new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-504-amd64-modified.iso # Create the new ISO image xorriso -as mkisofs \ -r -V 'Debian 5.0.4 amd64 Bin-1' \ -o "$new_iso" \ -J -J -joliet-long -cache-inodes \ -b isolinux/isolinux.bin \ -c isolinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ "$new_files"
amd64 Live DVD release 9.4.0
Here we have something rare in the world of bootable ISOs: Native xorriso commands rather than xorriso's mkisofs emulation. (No jigdo-related commands.)
xorriso \ -outdev debian-live-9.4.0-amd64-gnome.iso \ -volid d-live 9.4.0 gn amd64 \ -padding 0 \ -map /w/work/free/gnome/tmp/tmp8HCL24 / \ -chmod 0755 / -- \ -boot_image isolinux dir=/isolinux \ -boot_image isolinux system_area=/usr/lib/ISOLINUX/isohdpfx.bin \ -boot_image any next \ -boot_image any efi_path=boot/grub/efi.img \ -boot_image isolinux partition_entry=gpt_basdat
xorriso's own command set is described in man 1 xorriso. Online: https://www.gnu.org/software/xorriso/man_1_xorriso.html
-outdev debian-live-9.4.0-amd64-gnome.iso sets the name for the emerging ISO image file. We need a new file path here.
-volid d-live 9.4.0 gn amd64 sets the filesystem name. By a shortcomming of live-wrapper, the quotation marks are missing in the file /.disk/mkisofs. We need to put '-marks around "d-live 9.4.0 gn amd64".
-padding 0 omits the traditional padding against the Linux TAO CD Read Ahead Bug. Padding should be added by the burn program, indeed, rather than by the ISO image producer. We keep it.
-map /w/work/free/gnome/tmp/tmp8HCL24 / maps the directory tree "tmp8HCL24" to the root directory of the emerging ISO. (This is what the pathspecs like "boot" and "CD1" do in mkisofs emulation.) We replace this by mapping our mount point or extracted ISO-root directory to the new ISO-root, and maybe by a few more "-map" commands which bring particular files into the new ISO image.
-chmod 0755 / -- gives "rwxr-xr-x" permissions to the new ISO-root. We keep it.
-boot_image isolinux dir=/isolinux announces ISOLINUX legacy BIOS equipment in ISO directory /isolinux. (Like mkisofs option -b and its handful of add-on options. But sequence matters here. First -map, then -boot_image isolinux dir=. Other way round gives error.) We keep it.
-boot_image isolinux system_area=/usr/lib/ISOLINUX/isohdpfx.bin installs an MBR at the start of the ISO image. This enables booting from USB stick via legacy BIOS. We need to extract the first 432 bytes of the ISO into a disk file and give that file as argument to our command.
-boot_image any next ends the definition of the BIOS boot image. We keep it.
-boot_image any efi_path=boot/grub/efi.img marks the file /boot/grub/efi.img in the ISO as EL Torito boot image for EFI. This enables booting from CD, DVD or BD media. We keep it.
-boot_image isolinux partition_entry=gpt_basdat causes the creation of a partition of type 0xef in the MBR partition table. It also causes production of a GPT which stays invalid, nevertheless, because of the existence of the MBR partition. The MBR partition marks the "efi_path=" boot image as EFI System Partition. This is needed for booting via EFI from USB stick. We keep it.
An important difference between -outdev and -as mkisofs -o is that "-outdev" does not truncate the file "$new_iso" but would rather raise protest because of insufficient multi-session preprations:
xorriso : FAILURE : -indev differs from -outdev and -outdev media holds non-zero data
So we have to remove "$new_iso" before letting xorriso use it as output file.
Another difference is that xorriso by default calls fsync(2) on the output file after each 16 MiB of writing. This makes it lightweight on systems with few memory but also lets it appear much slower than in "-as mkisofs" mode. So if memory is plenty and the -outdev storage medium shall not be removed as soon as xorriso has ended, we may well disable this syncing by command -stdio_sync off.
Anticipating a change in Debian Live 9.5.0 we add command -compliance no_emul_toc which saves 64 KiB of result size at the cost of not recording multi-session history. This history is mostly of interest for incremental backups. It is disabled in the -as mkisofs emulation by default.
orig_iso="$HOME"/debian-live-9.4.0-amd64-gnome.iso new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-live-9.4.0-amd64-modified.iso mbr_template=isohdpfx.bin # Extract MBR template file to disk dd if="$orig_iso" bs=1 count=432 of="$mbr_template" # Delete file "$new_iso" if it exists test -e "$new_iso" && rm "$new_iso" # Create the new ISO image xorriso \ -outdev "$new_iso" \ -volid 'd-live 9.4.0 gn amd64' \ -padding 0 \ -compliance no_emul_toc \ -map "$new_files" / \ -chmod 0755 / -- \ -boot_image isolinux dir=/isolinux \ -boot_image isolinux system_area="$mbr_template" \ -boot_image any next \ -boot_image any efi_path=boot/grub/efi.img \ -boot_image isolinux partition_entry=gpt_basdat \ -stdio_sync off
What to do if no file /.disk/mkisofs exists
Up to some point release of Debian 9, the Debian Live CD ISOs did not get a file /.disk/mkisofs with their production shell command. The bootable ISOs of Debian derivates or of other Linux distros probably do not bear such info either.
In this case one may let xorriso analyze the boot equipment and make proposals. The younger the xorriso version, the better:
orig_iso=debian-live-8.4.0-i386-standard.iso xorriso -report_about warning -indev "$orig_iso" -report_system_area as_mkisofs
reports on stdout
-V 'Debian jessie 20160402-22:24' --modification-date='2016040221250200' -isohybrid-mbr --interval:local_fs:0s-15s:zero_mbrpt:'debian-live-8.4.0-i386-standard.iso' -partition_cyl_align on -partition_offset 16 -partition_hd_cyl 64 -partition_sec_hd 32 -iso_mbr_part_type 0x17 -c '/isolinux/boot.cat' -b '/isolinux/isolinux.bin' -no-emul-boot -boot-load-size 4 -boot-info-table
The pseudo file path --interval:local_fs:...iso tells xorriso to cut out the first 32 KiB of the original ISO, to erase its MBR partition table, and to use it as MBR template for option -isohybrid-mbr. With ISOLINUX for legacy BIOS it actually needs only the first 432 bytes, as we did cut out above for the 9.3.0 "amd64" ISO. We cut out the MBR template and use it with -isohybrid-mbr.
-partition_offset makes the ISO more acceptable for partition editors which hate it when partition 1 begins at block 0. We keep it.
--modification-date= might be needed with some ISOs made by program grub-mkrescue. But afaik, Debian's boot software does not search for this info in order to find the filesystem from where it was booted. We omit it.
- Several others of the shown options are default and need normally not to be given:
-partition_cyl_align , -partition_hd_cyl , -partition_sec_hd , -iso_mbr_part_type. We omit them.
The other options -c to -boot-info-table make the ISO bootable by legacy BIOS from DVD. Together with -isohybrid-mbr they also make it bootable from USB stick. We keep them.
Some options like -J -joliet-long -r are not related to booting but rather to the presentation of the files after mounting the ISO. xorriso makes no particular proposals for these aspects. They are tradition, though. We add them.
orig_iso=debian-live-8.4.0-i386-standard.iso new_files="$HOME"/iso_unpacked_and_modified new_iso="$HOME"/debian-live-8.4.0-i386-modified.iso mbr_template=isohdpfx.bin # Extract MBR template file to disk dd if="$orig_iso" bs=1 count=432 of="$mbr_template" # Create the new ISO image xorriso -as mkisofs \ -r -J --joliet-long \ -V 'Debian jessie 20160402-22:24' \ -o "$new_iso" \ -isohybrid-mbr "$mbr_template" \ -partition_offset 16 \ -c isolinux/boot.cat \ -b isolinux/isolinux.bin \ -no-emul-boot -boot-load-size 4 -boot-info-table \ "$new_files"
Methods to overwrite, delete, or add files
The Debian wiki shows various ways how to prepare the changes for writing them to the new ISO. xorriso offers its own ways, too.
Copy full ISO directory tree to writable hard disk tree
The above examples assume that the ISO content of directories and data files was extracted to a directory "$HOME"/iso_unpacked_and_modified and that any desired changes were made to this copy of the directory tree.
orig_iso="$HOME"/debian-9.3.0-amd64-netinst.iso new_files="$HOME"/iso_unpacked_and_modified # Unpack the ISO directory tree xorriso -osirrox on -indev "$orig_iso" -extract / "$new_files" # (Later delete the unpacked tree which has deletion-unfriendly permissions:) # find "$new_files" -type d -exec chmod u+w '{}' ';' # rm -rf "$new_files"
More such unpacking methods are shown in ManipulatingISOs#Extraction_of_Files_from_an_ISO.
Add overlay filesystem for doing changes
This method is shown in DebianInstaller/Modify/CD#Helper_scripts:_diunpk.2C_dipk:
... sudo mount ${di_iso} $timestamp/${di_ro} -t iso9660 -o loop,uid=${uid},gid=${gid} sudo mount -t aufs -o br:$timestamp/${di_rw}:$timestamp/${di_ro} none $timestamp/${di_rw} ...
The aufs mount point "${di_rw}" then can fulfill the role of "$new_files" in the ISO repacking examples.
In xorriso override mounted ISO tree by particular changed files
In xorriso, the operation of scheduling files for being part of the ISO is called "mapping". Each time an input file or directory is given, the mapping is adjusted accordingly. It is well possible to overwrite all or parts of a previous mapping by a further subsequent input specification. (genisoimage crashes sometimes at such occasions.)
orig_iso="$HOME"/debian-9.3.0-amd64-netinst.iso orig_mount=/mnt/iso changed_isolinux="$HOME"/isolinux_dir_from_iso # Mount original ISO read-only sudo mount "$orig_iso" "$orig_mount" # Copy out a few files which you want to change cp -r /mnt/iso/isolinux "$changed_isolinux" # Change or add files in "$changed_isolinux" # Create the new ISO image from original read-only tree and changed files xorriso -as mkisofs \ ... specific options ... \ "$orig_mount" \ -graft-points \ /isolinux="$changed_isolinux"
Option -graft-points enables the pathspec syntax target=origin by which we can choose a particular path in the ISO for the file or tree which gets mapped in. The pathspec /isolinux="$changed_isolinux" overrides conflicting parts of the previous mapping from "$orig_mount"/isolinux to /isolinux.
Mappings do not flatly replace each other but rather get merged on directory level. I.e. files do not get deleted from the mapping if they are missing in the origin of a subsequent pathspec. They can only get overwritten by another file of the same name. But xorriso's own command set may also delete files. For that, we would finally have to leave mkisofs emulation and apply commands like "-rm" or "-rm_r".
If we assume that "/isolinux/f10.txt" would have become obsolete and does not exist in "$changed_isolinux" any more, then it is still mapped by "$orig_mount". This mapping would then need to be deleted before ISO production begins:
xorriso -as mkisofs \ ... specific options ... \ "$orig_mount" \ -graft-points \ /isolinux="$changed_isolinux" -- \ -rm /isolinux/f10.txt --
First we leave the emulation command "-as" by "--". Then we execute the command "-rm" which has a variable length parameter list. Therefore it needs to be terminated by another "--" argument. About xorriso's own command set see: https://www.gnu.org/software/xorriso/man_1_xorriso.html
But a use case for this manipulation would still have to be found.
In xorriso load ISO tree and write modified new ISO
This method uses xorriso's native command set rather than the emulation of mkisofs. It has the advantage that we do not have to take care of the specific boot options of the original ISO, because "-boot_image any replay" will do this for us.
orig_iso="$HOME"/debian-9.3.0-amd64-netinst.iso new_iso="$HOME"/debian-9.3.0-amd64-modified.iso changed_isolinux="$HOME"/isolinux_dir_from_iso # Get the /isolinux directory from the original ISO xorriso -osirrox on -indev "$orig_iso" -extract /isolinux "$changed_isolinux" # Change or add files in "$changed_isolinux" # If present: Remove an older version of "$new_iso" test -e "$new_iso" && rm "$new_iso" # Make new_iso from orig_iso and the changed files xorriso \ -indev "$orig_iso" \ -outdev "$new_iso" \ \ -map "$changed_isolinux" /isolinux \ -rm /isolinux/f10.txt -- \ \ -boot_image any replay \ \ -compliance no_emul_toc \ -padding included
Note that the sequence of native xorriso commands matters: First aquire input and output, then manipulate the input by commands like -map or -rm, then replay the boot related commands learned from orig_iso, and make the output more similar to the output of the mkisofs emulation.
See for the native xorriso commands: https://www.gnu.org/software/xorriso/man_1_xorriso.html
See also:
External Links
https://www.debian.org/CD/faq - debian-cd Frequently Asked Questions
https://cdimage.debian.org/debian-cd/current/ - debian-cd ISO images
https://cdimage.debian.org/mirror/cdimage/archive/ - Many older ISO images
https://dev.lovelyhq.com/libburnia/libisofs/raw/master/doc/boot_sectors.txt - Boot sector formats on byte level