home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Linux / Ubuntu_64-bit / ubuntu-11.04-desktop-amd64.iso / casper / filesystem.squashfs / bin / check-missing-firmware < prev    next >
Text File  |  2011-04-22  |  6KB  |  231 lines

  1. #!/bin/sh
  2. set -e
  3. . /usr/share/debconf/confmodule
  4.  
  5. MISSING=/dev/.udev/firmware-missing
  6. DENIED=/tmp/missing-firmware-denied
  7.  
  8. if [ "x$1" = "x-n" ]; then
  9.     NONINTERACTIVE=1
  10. else
  11.     NONINTERACTIVE=""
  12. fi
  13.  
  14. log () {
  15.     logger -t check-missing-firmware "$@"
  16. }
  17.  
  18. # Not all drivers register themselves if firmware is missing; in that
  19. # case determine the module via the device's modalias.
  20. get_module () {
  21.     local devpath=$1
  22.  
  23.     if [ -d $devpath/driver ]; then
  24.         # The realpath of the destination of the driver/module
  25.         # symlink should be something like "/sys/module/e100"
  26.         basename $(realpath $devpath/driver/module) || true
  27.     elif [ -e $devpath/modalias ]; then
  28.         modalias="$(cat $devpath/modalias)"
  29.         # Take the last module returned by modprobe
  30.         modprobe --show-depends "$modalias" 2>/dev/null | \
  31.             sed -n -e '$s#^.*/\([^.]*\)\.ko.*$#\1#p'
  32.     fi
  33. }
  34.  
  35. check_missing () {
  36.     # Give modules some time to request firmware.
  37.     sleep 1
  38.     
  39.     modules=""
  40.     files=""
  41.     if [ -d "$MISSING" ]; then
  42.         for file in $(find $MISSING -type l); do
  43.             # decode firmware filename as encoded by
  44.             # udev firmware.agent
  45.             fwfile="$(basename $file | sed -e 's#\\x2f#/#g')"
  46.             
  47.             # strip probably nonexistant firmware subdirectory
  48.             devpath="$(readlink $file | sed 's/\/firmware\/.*//')"
  49.             # the symlink is supposed to point to the device in /sys
  50.             if ! echo "$devpath" | grep -q '^/sys/'; then
  51.                 devpath="/sys$devpath"
  52.             fi
  53.  
  54.             module=$(get_module "$devpath")
  55.             if [ -z "$module" ]; then
  56.                 log "failed to determine module from $devpath"
  57.                 continue
  58.             fi
  59.  
  60.             rm -f "$file"
  61.  
  62.             if grep -q "^$fwfile$" $DENIED 2>/dev/null; then
  63.                 continue
  64.             fi
  65.  
  66.             modules="$module${modules:+ $modules}"
  67.             files="$fwfile${files:+ $files}"
  68.         done
  69.     fi
  70.  
  71.     if [ -n "$modules" ]; then
  72.         log "missing firmware files ($files) for $modules"
  73.         return 0
  74.     else
  75.         log "no missing firmware in $MISSING"
  76.         return 1
  77.     fi
  78. }
  79.  
  80. # If found, copy firmware file; preserve subdirs.
  81. try_copy () {
  82.     local fwfile=$1
  83.     local sdir file f target
  84.  
  85.     sdir=$(dirname $fwfile | sed "s/^\.$//")
  86.     file=$(basename $fwfile)
  87.     for f in "/media/$fwfile" "/media/firmware/$fwfile" \
  88.          ${sdir:+"/media/$file" "/media/firmware/$file"}; do
  89.         if [ -e "$f" ]; then
  90.             target="/lib/firmware${sdir:+/$sdir}"
  91.             log "copying loose file $file from '$(dirname $f)' to '$target'"
  92.             mkdir -p "$target"
  93.             rm -f "$target/$file"
  94.             cp -aL "$f" "$target" || true
  95.             break
  96.         fi
  97.     done
  98. }
  99.  
  100. first_try=1
  101. first_ask=1
  102. ask_load_firmware () {
  103.     if [ "$first_try" ]; then
  104.         first_try=""
  105.         return 0
  106.     fi
  107.  
  108.     if [ "$NONINTERACTIVE" ]; then
  109.         if [ ! "$first_ask" ]; then
  110.             return 1
  111.         else
  112.             first_ask=""
  113.             return 0
  114.         fi
  115.     fi
  116.  
  117.     db_subst hw-detect/load_firmware FILES "$files"
  118.     if ! db_input high hw-detect/load_firmware; then
  119.         if [ ! "$first_ask" ]; then
  120.             exit 1;
  121.         else
  122.             first_ask=""
  123.         fi
  124.     fi
  125.     if ! db_go; then
  126.         exit 10 # back up
  127.     fi
  128.     db_get hw-detect/load_firmware
  129.     if [ "$RET" = true ]; then
  130.         return 0
  131.     else
  132.         echo "$files" | tr ' ' '\n' >> $DENIED
  133.         return 1
  134.     fi
  135. }
  136.  
  137. list_deb_firmware () {
  138.     ar p "$1" data.tar.gz | tar zt \
  139.         | grep '^\./lib/firmware/' \
  140.         | sed -e 's!^\./lib/firmware/!!' \
  141.         | grep -v '^$'
  142. }
  143.  
  144. check_deb_arch () {
  145.     arch=$(ar p "$1" control.tar.gz | tar zxO ./control | grep '^Architecture:' | sed -e 's/Architecture: *//')
  146.     [ "$arch" = all ] || [ "$arch" = "$(udpkg --print-architecture)" ]
  147. }
  148.  
  149. # Remove non-accepted firmware package
  150. remove_pkg() {
  151.     pkgname="$1"
  152.     # Remove all files listed in /var/lib/dpkg/info/$pkgname.md5sum
  153.     for file in $(cut -d" " -f 2- /var/lib/dpkg/info/$pkgname.md5sum) ; do
  154.         rm /$file
  155.     done
  156. }
  157.  
  158. install_firmware_pkg () {
  159.     if echo "$1" | grep -q '\.deb$'; then
  160.         # cache deb for installation into /target later
  161.         mkdir -p /var/cache/firmware/
  162.         cp -aL "$1" /var/cache/firmware/ || true
  163.         filename="$(basename "$1")"
  164.         pkgname="$(echo $filename |cut -d_ -f1)"
  165.         udpkg --unpack "/var/cache/firmware/$filename"
  166.         if [ -f /var/lib/dpkg/info/$pkgname.preinst ] ; then
  167.             # Run preinst script to see if the firmware
  168.             # license is accepted Exit code of preinst
  169.             # decide if the package should be installed or
  170.             # not.
  171.             if /var/lib/dpkg/info/$pkgname.preinst ; then
  172.                 :
  173.             else
  174.                 remove_pkg "$pkgname"
  175.                 rm "/var/cache/firmware/$filename"
  176.             fi
  177.         fi
  178.     else
  179.         udpkg --unpack "$1"
  180.     fi
  181. }
  182.  
  183. # Try to load udebs (or debs) that contain the missing firmware.
  184. # This does not use anna because debs can have arbitrary
  185. # dependencies, which anna might try to install.
  186. check_for_firmware() {
  187.     echo "$files" | sed -e 's/ /\n/g' >/tmp/grepfor
  188.     for filename in $@; do
  189.         if [ -f "$filename" ]; then
  190.             if check_deb_arch "$filename" && list_deb_firmware "$filename" | grep -qf /tmp/grepfor; then
  191.                 log "installing firmware package $filename"
  192.                 install_firmware_pkg "$filename" || true
  193.             fi
  194.         fi
  195.     done
  196.     rm -f /tmp/grepfor
  197. }
  198.  
  199. while check_missing && ask_load_firmware; do
  200.     # first, check if needed firmware (u)debs are available on the
  201.     # PXE initrd or the installation CD.
  202.     if [ -d /firmware ]; then
  203.         check_for_firmware /firmware/*.deb /firmware/*.udeb
  204.     fi
  205.     if [ -d /cdrom/firmware ]; then
  206.         check_for_firmware /cdrom/firmware/*.deb /cdrom/firmware/*.udeb
  207.     fi
  208.  
  209.     # second, look for loose firmware files on the media device.
  210.     if mountmedia; then
  211.         for file in $files; do
  212.             try_copy "$file"
  213.         done
  214.         umount /media || true
  215.     fi
  216.  
  217.     # last, look for firmware (u)debs on the media device
  218.     if mountmedia driver; then
  219.         check_for_firmware /media/*.deb /media/*.udeb /media/*.ude /media/firmware/*.deb /media/firmware/*.udeb /media/firmware/*.ude
  220.         umount /media || true
  221.     fi
  222.  
  223.     # remove and reload modules so they see the new firmware
  224.     # Sort to only reload a given module once if it ask for more
  225.     # than one firmware file (example iwlagn)
  226.     for module in $(echo $modules | tr " " "\n" | sort -u); do
  227.         modprobe -r $module || true
  228.         modprobe $module || true
  229.     done
  230. done
  231.