This is an improved version of the patch I originally posted to this bug report. It applies mainly to the "cdrom-detect" udeb, although I suggest that the ISO volume label (such as "Debian 7.1.0 M-A 1") be included somewhere in the initrd; currently it does not appear to be. As I said previously, a dependency on "loop-modules" will have to be added, so that the "loop.ko" kernel module gets copied into the initrd.
This patch adds support for a boot parameter, "loopmount=", which specifies an ISO image file to be loaded from another filesystem, and used to boot from. For example: loopmount=KINGSTON:/linux/debian-7.1.0-amd64-i386-netinst.iso This directs the initrd to look for a block device filesystem with the label "KINGSTON" (as reported by /sbin/blkid), and to use the file "debian-7.1.0-amd64-i386-netinst.iso", in the subdirectory "/linux" (the leading "/" is not actually necessary) as a boot image. In addition to the filesystem labels found in /dev/disk/by-label/, the block device can be identified by UUID, as found in /dev/disk/by-uuid/. If the filesystem label/UUID (and ":") is not specified, then all available partitions and CD devices will be searched for the specified ISO image file, in the specified directory. If the "loopmount" parameter is not used, then the initrd will search for a direct ISO filesystem in the same way as previously, although any block device with the expected volume label ("Debian 7.1.0 M-A 1") will be tried first. It is expected that this facility will be most useful with USB flashdrives, although it is in no way limited to those. It can be applied to any block device with a vfat, ext{2,3,4}, or iso9660 filesystem; others could easily be added. Testing seems to show that the patch works well; the relevant portion of the installation log is reproduced below. Oct 4 06:02:19 cdrom-detect: Searching for Debian installation media... Oct 4 06:02:19 cdrom-detect: Devices: '/dev/sr0' Oct 4 06:02:19 cdrom-detect: LOOPDEV='KINGSTON' LOOPFILE='/linux/debian-7.1.0-amd64-i386-netinst.iso' Oct 4 06:02:19 cdrom-detect: trying loopmount on (/dev/disk/by-label/KINGSTON)... Oct 4 06:02:19 kernel: [ 226.383202] FAT-fs (sdf1): utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive! Oct 4 06:02:19 kernel: [ 226.395607] loop: module loaded Oct 4 06:02:19 cdrom-detect: CD-ROM mount succeeded: device=/loop/linux/debian-7.1.0-amd64-i386-netinst.iso fstype=iso9660 Oct 4 06:02:19 kernel: [ 226.474076] ISO 9660 Extensions: Microsoft Joliet Level 3 Oct 4 06:02:19 kernel: [ 226.474149] ISO 9660 Extensions: RRIP_1991A Oct 4 06:02:19 cdrom-detect: Detected CD 'Debian GNU/Linux 7.1.0 "Wheezy" - Official Multi-architecture amd64/i386 NETINST #1 20130615-23:44' Oct 4 06:02:19 cdrom-detect: Detected CD with 'stable' (wheezy) distribution This patch will increase the size of the (uncompressed) initrd by about 37KB: 36KB for the required "loop.ko" module, and 1KB of extra boot script. In a 200MB or 300MB ISO image, this is surely immaterial. Since the patch adds a previously unavailable feature, which will not operate unless activated by an explicit boot parameter, there seems to be no reason why it should not be applied. Compare it with the current procedure for installing Debian from a USB flashdrive: http://www.debian.org/releases/stable/amd64/ch04s03.html As an administrative note, I recommend that this bug report be retitled; the current title no longer reflects what we are discussing, and the availability of my patch is surely now the most important issue relating to it. -- Ian Bruce
--- debian-7.1.0-amd64.orig/var/lib/dpkg/info/cdrom-detect.postinst 2013-09-10 17:45:08.305375296 -0700 +++ debian-7.1.0-amd64/var/lib/dpkg/info/cdrom-detect.postinst 2013-10-03 21:46:39.392315543 -0700 @@ -1,4 +1,8 @@ -#! /bin/sh +#!/bin/sh + +# this should go in /etc/lsb-release or somewhere + +DISTRIB_LABEL="Debian 7.1.0 M-A 1" set -e . /usr/share/debconf/confmodule @@ -14,12 +18,21 @@ exit 1 } +list_devices_by_id() +{ + local dir disk="$(echo "$1" | sed 's/ /\\x20/g')" + for dir in /dev/disk/by-label /dev/disk/by-uuid ; do + [ -e ${dir}/${disk} ] && echo ${dir}/${disk} || true + done +} + try_mount() { local device=$1 local type=$2 + local options=$3 local ret=1 - if mount -t $type -o $OPTIONS $device /cdrom; then + if mount -t $type -o $options $device /cdrom; then log "CD-ROM mount succeeded: device=$device fstype=$type" if [ -e /cdrom/.disk/info ]; then CDNAME=$(cat /cdrom/.disk/info) @@ -68,6 +81,7 @@ CDFS=iso9660 FATFS=vfat OPTIONS=ro,exec + LOOPFS=vfat,ext4,iso9660 ;; hurd) CDFS=iso9660fs @@ -95,12 +109,26 @@ mkdir /cdrom 2>/dev/null || true +for arg in $(cat /proc/cmdline); do + case $arg in + loopmount=*) + LOOPMOUNT=${arg#loopmount=} + LOOPFILE=${LOOPMOUNT#*:} + [ "$LOOPFILE" != "$LOOPMOUNT" ] && LOOPDEV=${LOOPMOUNT%:*} + ;; + esac +done + +if [ "$LOOPMOUNT" ]; then + mkdir /loop 2>/dev/null || true +fi + # Need to wait for the usb device scan to complete if [ "$OS" = "linux" ]; then for count in 1 2 3 4 5 6 8 9 10; do devices="$(list-devices cd; list-devices maybe-usb-floppy)" log "Devices: '$devices'" - if [ -n "$devices" ]; then + if [ "$devices" ]; then break 2 else sleep 1 @@ -109,27 +137,62 @@ fi while true; do - WRONG= + WRONG='' - devices="$(list-devices cd; list-devices maybe-usb-floppy)" - for device in $devices; do - if try_mount $device $CDFS; then - break 2 - fi - done - - devices="$(list-devices usb-partition)" - for device in $devices; do - if try_mount $device $CDFS; then - db_set cdrom-detect/hybrid true - break 2 - fi - if try_mount $device $FATFS; then - db_set cdrom-detect/usb-hdd true - break 2 + if [ "$LOOPMOUNT" ] + then + + log "LOOPDEV='$LOOPDEV' LOOPFILE='$LOOPFILE'" + + loopfile=/loop/${LOOPFILE#/} + + if [ "$LOOPDEV" ] ; then + devices="$(list_devices_by_id "$LOOPDEV")" + else + devices="$(list-devices partition; list-devices cd)" fi - done + log "trying loopmount on ($devices)..." + + for device in $devices; do + if mount -o $OPTIONS -t $LOOPFS $device /loop; then + if [ -f $loopfile ] && try_mount $loopfile $CDFS loop,$OPTIONS ; then + break 2 + else + umount /loop + fi + fi + done + + else + + devices="$(list_devices_by_id "$DISTRIB_LABEL")" + for device in $devices; do + if try_mount $device $CDFS $OPTIONS; then + break 2 + fi + done + + devices="$(list-devices cd; list-devices maybe-usb-floppy)" + for device in $devices; do + if try_mount $device $CDFS $OPTIONS; then + break 2 + fi + done + + devices="$(list-devices usb-partition)" + for device in $devices; do + if try_mount $device $CDFS $OPTIONS; then + db_set cdrom-detect/hybrid true + break 2 + fi + if try_mount $device $FATFS $OPTIONS; then + db_set cdrom-detect/usb-hdd true + break 2 + fi + done + + fi if [ "$WRONG" ]; then db_input critical cdrom-detect/wrong-cd || [ $? -eq 30 ] @@ -138,7 +201,7 @@ fi # If a device was detected but the mount failed, ask for the CD. - if [ -n "$devices" ]; then + if [ "$devices" ]; then db_input critical cdrom-detect/retry || [ $? -eq 30 ] db_go db_get cdrom-detect/retry