#!/bin/sh set -e . /usr/share/debconf/confmodule #set -x if [ -z "$1" ]; then PROGRESSBAR=hw-detect/detect_progress_step else PROGRESSBAR=$1 fi NEWLINE=" " MISSING_MODULES_LIST="" SUBARCH="$(archdetect)" finish_install=/usr/lib/finish-install.d/30hw-detect LOAD_IDE="" if db_get hw-detect/load-ide && [ "$RET" = true ]; then LOAD_IDE=1 fi # Check for virtio devices if [ -d /sys/bus/pci/devices ] && \ grep -q 0x1af4 /sys/bus/pci/devices/*/vendor 2>/dev/null && \ ! grep -q ^virtio_ /proc/modules; then anna-install virtio-modules || true fi if [ -x /sbin/depmod ]; then depmod -a > /dev/null 2>&1 || true fi log () { logger -t hw-detect "$@" } is_not_loaded() { ! ((cut -d" " -f1 /proc/modules | grep -q "^$1\$") || \ (cut -d" " -f1 /proc/modules | sed -e 's/_/-/g' | grep -q "^$1\$")) } is_available () { modprobe -qn "$1" } # Module as first parameter, description of device the second. missing_module () { if ! in_list "$1" "$MISSING_MODULES_LIST"; then if [ -n "$MISSING_MODULES_LIST" ]; then MISSING_MODULES_LIST="$MISSING_MODULES_LIST, " fi MISSING_MODULES_LIST="$MISSING_MODULES_LIST$1 ($2)" fi } # The list can be delimited with spaces or spaces and commas. in_list() { echo "$2" | grep -q "\(^\| \)$1\(,\| \|$\)" } snapshot_devs() { echo -n `grep : /proc/net/dev | cut -d':' -f1` } compare_devs() { local olddevs="$1" local devs="$2" local dev newdevs newdevs= for dev in $devs; do if ! echo " $olddevs " | grep -q " $dev "; then newdevs="${newdevs:+$newdevs }$dev" fi done echo "$newdevs" } load_module() { local module="$1" local cardname="$2" local devs="" local olddevs="" local newdev="" old=`cat /proc/sys/kernel/printk` echo 0 > /proc/sys/kernel/printk devs="$(snapshot_devs)" if log-output -t hw-detect modprobe -v "$module"; then olddevs="$devs" devs="$(snapshot_devs)" newdevs="$(compare_devs "$olddevs" "$devs")" # Make sure space is used as a delimiter. IFS_SAVE="$IFS" IFS=" " if [ -n "$newdevs" -a -n "$cardname" ]; then mkdir -p /etc/network for dev in $newdevs; do echo "${dev}:${cardname}" >> /etc/network/devnames done fi IFS="$IFS_SAVE" else log "Error loading '$module'" if [ "$module" != floppy ] && [ "$module" != ide-floppy ] && \ [ "$module" != ide-cd ] && [ "$module" != ide-generic ]; then db_subst hw-detect/modprobe_error CMD_LINE_PARAM "modprobe -v $module" db_input medium hw-detect/modprobe_error || [ $? -eq 30 ] db_go fi fi echo $old > /proc/sys/kernel/printk } # Some pci chipsets are needed or there can be DMA or other problems. get_ide_chipset_info() { for ide_module in $(find /lib/modules/*/kernel/drivers/ide/pci/ -type f 2>/dev/null); do if [ -e $ide_module ]; then baseidemod=$(echo $ide_module | sed 's/\.ko$//; s/.*\///') echo "$baseidemod:IDE chipset support" fi done } # Return list of lines formatted "module:Description" get_detected_hw_info() { if [ "${SUBARCH%%/*}" = powerpc ]; then discover-mac-io if [ "$SUBARCH" = powerpc/chrp_rs6k ] || \ [ "$SUBARCH" = powerpc/chrp_ibm ]; then discover-ibm fi fi if [ "${SUBARCH%%/*}" = sparc ]; then discover-sbus fi if [ -d /sys/bus/usb ]; then echo "usb-storage:USB storage" fi } # NewWorld PowerMacs don't want floppy or ide-floppy, and on some models # (e.g. G5s) the kernel hangs when loading the module. get_floppy_info() { case $SUBARCH in powerpc/powermac_newworld) ;; *) echo "floppy:Linux Floppy" ;; esac } get_ide_floppy_info() { case $SUBARCH in powerpc/powermac_newworld) ;; *) echo "ide-floppy:Linux IDE floppy" ;; esac } # Manually load modules to enable things we can't detect. # XXX: This isn't the best way to do this; we should autodetect. # The order of these modules are important. get_manual_hw_info() { if [ "$LOAD_IDE" ]; then get_floppy_info get_ide_chipset_info echo "ide-generic:Linux IDE support" get_ide_floppy_info echo "ide-disk:Linux ATA DISK" echo "ide-cd:Linux ATAPI CD-ROM" fi } # Should be greater than the number of kernel modules we can reasonably # expect it will ever need to load. MAX_STEPS=1000 OTHER_STEPS=4 # Use 1/10th of the progress bar for the non-module-load steps. OTHER_STEPSIZE=$(expr $MAX_STEPS / 10 / $OTHER_STEPS) db_progress START 0 $MAX_STEPS $PROGRESSBAR db_progress INFO hw-detect/detect_progress_step # TODO: Can possibly be removed if udev will load yenta_socket automatically # Load yenta_socket, if hardware is available, for Cardbus cards. if [ -d /sys/bus/pci/devices ] && \ grep -q 0x060700 /sys/bus/pci/devices/*/class 2>/dev/null && \ ! grep -q ^yenta_socket /proc/modules; then db_subst hw-detect/load_progress_step CARDNAME "Cardbus bridge" db_subst hw-detect/load_progress_step MODULE "yenta_socket" db_progress INFO hw-detect/load_progress_step log "Detected Cardbus bridge, loading yenta_socket" load_module yenta_socket # Ugly hack, but what's the alternative? sleep 3 || true fi # Load the ethernet gadget network driver (g_ether) on S3C2410/S3C2440 (Openmoko GTA01/02) if [ -d /sys/bus/platform/devices/s3c2440-usbgadget -o \ -d /sys/bus/platform/devices/s3c2410-usbgadget ] ; then db_subst hw-detect/load_progress_step CARDNAME "S3C2410/S3C2440 SoC" db_subst hw-detect/load_progress_step MODULE "g_ether" db_progress INFO hw-detect/load_progress_step log "Detected S3C2410/S3C2440 SoC, loading g_ether" load_module g_ether register-module g_ether fi # Load xenbus_probe_frontend if we're running under the Xen hypervisor, so # that it can deal with autoloading such things as xen-blkfront and # xen-netfront. if [ "$(cat /sys/hypervisor/type 2>/dev/null || true)" = xen ] && \ [ ! -d /sys/bus/xen ]; then db_subst hw-detect/load_progress_step CARDNAME "Xen frontend" db_subst hw-detect/load_progress_step MODULE "xenbus_probe_frontend" db_progress INFO hw-detect/load_progress_step log "Detected Xen hypervisor, loading xenbus_probe_frontend" load_module xenbus_probe_frontend register-module -i xenbus_probe_frontend fi # If using real hotplug, re-run the rc scripts to pick up new modules. # TODO: this just loads modules itself, rather than handing back a list # Since we've just run depmod, new modules might be available, so we # must trigger as well as settle. update-dev >/dev/null ALL_HW_INFO=$(get_detected_hw_info; get_manual_hw_info) db_progress STEP $OTHER_STEPSIZE # Remove modules that are already loaded or not available, and construct # the list for the question. LIST="" PROCESSED="" AVAIL_MODULES="$(find /lib/modules/$(uname -r)/ | sed 's!.*/!!' | cut -d . -f 1)" LOADED_MODULES="$(cut -d " " -f 1 /proc/modules) $(cut -d " " -f 1 /proc/modules | sed -e 's/_/-/g')" IFS_SAVE="$IFS" IFS="$NEWLINE" for device in $ALL_HW_INFO; do module="${device%%:*}" cardname="${device##*:}" if [ "$module" != "ignore" -a "$module" != "" ] && ! in_list "$module" "$LOADED_MODULES" && ! in_list "$module" "$PROCESSED" then if [ -z "$cardname" ]; then cardname="[Unknown]" fi if in_list "$module" "$AVAIL_MODULES"; then LIST="${LIST:+$LIST, }$module ($(echo "$cardname" | sed 's/,/ /g'))" PROCESSED="$PROCESSED $module" else missing_module "$module" "$cardname" fi fi done IFS="$IFS_SAVE" db_progress STEP $OTHER_STEPSIZE if [ "$LIST" ]; then # Ask which modules to install. db_subst hw-detect/select_modules list "$LIST" db_set hw-detect/select_modules "$LIST" db_input medium hw-detect/select_modules || true db_go || exit 10 # back up db_get hw-detect/select_modules LIST="$RET" fi list_to_lines() { echo "$LIST" | sed 's/, /\n/g' } # Work out amount to step per module load. expr rounds down, so # it may not get quite to 100%, but will at least never exceed it. MODULE_STEPS=$(expr \( $MAX_STEPS - \( $OTHER_STEPS \* $OTHER_STEPSIZE \) \)) if [ "$LIST" ]; then MODULE_STEPSIZE=$(expr $MODULE_STEPS / $(list_to_lines | wc -l)) fi IFS="$NEWLINE" for device in $(list_to_lines); do module="${device%% *}" cardname="`echo $device | cut -d'(' -f2 | sed 's/)$//'`" # Restore IFS after extracting the fields. IFS="$IFS_SAVE" if [ -z "$module" ] ; then module="[Unknown]" ; fi if [ -z "$cardname" ] ; then cardname="[Unknown]" ; fi log "Detected module '$module' for '$cardname'" if is_not_loaded "$module"; then db_subst hw-detect/load_progress_step CARDNAME "$cardname" db_subst hw-detect/load_progress_step MODULE "$module" db_progress INFO hw-detect/load_progress_step if [ "$cardname" = "[Unknown]" ]; then load_module "$module" else load_module "$module" "$cardname" fi fi db_progress STEP $MODULE_STEPSIZE IFS="$NEWLINE" done IFS="$IFS_SAVE" if [ -z "$LIST" ]; then db_progress STEP $MODULE_STEPS fi # Load ide-generic and check if that results in new block devices. # If so, make sure it is added to the initrd for the installed system. # Note: this may need to be done for more systems than just systems # that have an ISA bus, but that seems like a good start; it could also # be done unconditionally. if [ -z "$LOAD_IDE" ] && is_not_loaded ide-generic && \ [ -e /sys/bus/isa ] && is_available ide-generic; then update-dev --settle >/dev/null blockdev_count=$(ls /sys/block | wc -w) log "ISA bus detected; loading module 'ide-generic'" load_module ide-generic update-dev --settle >/dev/null if [ $(ls /sys/block | wc -w) -gt $blockdev_count ]; then log "New devices detected after loading ide-generic" # This will tell initramfs-tools to load ide-generic kopts= if db_get debian-installer/add-kernel-opts && [ "$RET" ]; then kopts="$RET" fi if ! echo "$kopt" | grep -Eq "(^| )all_generic_ide(=1|)( |$)"; then db_set debian-installer/add-kernel-opts \ "${kopts:+$kopts }all_generic_ide=1" fi fi fi if ! is_not_loaded ohci1394 || ! is_not_loaded firewire-ohci; then # if firewire was found, try to enable firewire cd support if is_not_loaded sbp2 && is_not_loaded firewire-sbp2 && \ is_available scsi_mod; then sbp2module= if is_available firewire-sbp2; then sbp2module=firewire-sbp2 elif is_available sbp2; then sbp2module=sbp2 fi if [ -n "$sbp2module" ]; then db_subst hw-detect/load_progress_step CARDNAME "FireWire CDROM support" db_subst hw-detect/load_progress_step MODULE "$sbp2module" db_progress INFO hw-detect/load_progress_step load_module "$sbp2module" register-module "$sbp2module" else missing_module firewire-sbp2 "FireWire CDROM" fi fi db_progress STEP $OTHER_STEPSIZE # also try to enable firewire ethernet (The right way to do this is # really to catch the hotplug events from the kernel.) if is_not_loaded eth1394; then if is_available eth1394; then db_subst hw-detect/load_progress_step CARDNAME "FireWire ethernet support" db_subst hw-detect/load_progress_step MODULE "eth1394" db_progress INFO hw-detect/load_progress_step load_module eth1394 "FireWire ethernet" # do not call register-module; udev/hotplug will load it # on the installed system else missing_module eth1394 "FireWire ethernet" fi fi fi apply_pcmcia_resource_opts() { local config_opts=/etc/pcmcia/config.opts # Idempotency if ! [ -f ${config_opts}.orig ]; then cp $config_opts ${config_opts}.orig fi cp ${config_opts}.orig $config_opts local mode="" local rmode="" local type="" local value="" while [ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ]; do if [ "$1" = exclude ]; then mode=exclude rmode=include shift elif [ "$1" = include ]; then mode=include rmode=exclude shift fi type="$1" shift value="$1" shift if grep -q "^$rmode $type $value\$" $config_opts; then sed "s/^$rmode $type $value\$/$mode $type $value/" \ $config_opts >${config_opts}.new mv ${config_opts}.new $config_opts else echo "$mode $type $value" >>$config_opts fi done } # get pcmcia running if possible PCMCIA_INIT=/etc/init.d/pcmciautils if [ -x "$PCMCIA_INIT" ]; then if is_not_loaded pcmcia_core; then db_input low hw-detect/pcmcia_resources || true db_go || true if db_get hw-detect/pcmcia_resources && [ "$RET" ]; then apply_pcmcia_resource_opts $RET fi # cdebconf doesn't set seen flags, so this would normally be # asked again on subsequent hw-detect runs, which is # annoying. db_fset hw-detect/pcmcia_resources seen true || true db_progress INFO hw-detect/pcmcia_step $PCMCIA_INIT start 2>&1 | log db_progress STEP $OTHER_STEPSIZE fi fi have_pcmcia=0 if ls /sys/class/pcmcia_socket/* >/dev/null 2>&1; then if db_get hw-detect/start_pcmcia && [ "$RET" = false ]; then have_pcmcia=0 else have_pcmcia=1 fi fi # find Cardbus network cards cardbus_check_netdev() { local socket="$1" local netdev="$2" if [ -L "$netdev/device" ] && \ [ -d "$socket/device/$(basename "$(readlink "$netdev/device")")" ]; then echo "$(basename "$netdev")" >> /etc/network/devhotplug fi } # Try to do this only once.. if [ "$have_pcmcia" -eq 1 ] && \ ! grep -q pcmciautils /var/lib/apt-install/queue 2>/dev/null; then log "Detected PCMCIA, installing pcmciautils." apt-install pcmciautils || true for socket in /sys/class/pcmcia_socket/*; do for netdev in /sys/class/net/*; do cardbus_check_netdev "$socket" "$netdev" done done if db_get hw-detect/pcmcia_resources && [ -n "$RET" ]; then echo "mkdir /target/etc/pcmcia 2>/dev/null || true" \ >>$finish_install echo "cp /etc/pcmcia/config.opts /target/etc/pcmcia/config.opts" \ >>$finish_install fi fi # Install udev into target apt-install udev || true # Install pciutils/usbutils if [ -d /sys/bus/pci ]; then apt-install pciutils || true fi if [ -d /sys/bus/usb ]; then apt-install usbutils || true fi # If hardware has support for pmu, install pbbuttonsd if [ -d /sys/class/misc/pmu/ ]; then apt-install pbbuttonsd || true fi # Install eject? if [ -n "$(list-devices cd; list-devices maybe-usb-floppy)" ]; then apt-install eject || true fi # Install opal-prd for OpenPOWER machines LP: #1555904 if [ -d /sys/firmware/devicetree/base/ibm,opal/diagnostics ]; then apt-install opal-prd || true fi db_progress SET $MAX_STEPS db_progress STOP if [ -n "$MISSING_MODULES_LIST" ]; then log "Missing modules '$MISSING_MODULES_LIST" fi if [ "$CHECK_MISSING_FIRMWARE" != 0 ]; then check-missing-firmware else log "skipping check-missing-firmware as requested by the caller" fi sysfs-update-devnames # Let userspace /dev tools rescan the devices update-dev --settle >/dev/null exit 0