3

I am trying to build an installation image (to be transferred to USB media) for Red Hat Linux 7.4 with a custom kickstart file, and the corresponding ks= argument added to grub, but and can't figure out how to do it.

Here are the approaches I have tried:

dd if=rhel-server-7.4-x86_64-dvd.iso of=/dev/sdb

This builds the a bootable USB stick, but of course without the kickstart file.

Next, I copied the content of the ISO to a temporary file, added my ks.cfg and modified the grub configuration, and then used genisoimage to rebuild a new image.

genisoimage \
  -untranslated-filenames \
  -rational-rock \
  -v \
  -translation-table \
  -input-charset "default" \
  -J \
  -joliet-long \
  $VOLLABELARGS 
  -b isolinux/isolinux.bin \
  -c isolinux/boot.cat \
  -no-emul-boot \
  -boot-load-size 4 \
  -boot-info-table \
  -eltorito-alt-boot \
  -efi-boot images/efiboot.img \
  -no-emul-boot \
  -o $THISDIR/$VOLLABEL.iso \

This is based on Red Hat's own instructions for RHEL 6 - I am, of course, using RHEL 7. This works for BIOS booting, but when I try it on the UEFI system, the resulting image is rejected as "not compatible".

The resulting image is also noticeably larger than the original RHEL ISO.

Examining it with xorriso shows that it is also substantially different from the original. isohybrid helps some, but not enough to make the image bootable.

The output of xorriso -report on Red Hat's ISO:

xorriso -indev rhel-server-7.4-x86_64-dvd.iso -report_el_torito cmd
-volid 'RHEL-7.4 Server.x86_64'
-volume_date uuid '2017071101014600'
-boot_image isolinux system_area=--interval:imported_iso:0s-15s:zero_mbrpt,zero_gpt:'rhel-server-7.4-x86_64-boot.iso'
-boot_image any partition_cyl_align=on
-boot_image any partition_offset=0
-boot_image any partition_hd_cyl=64
-boot_image any partition_sec_hd=32
-boot_image any iso_mbr_part_type=0x00
-boot_image any cat_path='/isolinux/boot.cat'
-boot_image isolinux bin_path='/isolinux/isolinux.bin'
-boot_image any platform_id=0x00
-boot_image any emul_type=no_emulation
-boot_image any load_size=2048
-boot_image any boot_info_table=on
-boot_image any next
-boot_image any efi_path='/images/efiboot.img'
-boot_image any platform_id=0xef
-boot_image any emul_type=no_emulation
-boot_image any load_size=9211904
-boot_image isolinux partition_entry=gpt_basdat

And the output of xorriso on my image:

xorriso -indev myimage.iso -report_el_torito cmd
-volid '"MYIMAGE"'
-volume_date uuid '2018011923504500'
-boot_image isolinux system_area=--interval:imported_iso:0s-15s:zero_mbrpt:'MYIMAGE.iso'
-boot_image any partition_cyl_align=on
-boot_image any partition_offset=0
-boot_image any partition_hd_cyl=64
-boot_image any partition_sec_hd=32
-boot_image any iso_mbr_part_type=0x17
-boot_image any cat_path='/isolinux/boot.cat'
-boot_image isolinux bin_path='/isolinux/isolinux.bin'
-boot_image any platform_id=0x00
-boot_image any emul_type=no_emulation
-boot_image any load_size=2048
-boot_image any boot_info_table=on
-boot_image any next
-boot_image any efi_path='/images/efiboot.img'
-boot_image any platform_id=0xef
-boot_image any emul_type=no_emulation
-boot_image any load_size=9211904

Comparing these two, Red Hat has a few GPT-related entries that my image is missing.

Other approaches I have looked at but am not even sure if I'm going off in the wrong direction with those.

  • Using lorax/livemedia-creator. I find the instructions quite confusing. It appears to be used to build a live image, but I can't figure out how to invoke Anaconda.

  • Format the USB stick as a standard three-partition hard drive. I can't figure out how to make this bootable, though.

What is the best/easiest way to accomplish what I want?

My requirements:

  • Must be Linux command line; I want to script this process.
  • Should generate an image file, I don't want to write directly to my USB script if I can avoid it.
  • Should be able to run as non-root user.

The image file does not need to support CD/DVD booting.

  • For option #2, have you looked at the man page for grub2-install? (systutorials.com/docs/linux/man/8-grub2-install) There's an option: --efi-directory=DIR that might be of use to you. I honestly think the route of installing grub on one partition and putting together a grub config is the easiest route when it comes to booting off USBs. I haven't had much luck finding a tool to do it for me. – Centimane Jan 23 '18 at 17:34
  • Never use genisoimage, it is full of well known bugs and unmaintained by the publishers. Better use the original software mkisofs that has no known bugs and is maintained. – schily Jun 5 '18 at 15:21
  • @schily That's a tough call to make in this case, actually. genisoimage is in the official RedHat repository, so even if it isn't supported by the authors, it is supported by RH. xorriso comes from the EPEL repository. Generally speaking, while EPEL is very good, in my experience the quality isn't up to RedHat's quality. It has been a while since I did this, but IIRC, mkisofs was not an option; I think it may have been missing a few features critical for this project. – Kevin Keane Jun 6 '18 at 16:04
  • Please note that genisoimage has aprox. 50 bugs that are unfixed since 12 years. Genisoimage must be seen as completely unsupported by RH. In special as the well known bugs result in defects in the file system image that is created. BTW: mkisofs implements twice as many features than genisoimage, do you really believe mkisofs in inferior? Check: schilytools.sourceforge.net/man/man8/mkisofs.8.html – schily Jun 6 '18 at 16:07
  • Looking a bit deeper into this: mkisofs is simply not available for RedHat, neither in the official repos nor in EPEL. I avoid other sources of software, simply to keep my sanity. – Kevin Keane Jun 7 '18 at 17:08
2

The decisive advantage of original over genisoimage remake is probably in the line

-boot_image isolinux partition_entry=gpt_basdat

genisoimage cannot make partition tables for EFI. (Inspect both ISOs by "/sbin/fdisk -l" to see the difference.) You actually need the MBR partition of type 0xef. But tradition is to also add an invalid and thus useless GPT.

One way to get the partition tables would be to run after genisoimage

isohybrid --uefi $THISDIR/$VOLLABEL.iso

The program stems from SYSLINUX source. One should use the version from the same source release or git clone from which "isolinux.bin" stems.

Other distros use xorriso's mkisofs emulation with the boot options which this xorriso command tells:

xorriso -indev rhel-server-7.4-x86_64-dvd.iso -report_el_torito as_mkisofs

There will be a lengthy addess to option -isohybrid-mbr:

--interval:imported_iso:0s-15s:zero_mbrpt,zero_gpt:'rhel-server-7.4-x86_64-boot.iso

It tells xorriso to use the first 32 KiB of the original ISO as MBR template and further System Area. Normally it is SYSLINUX file "isohdpfx.bin", which has only 432 bytes. You may replace it by "mbr.bin" after copying the first 432 bytes yourself:

dd if=rhel-server-7.4-x86_64-dvd.iso bs=432 count=1 of=mbr.bin
  • Thank you! I had used isohybrid, but not the --uefi switch. And that did indeed do the trick, at least as far as it goes. Grub comes up, but then complains that it can't find vmlinuz. That's just standard EFI partition manipulation, though. – Kevin Keane Jan 23 '18 at 18:53
  • After posting my question, I also found this (RedHat login required): access.redhat.com/solutions/60959 . RedHat says that building your own ISO is not supported, but provides some helpful tips anyway. – Kevin Keane Jan 23 '18 at 19:53
  • Just for the records: The RedHat/Fedora ISOs get rebuild correctly during my xorriso regression tests. (Not in reach for xorriso are the two-headed SuSE FrankenISOs, the boot equipment of most BSD ISOs, and the UDFs by Microsoft.) – Thomas Schmitt Jan 24 '18 at 9:44
  • For an EFI boot, you do not need an EFI partition table and the better original software mkisofs supports EFI boot. See: schilytools.sourceforge.net/man/man8/mkisofs.8.html – schily Jun 5 '18 at 15:29
2

Based on answers from Thomas and Kevin I managed to get a working procedure based on xorriso, which is available from EPEL. My goals were similar to Kevin's:

  • Use a stock RHEL 7 installation media
  • Implant a kickstart and configuration scripts into the resulting image
  • Select the kickstart automatically for installation
  • Produce an image compatible with UEFI boot
  • Make the procedure scripted

Tested successfully with RHEL 7.5 and 7.6.

Step by step procedure

  1. Have xorriso installed from EPEL.
  2. Have RHEL 7 installation DVD downloaded in $ISO_SRC.
  3. Have your kickstart (ks.cfg) and scripts ready in $SCRIPTS.
  4. Extract files, which need to be customized, from ISO into $FILES:

    • isolinux/isolinux.cfg
    • EFI/BOOT/grub.cfg
    • images/efiboot.img
  5. Modify the *.cfg boot configuration files in $FILES:

    Note: I do not modify the disc label (or volume ID) intentionally. It is space sensitive (potentially any special characters) and I found it easier to reuse it instead of replacing.

    • add kickstart parameter to boot command

      '(.*)(hd:LABEL=\S+)(.*)''\1\2 inst.ks=\2:/$SCRIPTS/ks.cfg\3'

    • set default boot menu for legacy boot in isolinux.cfg

      '^\s*menu default\s*\n'''

    • set default boot menu for UEFI boot in grub.cfg

      'set default=.*''set default="0"'

  6. Modify the UEFI boot image images/efiboot.img in $FILES:

    • mount it in a temporary directory
    • copy the UEFI boot menu $FILES/EFI/BOOT/grub.cfg into it
    • unmount
  7. Build your customized image:

    xorriso \
      -indev "$ISO_SRC" \
      -map "$SCRIPTS" /"$SCRIPTS" \
      -map "$FILES" / \
      -boot_image any replay \
      -outdev "$ISO_DST"
    

    The command copies contents of the source ISO image $ISO_SRC, merges local directories' contents and replays all boot settings from the source into the destination image $ISO_DST. No further steps are required.

Note on geniso method

I had hard time with following the geniso method as described by Kevin. I managed to produce the output ISO image, however, geniso was complaining about not being able to modify the isolinux.bin image, hence I had to extract it too. This is not mentioned in the procedure.

I faced the wall on enabling the UEFI boot with isohybrid. It returned an error I did not find a workaround for:

$ isohybrid --uefi rhel-custom.iso
isohybrid: rhel-custom.iso: boot loader does not have an isolinux.bin hybrid 
signature. Note that isolinux-debug .bin does not support hybrid booting

Ansible role

I did create an Ansible role, which performs the task: build_boot_iso.

  • Thank you for reporting your experience! I wonder why you were having problems with isolinux.bin. I have used my method with 7.5, as well, and didn't need to copy isolinux.bin anywhere else. Did you use the -b isolinux/isolinux.bin argument ? The problem with isohybrid seems like it is somehow related to the isolinux.bin issue. Interesting idea to use -indev and -outdev with xorriso; that seems much simpler than my method. – Kevin Keane Jan 23 at 23:55
  • I did follow your instructions almost literally (needed to decrypt your setup from variables, though), so yes, there were all the switches. I thought it might be related to unmatching isolinux.bin stem. However, searching around I found info it shouldn't matter if your system is decent enough. I'm using a patched RHEL 7 with 7.5 media, which might possibly be a bit ahead of the ISO. Anyway, the xorriso method works like a charm and is much more straightforward. – gadamiak Jan 25 at 9:03
  • I did publish an ansible role, which performs the task of creating a boot ISO based on my instructions. The link is in the answer body. – gadamiak Feb 16 at 17:35
  • @gadamiak Have you tried livecd-creator? – ImranRazaKhan Mar 13 at 17:20
1

I now have completed the process, thanks to @Thomas Schmitt's invaluable tip.

Here is the complete process.

Overview

You must modify three files on the original Red Hat DVD:

  • isolinux/isolinux.cfg
  • EFI/BOOT/grub.cfg
  • images/efiboot.img

Decide on a volume label that you want to use. The volume label should be shorter than 14 characters.

Then use genisoimage to build the new ISO with that volume label, use isohybrid --uefi to make it UEFI compatible, and use implantisomd5 to update the correct checksum

Step-by-Step

I have scripted this, but the script is very specific to our situation, so no point in posting it.

  • Mount the original Red Hat DVD using fuseiso.
  • Set an environment variable VOLUMELABEL to your chosen volume label.
  • Copy the three files you need to modify to another location.

Edit the isolinux.cfg file. This file will be used for BIOS booting.

  • Edit the isolinux.cfg file, adding the argument to the first two lines that start with append: ks=hd:LABEL=$VOLUMELABEL:/ks.cfg.
  • Update the inst.stage2 argument everywhere you find it (probably four places) to read: inst.stage2=hd:LABEL=$VOLUMELABEL.
  • You may also want to remove the menu default entry so your image defaults to Install instead of Test & Install.

Edit the grub.cfg file. This file will be used for EFI booting. Note that this file (and everything in EFI/BOOT) will exist twice: once on the regular DVD image, and also inside the efiboot.img file.

  • Add the same argument to the first two lines that start with linuxefi.
  • Update the inst.stage2 argument everywhere you find it (probably four places) to read: inst.stage2=hd:LABEL=$VOLUMELABEL.
  • IMPORTANT AND EASY TO OVERLOOK: Also edit the line that starts with search in grub.cfg.

Edit the efiboot.img file. This will actually be booted by EFI.

  • Mount your copy of the efiboot.img file. Unfortunately, I have not found a way to do this with fusermount, so you have to be root to do this.
  • Copy the modified grub.cfg into the efiboot.img file under EFI/BOOT
  • Umount your copy of the efiboot.img file.

Now you can generate the ISO image.

The arguments to genisoimage are position-sensitive. Key points: I base the image on the original mounted ISO file (mounted as $TMPDIR), then use -m to exclude the three modified files, and use graft points to insert the modifications, as well as the kickstart file, into the image. In my image, I also removed the directory addons.

genisoimage \
  -untranslated-filenames \
  -graft-points \
  -rational-rock \
  -v \
  -translation-table \
  -input-charset "default" \
  -J \
  -joliet-long \
  -V $VOLLABEL -A $VOLLABEL -volset $VOLLABEL \
  -b isolinux/isolinux.bin \
  -c isolinux/boot.cat \
  -no-emul-boot \
  -boot-load-size 4 \
  -boot-info-table \
  -eltorito-alt-boot \
  -efi-boot images/efiboot.img \
  -no-emul-boot \
  -quiet \
  -o $THISDIR/$VOLLABEL.iso \
  -m $TMPDIR/EFI/BOOT/grub.cfg \
  -m $TMPDIR/isolinux/isolinux.cfg \
  -m $TMPDIR/images/efiboot.img \
  -m addons \
  $TMPDIR \
  EFI/BOOT/grub.cfg=$TMPGRAFT/grub.cfg \
  isolinux/isolinux.cfg=$TMPGRAFT/isolinux.cfg \
  images/efiboot.img=$TMPGRAFT/efiboot.img \
  $KICKSTARTFILE=$KICKSTARTDIR/$KICKSTARTFILE

Then use isohybrid --uefi and implantisomd5:

isohybrid --uefi $THISDIR/$VOLUMELABEL.iso
implantisomd5 $THISDIR/$VOLUMELABEL.iso

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.