--- live.old	2011-01-28 12:03:12.548298292 +0000
+++ live	2011-01-28 12:10:47.112297092 +0000
@@ -1547,6 +1547,674 @@
 	return 1
 }
 
+# Helper functions to access the Gujin bootloader extended "$INT13SF"
+# signature in real-mode memory (kept unmodified by Linux), containing
+# the description of the El-Torito BIOS disk simulation source file.
+# Gujin solution do not search for a *.iso filename on every filesystem,
+# the signature identify the right partition.
+# It would be better to support VFAT to mount a USB disk containing
+# the *.iso file.
+
+# Unfortunately hexdump is slow (seconds! do not seek?), but we can
+# seek with dd and display with hexdump.
+# Note that dd do not like its parameters in hexadecimal (prefixed
+# with 0x) so we transform them in decimal by $(()).
+USE_DD_TO_SEEK=1
+
+# printf to the current tty or to a file,
+# never mess with "return values" on standard output:
+debug()
+{
+#	printf "$@" >> /tmp/gujin.log
+#	printf "$@" > /dev/null
+#	printf "$@" > /dev/tty
+#	printf "$@" 1>&2
+	printf "$@" >> /live.log
+}
+
+# return/display the value of /dev/mem or stdin:
+peek()
+{
+	# parameters:
+	local OFFSET LENGTH FORMAT FILE
+	OFFSET=${1}
+	LENGTH=${2}
+	FORMAT=${3}
+	FILE=${4}
+
+	if [ "${USE_DD_TO_SEEK}" != 1 ]
+	then
+		hexdump -v -n ${LENGTH} -s ${OFFSET} -e "${FORMAT}" ${FILE}
+	else
+		local IF_FILE
+		if [ "${FILE}" != "" ]
+		then
+			IF_FILE="if=${FILE}"
+		fi
+		dd bs=1 skip=$((${OFFSET})) count=$((${LENGTH})) ${IF_FILE} \
+			2>/dev/null | hexdump -v -e "${FORMAT}"
+	fi
+}
+
+# return/display the decimal value of the byte:
+peekb()
+{
+	# parameters:
+	local OFFSET FILE
+	OFFSET=${1}
+	FILE=${2}
+
+	peek ${OFFSET} 1 '"%u"' ${FILE}
+}
+
+# return/display the decimal value of the 16 bits word
+peekw()
+{
+	# parameters:
+	local OFFSET FILE
+	OFFSET=${1}
+	FILE=${2}
+
+	peek ${OFFSET} 2 '"%u"' ${FILE}
+}
+
+# return/display the decimal value of the 32 bits word
+peekl()
+{
+	# parameters:
+	local OFFSET FILE
+	OFFSET=${1}
+	FILE=${2}
+
+	peek ${OFFSET} 4 '"%u"' ${FILE}
+}
+
+# return/display the hexadecimal value string of the 64 bits word
+peekll()
+{
+	# parameters:
+	local OFFSET FILE
+	OFFSET=${1}
+	FILE=${2}
+
+	peek ${OFFSET} 8 '/1 "%02X "' ${FILE}
+}
+
+# return/display the string of size ${LENGTH}
+peekstr()
+{
+	# parameters:
+	local OFFSET LENGTH FILE
+	OFFSET=${1}
+	LENGTH=${2}
+	FILE=${3}
+
+	peek ${OFFSET} ${LENGTH} '/1 "%c"' ${FILE}
+	# we could also:
+	#	dd bs=1 skip=$((${OFFSET})) count=$((${LENGTH})) \
+	#		${IF_FILE} 2>/dev/null
+}
+
+# Get the address of the TSR (Terminate & Stay Resident) managing BIOS disks:
+get_bios_irq_0x13()
+{
+	# NO parameters
+
+	local ADDR_IRQ13 OFFSET_IRQ13 SEGMENT_IRQ13 LINADR_IRQ13
+	# address of vector of BIOS disk services (0x13):
+	ADDR_IRQ13=$((4 * 0x13))
+	# address of BIOS disk services:
+	OFFSET_IRQ13=$(peekw ${ADDR_IRQ13} /dev/mem)
+	SEGMENT_IRQ13=$(peekw $((${ADDR_IRQ13} +2)) /dev/mem)
+	[ "${OFFSET_IRQ13}" = "" ] && return 1
+	LINADR_IRQ13=$((0x10 * ${SEGMENT_IRQ13} + ${OFFSET_IRQ13}))
+	debug "DISK IRQ at 0x%X:0x%X i.e. linear 0x%X\n" \
+		${SEGMENT_IRQ13} ${OFFSET_IRQ13} ${LINADR_IRQ13}
+	printf "%s" ${LINADR_IRQ13}
+	return 0
+}
+
+# Check if the TSR follows INT13SF format:
+# WEB search '$INT13SF' for detail of format
+check_INT13SF_signature()
+{
+	# parameters: TSR address
+	local LINADR_IRQ13
+	LINADR_IRQ13=${1}
+
+	local JMP0 JMP1 JMP2
+	JMP0=$(peekb $((${LINADR_IRQ13} +0)) /dev/mem)
+	JMP1=$(peekb $((${LINADR_IRQ13} +1)) /dev/mem)
+	JMP2=$(peekb $((${LINADR_IRQ13} +2)) /dev/mem)
+	debug "INT13SF jmp instruction: 0x%X 0x%X 0x%X\n" ${JMP0} ${JMP1} ${JMP2}
+
+	if [ ${JMP0} -eq $((0xe9)) -a ${JMP1} -eq $((0x89)) -a ${JMP2} -eq $((0x00)) ]
+	then
+		debug "Warning, maybe using old Gujin version, limited functionality\n"
+	fi
+
+	# test "Safe ID string":
+	local INT13SF_SIG INT13SF_CORRECT_SIG
+
+	INT13SF_SIG=$(peekll $((${LINADR_IRQ13} +3)) /dev/mem)
+	INT13SF_CORRECT_SIG=$(echo '$INT13SF' | peekll 0)
+	debug "INT13SF_CORRECT_SIG=%s, INT13SF_SIG=%s\n" \
+		"${INT13SF_CORRECT_SIG}" "${INT13SF_SIG}"
+
+	# display end of INT13SF structure:
+	debug "INT13SF oldintaddr 0x%X flags 0x%08X\n" \
+		$(peekl $((${LINADR_IRQ13} +3+8+8)) /dev/mem) \
+		$(peekl $((${LINADR_IRQ13} +3+8+8+4)) /dev/mem)
+
+	return $([ "${INT13SF_SIG}" != "${INT13SF_CORRECT_SIG}" ])
+}
+
+# Check if the TSR follows extended Gujin format:
+check_Gujin_signature()
+{
+	# parameters: TSR address
+	local LINADR_IRQ13
+	LINADR_IRQ13=${1}
+
+	# test "Vendor ID string":
+	local GUJIN_SIG GUJIN_CORRECT_SIG
+
+	GUJIN_SIG=$(peekll $((${LINADR_IRQ13} +3+8)) /dev/mem)
+	GUJIN_CORRECT_SIG=$(echo 'Gujin   ' | peekll 0)
+	debug "GUJIN_CORRECT_SIG=%s, GUJIN_SIG=%s\n" \
+		"${GUJIN_CORRECT_SIG}" "${GUJIN_SIG}"
+	return $([ "${GUJIN_SIG}" != "${GUJIN_CORRECT_SIG}" ])
+}
+
+# Try to locate the disk in use by using the disk serial number:
+# Only return (i.e. display) the path if a SINGLE disk match
+get_disk_by_id()
+{
+	# parameters:
+	local EBIOS_DEVICE_ADR
+	EBIOS_DEVICE_ADR=${1}
+
+	debug "serial_number=0x%08X %08X %08X %08X\n" \
+		$(peekl $((${EBIOS_DEVICE_ADR} +0)) /dev/mem) \
+		$(peekl $((${EBIOS_DEVICE_ADR} +4)) /dev/mem) \
+		$(peekl $((${EBIOS_DEVICE_ADR} +8)) /dev/mem) \
+		$(peekl $((${EBIOS_DEVICE_ADR} +12)) /dev/mem)
+
+	# If there is only one single USB disk, that will be the one.
+	local PATTERN
+	PATTERN='/dev/disk/by-id/usb-*-0:0'
+	if [ $(ls ${PATTERN} 2>/dev/null | wc -l) -eq 1 ]
+	then
+		debug "Single USB drive present: %s\n" ${PATTERN}
+		ls ${PATTERN}
+		return 0
+	fi
+
+	# The only mapping on the serial number displayed by 'usb-devices'
+	# and present in /dev/disk/by-id/usb-*-0:0 and the one given by
+	# INT 0x13 AH=0x48 (WEB search D1386r5.pdf) which is named "64-bit
+	# Serial Number as defined in the USB Mass Storage specifications"
+	# which works for me is:
+	local DISK_BY_ID0 DISK_BY_ID1 DISK_BY_ID2
+	local DISK_BY_ID3 DISK_BY_ID4 DISK_BY_ID5
+
+	DISK_BY_ID0=$(peekb $((${EBIOS_DEVICE_ADR} +9)) /dev/mem)
+	DISK_BY_ID1=$(peekb $((${EBIOS_DEVICE_ADR} +8)) /dev/mem)
+	DISK_BY_ID2=$(peekb $((${EBIOS_DEVICE_ADR} +7)) /dev/mem)
+	DISK_BY_ID3=$(peekb $((${EBIOS_DEVICE_ADR} +6)) /dev/mem)
+	DISK_BY_ID4=$(peekb $((${EBIOS_DEVICE_ADR} +5)) /dev/mem)
+	DISK_BY_ID5=$(peekb $((${EBIOS_DEVICE_ADR} +4)) /dev/mem)
+	PATTERN=$(printf "/dev/disk/by-id/usb-*_%02X%02X%02X%02X%02X%02X-0:0" \
+		${DISK_BY_ID0} ${DISK_BY_ID1} ${DISK_BY_ID2} \
+		${DISK_BY_ID3} ${DISK_BY_ID4} ${DISK_BY_ID5})
+
+	debug "# searching ID: %s in 'ls /dev/disk/by-id/usb-*-0:0':\n" "${PATTERN}"
+	debug "# %s\n" $(ls /dev/disk/by-id/usb-*-0:0)
+	if [ $(ls ${PATTERN} 2>/dev/null | wc -l) -eq 1 ]
+	then
+		debug "Single USB drive with correct signature present\n"
+		ls ${PATTERN}
+		return 0
+	fi
+	return 1
+}
+
+# Search in /dev/disk/by-path/pci-* if a block device correspond parameters:
+# Only return (i.e. display) the path if a SINGLE disk match
+find_usb_disk_by_path()
+{
+	# parameters:
+	local PCI_bus PCI_device PCI_function IS_SLAVE
+	PCI_bus=${1}
+	PCI_device=${2}
+	PCI_function=${3}
+	IS_SLAVE=${4}
+
+	local cpt_port list_port DISK_BY_PATH MATCH_FOUND
+
+	# search for directly connected, i.e. no HUB:
+	#	/dev/disk/by-path/pci-0000:00:12.1-usb-0:X:1.0-scsi-0:0:0:0
+	list_port="1 2 3 4 5 6 7 8"
+	# and search through first 8 USB HUB:
+	#	/dev/disk/by-path/pci-0000:00:12.1-usb-0:X.Y:1.0-scsi-0:0:0:0
+	# most USB HUB have only 4 ports:
+	list_port="${list_port} 1.1 1.2 1.3 1.4"
+	list_port="${list_port} 2.1 2.2 2.3 2.4"
+	list_port="${list_port} 3.1 3.2 3.3 3.4"
+	list_port="${list_port} 4.1 4.2 4.3 4.4"
+	list_port="${list_port} 5.1 5.2 5.3 5.4"
+	list_port="${list_port} 6.1 6.2 6.3 6.4"
+	list_port="${list_port} 7.1 7.2 7.3 7.4"
+	list_port="${list_port} 8.1 8.2 8.3 8.4"
+	MATCH_FOUND=0
+	for cpt_port in ${list_port}
+	do
+		DISK_BY_PATH=$(printf "/dev/disk/by-path/pci-%04x:%02x:%02x.%x-usb-0:%s:1.0-scsi-0:0:%u:0" \
+					0 ${PCI_bus} ${PCI_device} ${PCI_function} ${cpt_port} ${IS_SLAVE})
+		if [ -b "${DISK_BY_PATH}" ]
+		then
+			debug "Checking %s: is a block device\n" ${DISK_BY_PATH}
+			if [ ${MATCH_FOUND} != 0 ]
+			then
+				debug "Checking %s: we have 2 block device, abort\n" \
+					${DISK_BY_PATH}
+				return 1
+			fi
+			MATCH_FOUND=${DISK_BY_PATH}
+		else
+			debug "Checking %s: do not exist\n" ${DISK_BY_PATH}
+		fi
+	done
+	if [ ${MATCH_FOUND} != 0 ]
+	then
+		printf "%s" ${MATCH_FOUND}
+	fi
+	return 0
+}
+
+# Search in /dev/disk/by-path/pci* if a disk correspond to what
+# the BIOS said to Gujin:
+# TODO: fails if the wrong USB disk is on a main USB port,
+# and the right USB disk is on a USB HUB. Well, that's live.
+find_disk_by_path()
+{
+	# parameters:
+	local EBIOS_BUS_ADR EBIOS_INTERFACE IS_SLAVE
+	EBIOS_BUS_ADR=${1}
+	EBIOS_INTERFACE=${2}
+	IS_SLAVE=${3}
+	
+	local PCI_bus PCI_device PCI_function DISK_BY_PATH
+
+	PCI_bus=$(peekb $((${EBIOS_BUS_ADR} +0)) /dev/mem)			# EBIOS_BUS[0]
+	PCI_device=$(peekb $((${EBIOS_BUS_ADR} +1)) /dev/mem)		# EBIOS_BUS[1]
+	PCI_function=$(peekb $((${EBIOS_BUS_ADR} +2)) /dev/mem)		# EBIOS_BUS[2]
+	debug "PCI_bus=0x%X, PCI_device=0x%X, PCI_function=0x%X\n" \
+		${PCI_bus} ${PCI_device} ${PCI_function}
+	if [ ${EBIOS_INTERFACE} = "USB" ]
+	then
+		DISK_BY_PATH=$(find_usb_disk_by_path ${PCI_bus} ${PCI_device} ${PCI_function} ${IS_SLAVE})
+		if [ ! -b "${DISK_BY_PATH}" -a $? -eq 0 ]
+		then
+			# happens when loaded with OHCI and Linux runs EHCI (USB disk on USB HUB):
+			# lspci: 00:12.1 USB Controller: ATI Technologies Inc SB700 USB OHCI1 Controller
+			#        00:12.2 USB Controller: ATI Technologies Inc SB700/SB800 USB EHCI Controller
+			if [ ${PCI_function} -eq 2 ]
+			then
+				PCI_function=1
+			else
+				PCI_function=2
+			fi
+			debug "try switching EHCI/OHCI, PCI_function=%u\n" ${PCI_function}
+			DISK_BY_PATH=$(find_usb_disk_by_path ${PCI_bus} ${PCI_device} ${PCI_function} ${IS_SLAVE})
+		fi
+	else
+		DISK_BY_PATH=$(printf "/dev/disk/by-path/pci-%04x:%02x:%02x.%x-scsi-0:0:%u:0" \
+			0 ${PCI_bus} ${PCI_device} ${PCI_function} ${IS_SLAVE})
+	fi
+	printf "%s" ${DISK_BY_PATH}
+}
+
+# Search each partition for the right start/length,
+# with ${DISK_BY_PATH_LINK} ${DISK_BY_ID_LINK} hints:
+find_device()
+{
+	# parameters:
+	local PARTITION_START PARTITION_LENGTH DISK_BY_PATH_LINK DISK_BY_ID_LINK
+	PARTITION_START=${1}
+	PARTITION_LENGTH=${2}
+	DISK_BY_PATH_LINK=${3}
+	DISK_BY_ID_LINK=${4}
+
+	local PARTITION_LIST CURPART CURDISK MATCH MATCHDISK
+	MATCH=0
+	MATCHDISK="none"
+
+	PARTITION_LIST=$(awk '/^ /{printf "%s ", $4}' /proc/partitions)
+	for CURPART in ${PARTITION_LIST}
+	do
+		unset CURDISK
+		if [ ! -d /sys/block/${CURPART} ]
+		then
+			# get "sda" from "sda2" AND get "mmcblk0" from "mmcblk0p1"
+			CURDISK=$(echo ${CURPART} \
+				| sed '/^mmcblk/s/p[0-9]*$//;/^mmcblk/!s/[0-9]*$//')
+			debug "%s is a partition of disk %s\n" ${CURPART} ${CURDISK}
+		fi
+
+		if [ "${CURDISK}" != "" ]
+		then
+			if [ "${DISK_BY_PATH_LINK}" != "" \
+				-a "${DISK_BY_PATH_LINK}" != ${CURDISK} ]
+			then
+				debug "%s is not part of the PCI disk %s\n" \
+					${CURDISK} ${DISK_BY_PATH_LINK}
+				continue
+			fi
+			if [ "${DISK_BY_ID_LINK}" != "" \
+				-a "${DISK_BY_ID_LINK}" != ${CURDISK} ]
+			then
+				debug "%s is not part of the ID disk %s\n" ${CURDISK} ${DISK_BY_ID_LINK}
+				continue
+			fi
+			if [ ${PARTITION_START} != $(cat /sys/block/${CURDISK}/${CURPART}/start) ]
+			then
+				debug "partition %s start %u wrong start\n" \
+					${CURPART} $(cat /sys/block/${CURDISK}/${CURPART}/start)
+				continue
+			fi
+			# Gujin <= v2.8.2 did not write fields PARTITION_LENGTH
+			# and PARTITION_TYPE, but easily recognised:
+			if [ ${PARTITION_LENGTH} != $(cat /sys/block/${CURDISK}/${CURPART}/size) \
+				-a ${PARTITION_LENGTH} != $((0xE0FA809C)) ]
+			then
+				debug "partition %s size %u wrong length\n" \
+					${CURPART} $(cat /sys/block/${CURDISK}/${CURPART}/size)
+				continue
+			fi
+			if [ ${MATCH} != 0 ]
+			then
+				debug "We have a double match %s (disk %s) and %s (disk %s), abort\n" \
+					${CURPART} ${CURDISK} ${MATCH} ${MATCHDISK}
+				return 1
+			fi
+			MATCH=${CURPART}
+			MATCHDISK=${CURDISK}
+			debug "## partition %s disk %s is one right device\n" \
+				${CURPART} ${CURDISK}
+		else
+			if [ "${DISK_BY_PATH_LINK}" != "" \
+				-a "${DISK_BY_PATH_LINK}" != ${CURPART} ]
+			then
+				debug "%s is not the PCI disk %s\n" \
+					${CURPART} ${DISK_BY_PATH_LINK}
+				continue
+			fi
+			if [ "${DISK_BY_ID_LINK}" != "" \
+				-a "${DISK_BY_ID_LINK}" != ${CURPART} ]
+			then
+				debug "%s is not the ID disk %s\n" ${CURPART} ${DISK_BY_ID_LINK}
+				continue
+			fi
+			if [ ${PARTITION_START} != 0 ]
+			then
+				debug "disk %s non null start\n" ${CURPART}
+				continue
+			fi
+			# Gujin <= v2.8.2 did not write fields PARTITION_LENGTH
+			# and PARTITION_TYPE, but easily recognised:
+			# One USB disk give BIOS size 2007808 and linux size 2009088...
+			local DELTASIZE
+			DELTASIZE=$(( ${PARTITION_LENGTH} - $(cat /sys/block/${CURPART}/size) ))
+			[ ${DELTASIZE} -lt 0 ] && DELTASIZE=$((-${DELTASIZE}))
+			debug "abs(DELTASIZE)=%u\n" $DELTASIZE
+			if [ ${DELTASIZE} -gt 2048 \
+				-a ${PARTITION_LENGTH} -ne $((0xE0FA809C)) ]
+			then
+				debug "disk %s size %u wrong length\n" \
+					${CURPART} $(cat /sys/block/${CURPART}/size)
+				continue
+			fi
+			if [ ${MATCH} != 0 ]
+			then
+				debug "We have a double match %s and %s (disk %s), abort\n" \
+					${CURPART} ${MATCH} ${MATCHDISK}
+				return 1
+			fi
+			MATCH=${CURPART}
+			debug "## disk %s is one right device\n" ${CURPART}
+		fi
+	done
+	if [ ${MATCH} != 0 ]
+	then
+		printf "%s" ${MATCH}
+	fi
+}
+
+# Find the mount point (if already mounted) or create the mount directory
+# and mount the device (if MOUNT_POINT parameter not empty):
+find_create_mount_point()
+{
+	# parameters:
+	local THEDEVICE PARTITION_TYPE MOUNT_POINT
+	THEDEVICE=${1}
+	PARTITION_TYPE=${2}
+	MOUNT_POINT=${3}
+
+	local AWK_CMD THEMOUNTPOINT
+	# Do not expand following dollar, it is for awk:
+	AWK_CMD='{ print $2 }'
+
+	THEMOUNTPOINT=$(awk "/\/dev\/${THEDEVICE}/${AWK_CMD}" /proc/mounts)
+	if [ "${THEMOUNTPOINT}" = "" -a "${MOUNT_POINT}" != "" ]
+	then
+		# Set the default name there:
+		case ${PARTITION_TYPE} in
+			1) MOUNT_FS="iso9660" ;;
+			2) MOUNT_FS="ext4" ;;
+			3) MOUNT_FS="vfat" ;;
+			*) MOUNT_FS="auto" ;;
+		esac
+		if [ ! -d "${MOUNT_POINT}" ]
+		then
+			mkdir "${MOUNT_POINT}"
+		fi
+		mount -o ro -t ${MOUNT_FS} /dev/${THEDEVICE} ${MOUNT_POINT}
+		if [ $? -eq 0 ]
+		then
+			debug "Successfull mount %s on %s with type %s\n" \
+				/dev/${THEDEVICE} ${MOUNT_POINT} ${MOUNT_FS}
+		elif [ "${MOUNT_FS}" = "ext4" ]
+		then
+			mount -o ro -t ext3 /dev/${THEDEVICE} ${MOUNT_POINT}
+			if [ $? -eq 0 ]
+			then
+				debug "Successfull mount %s on %s with type ext3\n" \
+					/dev/${THEDEVICE} ${MOUNT_POINT}
+			else
+				mount -o ro -t ext2 /dev/${THEDEVICE} ${MOUNT_POINT}
+				if [ $? -eq 0 ]
+				then
+					debug "Successfull mount %s on %s with type ext2\n" \
+						/dev/${THEDEVICE} ${MOUNT_POINT}
+				else
+					debug "FAILED mount %s on %s with type ext4/ext3/ext2\n" \
+						/dev/${THEDEVICE} ${MOUNT_POINT}
+				fi
+			fi
+		else
+			debug "FAILED mount %s on %s with type %s\n" \
+				/dev/${THEDEVICE} ${MOUNT_POINT} ${MOUNT_FS}
+		fi
+		# Re-check:
+		THEMOUNTPOINT=$(awk "/\/dev\/${THEDEVICE}/${AWK_CMD}" /proc/mounts)
+	fi
+	printf "%s" ${THEMOUNTPOINT}
+}
+
+gujin_disk_source_file()
+{
+	# parameters:
+	local MOUNT_POINT
+	MOUNT_POINT=${1}
+
+	# computer information:
+	local LINADR_IRQ13 LINADR_GUJIN
+	# Data left in memory by Gujin:
+	local INT13FILENAME HOSTBIOS IDE_MASK IDE_BASE
+	local EBIOS_BUSTYPE EBIOS_INTERFACE
+	local PARTITION_START PARTITION_LENGTH PARTITION_TYPE
+	# Intermediate results we deduce:
+	local IS_SLAVE DISK_BY_ID DISK_BY_ID_LINK DISK_BY_PATH DISK_BY_PATH_LINK
+	# Final result:
+	local THEDEVICE THEMOUNTPOINT
+
+	if [ ! -r /dev/mem ]
+	then
+		debug "Cannot read /dev/mem, cannot continue!\n"
+		return 1
+	fi
+
+	LINADR_IRQ13=$(get_bios_irq_0x13)
+	if [ $? -ne 0 ]
+	then
+		debug "Either dd or hexdump abscent or not working!\n"
+		return 1
+	fi
+	
+	if check_INT13SF_signature ${LINADR_IRQ13}
+	then
+		debug "Not a TSR or do not conform to \$INT13SF standard\n"
+		return 1
+	fi
+
+	if check_Gujin_signature ${LINADR_IRQ13}
+	then
+		debug "TSR is not Gujin\n"
+		return 1
+	fi
+
+	# We now know that it is a Gujin disk simulation
+
+	# Following fields are only generated from the Gujin bootloader:
+	LINADR_GUJIN=$((${LINADR_IRQ13} +3+8+8+4+4))
+	debug "LINADR_GUJIN=0x%X INT13BIOSDISK=0x%X\n" \
+		${LINADR_GUJIN} $(peekb ${LINADR_GUJIN} /dev/mem)
+
+	INT13FILENAME=$(peekstr $((${LINADR_GUJIN} +1)) 64 /dev/mem)
+	HOSTBIOS=$(peekb $((${LINADR_GUJIN} +1+64)) /dev/mem)
+	IDE_MASK=$(peekb $((${LINADR_GUJIN} +1+64+1)) /dev/mem)
+	IDE_BASE=$(peekw $((${LINADR_GUJIN} +1+64+1+1)) /dev/mem)
+	debug "INT13FILENAME=%s, HOSTBIOS=0x%X, IDE_MASK=0x%X, IDE_BASE=0x%X\n" \
+		${INT13FILENAME} ${HOSTBIOS} ${IDE_MASK} ${IDE_BASE}
+
+	EBIOS_BUSTYPE=$(peekstr $((${LINADR_GUJIN} +1+64+1+1+2)) 4 /dev/mem)
+	EBIOS_INTERFACE=$(peekstr $((${LINADR_GUJIN} +1+64+1+1+2+4)) 8 /dev/mem)
+	debug "EBIOS_BUSTYPE=%s, EBIOS_INTERFACE=%s.\n" \
+		"${EBIOS_BUSTYPE}" "${EBIOS_INTERFACE}"
+	# Those are not strings:
+	#EBIOS_BUS=$(peekstr $((${LINADR_GUJIN} +1+64+1+1+2+4+8)) 8 /dev/mem)
+	#EBIOS_DEVICE=$(peekstr $((${LINADR_GUJIN} +1+64+1+1+2+4+8+8)) 16 /dev/mem)
+	#debug "EBIOS_BUS=%s, EBIOS_DEVICE=%s\n" "${EBIOS_BUS}" "${EBIOS_DEVICE}"
+
+	# Warning: We will use ${EBIOS_INTERFACE} instead of "${EBIOS_INTERFACE}"
+	# to trim the trailing spaces, same for ${EBIOS_BUSTYPE}.
+	# We then cannot handle empty string:
+	if [ "${EBIOS_BUSTYPE}" = "" ]
+	then
+		EBIOS_BUSTYPE="NULL"
+		debug "set EBIOS_BUSTYPE to: %s.\n" ${EBIOS_BUSTYPE}
+	fi
+	if [ "${EBIOS_INTERFACE}" = "" ]
+	then
+		EBIOS_INTERFACE="NULL"
+		debug "set EBIOS_INTERFACE to: %s.\n" ${EBIOS_INTERFACE}
+	fi
+
+	# Warning, hexdump not able to handle long long,
+	# PARTITION_START/PARTITION_LENGTH truncated to 32 bits:
+	#PARTITION_START=$(hexdump -v -n 8 -s $((${LINADR_GUJIN} \
+	#				+1+64+1+1+2+4+8+8+16)) -e '/8 "%u"' /dev/mem)
+	PARTITION_START=$(peekl $((${LINADR_GUJIN} +1+64+1+1+2+4+8+8+16)) /dev/mem)
+	#PARTITION_LENGTH=$(hexdump -v -n 8 -s $((${LINADR_GUJIN} \
+	#				+1+64+1+1+2+4+8+8+16+8)) -e '/8 "%u"' /dev/mem)
+	PARTITION_LENGTH=$(peekl $((${LINADR_GUJIN} +1+64+1+1+2+4+8+8+16+8)) /dev/mem)
+	# PARTITION_TYPE: 1 ISO9660, 2 EXT*FS, 3: VFAT
+	PARTITION_TYPE=$(peekb $((${LINADR_GUJIN} +1+64+1+1+2+4+8+8+16+8+8)) /dev/mem)
+	debug "PARTITION_START=%u, PARTITION_LENGTH=%u, PARTITION_TYPE=%u\n" \
+		${PARTITION_START} ${PARTITION_LENGTH} ${PARTITION_TYPE}
+
+	# Search if we have an (ATA) slave disk:
+	if [  ${EBIOS_INTERFACE} = "ATA" \
+		-o ${EBIOS_INTERFACE} = "SATA" \
+		-o ${EBIOS_INTERFACE} = "ATAPI" ]
+	then
+		# uses EBIOS_DEVICE[0]:
+		IS_SLAVE=$(peekb $((${LINADR_GUJIN} +1+64+1+1+2+4+8+8)) /dev/mem)
+		debug "IS_SLAVE=%u (by EBIOS_DEVICE[0])\n" ${IS_SLAVE}
+	else
+		IS_SLAVE=$(( !!(${IDE_MASK} & 0x10) ))
+		debug "IS_SLAVE=%u (by IDE_MASK)\n" ${IS_SLAVE}
+	fi
+
+	# Search the serial number in /dev/disk/by-id/usb-* :
+	# The same system would work for 1394/FIBRE/I2O disks, but I do
+	# not have the hardware to test...
+	if [ ${EBIOS_INTERFACE} = "USB" ]
+	then
+		DISK_BY_ID=$(get_disk_by_id $((${LINADR_GUJIN} +1+64+1+1+2+4+8+8)))
+		if [ "${DISK_BY_ID}" != "" ]
+		then
+#			DISK_BY_ID_LINK=$(readlink ${DISK_BY_ID} | sed 's#../../##')
+			DISK_BY_ID_LINK=$(readlink ${DISK_BY_ID})
+			DISK_BY_ID_LINK=${DISK_BY_ID_LINK#../../}
+		fi
+		if [ "${DISK_BY_ID_LINK}" != "" ]
+		then
+			debug "DISK_BY_ID=%s points to %s\n" \
+				${DISK_BY_ID} ${DISK_BY_ID_LINK}
+		fi
+	fi
+
+	# Search the disk PCI interface in /dev/disk/by-path/pci*:
+	if [ ${EBIOS_BUSTYPE} != "ISA" ]
+	then
+		DISK_BY_PATH=$(find_disk_by_path $((${LINADR_GUJIN} +1+64+1+1+2+4+8)) \
+						${EBIOS_INTERFACE} ${IS_SLAVE})
+		if [ "${DISK_BY_PATH}" != "" ]
+		then
+#			DISK_BY_PATH_LINK=$(readlink ${DISK_BY_PATH} | sed 's#../../##')
+			DISK_BY_PATH_LINK=$(readlink ${DISK_BY_PATH})
+			DISK_BY_PATH_LINK=${DISK_BY_PATH_LINK#../../}
+		fi
+		if [ "${DISK_BY_PATH_LINK}" != "" ]
+		then
+			debug "DISK_BY_PATH=%s points to %s\n" \
+				${DISK_BY_PATH} ${DISK_BY_PATH_LINK}
+		fi
+	fi
+
+	# Find the device with ${DISK_BY_PATH_LINK} and ${DISK_BY_ID_LINK} hints:
+	THEDEVICE=$(find_device ${PARTITION_START} ${PARTITION_LENGTH} \
+				"${DISK_BY_PATH_LINK}" "${DISK_BY_ID_LINK}")
+	debug "THEDEVICE=%s\n" "${THEDEVICE}"
+	if [ "${THEDEVICE}" != "" ]
+	then
+		THEMOUNTPOINT=$(find_create_mount_point ${THEDEVICE} \
+							${PARTITION_TYPE} ${MOUNT_POINT})
+		debug "MOUNTPOINT=%s\n" "${THEMOUNTPOINT}"
+		if [ -e "${THEMOUNTPOINT}/${INT13FILENAME}" ]
+		then
+			debug "Found %s\n" "${THEMOUNTPOINT}/${INT13FILENAME}"
+			printf "%s\n" "${THEMOUNTPOINT}/${INT13FILENAME}"
+			return 0
+		fi
+	fi
+	return 1
+}
+
+# End Gujin helper functions.
+
 find_livefs ()
 {
 	timeout="${1}"
@@ -1607,6 +2275,11 @@
 				then
 					return 0
 				fi
+			else
+				if gujin_disk_source_file "/isofrom"
+				then
+					return 0
+				fi
 			fi
 			;;
 	esac
