1 if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
3 # Copyright (c) 2012-2014 Devin Teske
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 ############################################################ INCLUDES
31 BSDCFG_SHARE="/usr/share/bsdconfig"
32 . $BSDCFG_SHARE/common.subr || exit 1
33 f_dprintf "%s: loading includes..." device.subr
34 f_include $BSDCFG_SHARE/dialog.subr
35 f_include $BSDCFG_SHARE/geom.subr
36 f_include $BSDCFG_SHARE/strings.subr
37 f_include $BSDCFG_SHARE/struct.subr
39 BSDCFG_LIBE="/usr/libexec/bsdconfig"
40 f_include_lang $BSDCFG_LIBE/include/messages.subr
42 ############################################################ GLOBALS
44 NDEVICES=0 # Set by f_device_register(), used by f_device_*()
47 # A "device" from legacy sysinstall's point of view (mostly)
49 # NB: Disk devices have their `private' property set to GEOM ident
50 # NB: USB devices have their `private' property set to USB disk device name
52 f_struct_define DEVICE \
66 # Network devices have their `private' property set to this
67 f_struct_define DEVICE_INFO \
76 # Device types for f_device_register(), f_device_find(), et al.
78 setvar DEVICE_TYPE_ANY "any" # Any
79 setvar DEVICE_TYPE_NONE "NONE" # Unknown
80 setvar DEVICE_TYPE_DISK "DISK" # GEOM `DISK'
81 setvar DEVICE_TYPE_FLOPPY "FD" # GEOM `FD'
82 setvar DEVICE_TYPE_FTP "FTP" # Dynamic network device
83 setvar DEVICE_TYPE_NETWORK "NETWORK" # See f_device_get_all_network
84 setvar DEVICE_TYPE_CDROM "CDROM" # GEOM `DISK'
85 setvar DEVICE_TYPE_USB "USB" # GEOM `PART'
86 setvar DEVICE_TYPE_DOS "DOS" # GEOM `DISK' `PART' or `LABEL'
87 setvar DEVICE_TYPE_UFS "UFS" # GEOM `DISK' `PART' or `LABEL'
88 setvar DEVICE_TYPE_NFS "NFS" # Dynamic network device
89 setvar DEVICE_TYPE_HTTP_PROXY "HTTP_PROXY" # Dynamic network device
90 setvar DEVICE_TYPE_HTTP "HTTP" # Dynamic network device
92 # Network devices have the following flags available
98 # Default behavior is to call f_device_get_all() automatically when loaded.
100 : ${DEVICE_SELF_SCAN_ALL=1}
103 # Device Catalog variables
105 DEVICE_CATALOG_APPEND_ONLY= # Used by f_device_catalog_set()
106 NCATALOG_DEVICES=0 # Used by f_device_catalog_*() and MAIN
109 # A ``catalog'' device is for mapping GEOM devices to media devices (for
110 # example, determining if a $GEOM_CLASS_DISK geom is $DEVICE_TYPE_CDROM or
111 # $DEVICE_TYPE_DISK) and also getting default descriptions for devices that
112 # either lack a GEOM provided description or lack a presence in GEOM)
114 f_struct_define CATALOG_DEVICE \
119 ############################################################ FUNCTIONS
121 # f_device_register $var_to_set $name $desc $devname $type $enabled
122 # $init_function $get_function $shutdown_function
125 # Register a device. A `structure' (see struct.subr) is created and if
126 # $var_to_set is non-NULL, upon success holds the name of the struct created.
127 # The remaining positional arguments correspond to the properties of the
128 # `DEVICE' structure-type to be assigned (defined above).
130 # If not already registered (based on $name and $type), a new device is created
131 # and $NDEVICES is incremented.
135 local __var_to_set="$1" __name="$2" __desc="$3" __devname="$4"
136 local __type="$5" __enabled="$6" __init_func="$7" __get_func="$8"
137 local __shutdown_func="$9" __private="${10}" __capacity="${11}"
139 # Required parameter(s)
140 [ "$__name" ] || return $FAILURE
141 if [ "$__var_to_set" ]; then
142 setvar "$__var_to_set" "" || return $FAILURE
146 if f_device_find -1 "$__name" "$__type" __device; then
147 f_struct_free "$__device"
148 f_struct_new DEVICE "$__device" || return $FAILURE
150 __device=device_$(( NDEVICES + 1 ))
151 f_struct_new DEVICE "$__device" || return $FAILURE
152 NDEVICES=$(( $NDEVICES + 1 ))
154 $__device set name "$__name"
155 $__device set desc "$__desc"
156 $__device set devname "$__devname"
157 $__device set type "$__type"
158 $__device set enabled "$__enabled"
159 $__device set init "$__init_func"
160 $__device set get "$__get_func"
161 $__device set shutdown "$__shutdown_func"
162 $__device set private "$__private"
163 $__device set capacity "$__capacity"
165 [ "$__var_to_set" ] && setvar "$__var_to_set" "$__device"
171 # Reset the registered device chain.
176 while [ $n -le $NDEVICES ]; do
177 f_device_shutdown device_$n
180 # XXX This potentially leaks $dev->private if it's being
181 # used to point to something dynamic, but you're not supposed
182 # to call this routine at such times that some open instance
183 # has its private member pointing somewhere anyway.
185 f_struct_free device_$n
192 # f_device_reset_network
194 # Reset the registered network device chain.
196 f_device_reset_network()
198 local n=1 device type private i
199 while [ $n -le $NDEVICES ]; do
201 f_struct $device || continue
202 $device get type type
203 [ "$type" = "$DEVICE_TYPE_NETWORK" ] || continue
206 # Leave the device up (don't call shutdown routine)
209 # Network devices may have DEVICE_INFO private member
210 $device get private private
211 [ "$private" ] && f_struct_free "$private"
213 # Free the network device
214 f_struct_free $device
216 # Fill the gap we just created
218 while [ $i -lt $NDEVICES ]; do
219 f_struct_copy device_$(( $i + 1 )) device_$i
221 f_struct_free device_$NDEVICES
223 # Finally decrement the number of devices
224 NDEVICES=$(( $NDEVICES - 1 ))
232 # Get all device information for all devices.
236 local devname type desc capacity
238 f_dprintf "f_device_get_all: Probing devices..."
239 f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
241 # First go for the network interfaces
242 f_device_get_all_network
244 # Next, go for the GEOM devices we might want to use as media
245 local geom geoms geom_name
246 debug= f_geom_find "" $GEOM_CLASS_DEV geoms
247 for geom in $geoms; do
248 if ! f_device_probe_geom $geom; then
249 debug= $geom get name geom_name
250 f_dprintf "WARNING! Unable to classify %s as %s" \
251 "GEOM device $geom_name" "media source"
256 # f_device_get_all_network
258 # Get all network device information for attached network devices.
260 f_device_get_all_network()
262 local devname desc device flags
263 for devname in $( ifconfig -l ); do
264 # Eliminate network devices that don't make sense
269 # Try and find its description
270 f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
272 f_dprintf "Found network device named %s" "$devname"
273 debug= f_device_register device $devname "$desc" \
274 "$devname" $DEVICE_TYPE_NETWORK 1 \
275 f_media_init_network "" f_media_shutdown_network "" -1
277 # Set flags based on media and status
279 eval "$( ifconfig $devname 2> /dev/null | awk -v var=flags '
280 function _or(var, mask) {
281 printf "%s=$(( $%s | $%s ))\n", var, var, mask
283 BEGIN { S = "[[:space:]]+" }
285 if (!match($0, "^" S "(media|status):" S)) next
286 value = substr($0, RLENGTH + 1)
287 if ($1 == "media:") {
288 if (value ~ /Ethernet/) _or(var, "IF_ETHERNET")
289 if (value ~ /802\.11/) _or(var, "IF_WIRELESS")
290 } else if ($1 == "status:") {
291 if (value ~ /^active/) _or(var, "IF_ACTIVE")
294 $device set flags $flags
300 # Rescan all devices, after closing previous set - convenience function.
309 # f_device_rescan_network
311 # Rescan all network devices, after closing previous set - for convenience.
313 f_device_rescan_network()
315 f_device_reset_network
316 f_device_get_all_network
319 # f_device_probe_geom $geom
321 # Probe a single GEOM device and if it can be classified as a media source,
322 # register it using f_device_register() with known type-specific arguments.
324 f_device_probe_geom()
328 f_struct "$geom" || return $FAILURE
330 # geom associated variables
331 local geom_name geom_consumer provider_ref geom_provider=
332 local provider_geom provider_config provider_class=
333 local provider_config_type catalog_struct catalog_type
336 # gnop(8)/geli(8) associated variables (p for `parent device')
337 local p_devname p_geom p_consumer p_provider_ref p_provider
338 local p_provider_config p_provider_geom p_provider_class
340 # md(4) associated variables
341 local config config_type config_file magic=
343 # Temporarily disable debugging to keep debug output light
344 local old_debug="$debug" debug=
347 # Get the GEOM name (for use below in device registration)
349 $geom get name devname || continue
352 # Attempt to get the consumer, provider, provider config, and
353 # provider class for this geom (errors ignored).
355 # NB: Each GEOM in the `DEV' class should have one consumer.
356 # That consumer should have a reference to its provider.
358 $geom get consumer1 geom_consumer
359 f_struct "$geom_consumer" get provider_ref provider_ref &&
360 f_geom_find_by id "$provider_ref" provider geom_provider
361 if f_struct "$geom_provider"; then
362 $geom_provider get config provider_config
363 f_geom_parent $geom_provider provider_geom &&
364 f_geom_parent $provider_geom provider_class
368 # Get values for device registration (errors ignored)
370 f_struct "$provider_class" get name type
371 f_struct "$geom_provider" get mediasize capacity
372 f_struct "$provider_config" get descr desc
375 # For gnop(8), geli(8), or combination thereof, change device type to
376 # that of the consumer
378 p_devname= p_geom= p_provider= p_provider_config=
380 *.nop.eli) p_devname="${devname%.nop.eli}" ;;
381 *.eli.nop) p_devname="${devname%.eli.nop}" ;;
382 *.eli) p_devname="${devname%.eli}" ;;
383 *.nop) p_devname="${devname%.nop}" ;;
385 [ "$p_devname" ] && f_geom_find "$p_devname" $GEOM_CLASS_DEV p_geom
386 if [ "${p_geom:-$geom}" != "$geom" ]; then
387 f_struct "$p_geom" get consumer1 p_consumer
388 f_struct "$p_consumer" get provider_ref p_provider_ref &&
389 f_geom_find_by id "$p_provider_ref" provider p_provider
390 if f_struct "$p_provider"; then
391 $p_provider get config p_provider_config
392 f_geom_parent $p_provider p_provider_geom &&
393 f_geom_parent $p_provider_geom p_provider_class
395 f_struct "$p_provider_class" get name type
398 # Look up geom device in device catalog for default description
399 f_device_catalog_get \
400 $DEVICE_TYPE_ANY "${p_devname:-$devname}" catalog_struct
401 [ "$desc" ] || f_struct "catalog_device_$catalog_struct" get desc desc
403 # Use device catalog entry for potential re-classification(s)
404 f_struct "catalog_device_$catalog_struct" get type catalog_type
406 # Restore debugging for this next part (device registration)
410 # Register the device
415 # First attempt to classify by device catalog (see MAIN)
416 case "$catalog_type" in
418 f_dprintf "Found CDROM device for disk %s" "$devname"
419 debug= f_device_register device "$devname" "$desc" \
420 "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
421 f_media_init_cdrom f_media_get_cdrom \
422 f_media_shutdown_cdrom "" "$capacity" &&
427 # Fall back to register label device as a disk and taste it
428 f_dprintf "Found disk device named %s" "$devname"
429 debug= f_struct "$p_provider_config" get \
431 debug= f_struct "$provider_config" get \
433 debug= f_device_register device "$devname" "$desc" \
434 "/dev/$devname" $DEVICE_TYPE_DISK 1 \
435 "" "" "" "$disk_ident" "$capacity"
438 # Detect ``dangerously dedicated'' filesystems (errors ignored)
439 f_device_probe_disk_fs device "$devname" "$capacity" &&
445 f_dprintf "Found floppy device named %s" "$devname"
446 debug= f_device_register device "$devname" "$desc" \
447 "/dev/$devname" $DEVICE_TYPE_FLOPPY 1 \
448 f_media_init_floppy f_media_get_floppy \
449 f_media_shutdown_floppy "" "$capacity"
453 : fall through to below section # reduces indentation level
456 f_dprintf "Found disk device named %s" "$devname"
457 debug= f_device_register device "$devname" "$desc" \
458 "/dev/$devname" $DEVICE_TYPE_DISK 1 \
459 "" "" "" "" "$capacity"
463 # Attempt to get file(1) magic to potentially classify as
464 # alternate media type. If unable to get magic, fall back to
465 # md(4) characteristics (such as vnode filename).
467 [ -r "/dev/$devname" ] &&
468 magic=$( file -bs "/dev/$devname" 2> /dev/null )
469 if [ ! "$magic" ]; then
470 # Fall back to md(4) characteristics
471 if f_struct "$p_provider_config"; then
472 config="$p_provider_config"
474 config="$provider_config"
476 debug= f_struct "$config" get type config_type
477 debug= f_struct "$config" get file config_file
479 # Substitute magic for below based on type and file
480 case "$config_type=$config_file" in
481 vnode=*.iso) magic="ISO 9660" ;;
484 f_device_probe_disk_fs device \
485 "$devname" "$capacity" "$magic" &&
486 retval=$SUCCESS # Errors ignored
491 if f_struct "$p_provider_config"; then
492 config="$p_provider_config"
494 config="$provider_config"
496 debug= f_struct "$config" get type provider_config_type
497 f_device_probe_geom_part device \
498 "$provider_config_type" "$devname" "$capacity"
500 device_type=$DEVICE_TYPE_NONE
501 [ $retval -eq $SUCCESS ] &&
502 debug= f_struct "$device" get type device_type
504 # Potentially re-classify as USB device
505 if [ "$device_type" = "$DEVICE_TYPE_UFS" -a \
506 "$catalog_type" = "$DEVICE_TYPE_USB" ]
508 f_dprintf "Found USB device for partition %s" \
510 debug= f_struct "$p_provider_geom" get \
512 debug= f_struct "$provider_geom" get \
514 debug= f_device_register device "$devname" "$desc" \
515 "/dev/$devname" $DEVICE_TYPE_USB 1 \
516 f_media_init_usb f_media_get_usb \
517 f_media_shutdown_usb "$disk_name" "$capacity"
524 # Use the provider geom name as the description
525 if [ ! "$desc" ]; then
526 f_struct "$p_provider_geom" get name desc ||
527 f_struct "$provider_geom" get name desc
530 f_dprintf "Found disk device named %s" "$devname"
531 debug= f_device_register device \
532 "$devname" "${desc:-GEOM RAID device}" \
533 "/dev/$devname" $DEVICE_TYPE_DISK 1 \
534 "" "" "" "" "$capacity"
537 # Detect ``dangerously dedicated'' filesystems
538 f_device_probe_disk_fs device "$devname" "$capacity" &&
539 retval=$SUCCESS # Errors ignored
543 $GEOM_CLASS_ZFS_ZVOL)
544 f_dprintf "Found disk device named %s" "$devname"
545 debug= f_device_register device \
546 "$devname" "${desc:-GEOM ZFS::ZVOL device}" \
547 "/dev/$devname" $DEVICE_TYPE_DISK 1 \
548 "" "" "" "" "$capacity"
551 # Detect ``dangerously dedicated'' filesystems
552 f_device_probe_disk_fs device "$devname" "$capacity" &&
553 retval=$SUCCESS # Errors ignored
558 return $FAILURE # Unknown GEOM class
562 # Still here? Must be $GEOM_CLASS_LABEL
565 local label_geom label_devname label_devgeom= label_devconsumer
566 local label_devprovider= label_devprovider_ref label_devprovider_config
567 local label_gpart_type
569 if f_struct "$p_provider"; then
570 label_geom="$p_provider_geom"
572 label_geom="$provider_geom"
578 # Attempt to get the partition type by getting the `config'
579 # member of the provider for our device (which is named in the
580 # parent geom of our current provider).
582 debug= f_struct "$label_geom" get name label_devname &&
583 debug= f_geom_find "$label_devname" $GEOM_CLASS_DEV \
585 debug= f_struct "$label_devgeom" get \
586 consumer1 label_devconsumer
587 debug= f_struct "$label_devconsumer" get \
588 provider_ref label_devprovider_ref &&
589 debug= f_geom_find_by id "$label_devprovider_ref" \
590 provider label_devprovider
591 debug= f_struct "$label_devprovider" get \
592 config label_devprovider_config
593 debug= f_struct "$label_devprovider_config" get \
594 type label_gpart_type
597 # Register device label based on partition type
599 f_device_probe_geom_part device \
600 "$label_gpart_type" "$devname" "$capacity"
604 f_dprintf "Found CDROM device labeled %s" "$devname"
605 debug= f_device_register device \
606 "$devname" "ISO9660 file system" \
607 "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
608 f_media_init_cdrom f_media_get_cdrom \
609 f_media_shutdown_cdrom "" "$capacity"
613 # For generic labels, use provider geom name as real device
614 debug= f_struct "$label_geom" get name label_devname
616 # Look up label geom device in device catalog for default desc
617 debug= f_device_catalog_get \
618 $DEVICE_TYPE_ANY "$label_devname" catalog_struct
619 [ "$desc" ] || debug= f_struct \
620 "catalog_device_$catalog_struct" get desc desc
622 # Use device catalog entry for potential re-classification(s)
623 debug= f_struct "catalog_device_$catalog_struct" get \
626 # First attempt to classify by device catalog (see MAIN)
627 case "$catalog_type" in
629 f_dprintf "Found CDROM device for disk %s" "$devname"
630 debug= f_device_register device "$devname" "$desc" \
631 "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
632 f_media_init_cdrom f_media_get_cdrom \
633 f_media_shutdown_cdrom "" "$capacity" &&
638 # Fall back to register label device as a disk and taste it
639 f_dprintf "Found disk device labeled %s" "$devname"
640 debug= f_device_register device \
641 "$devname" "GEOM LABEL device" \
642 "/dev/$devname" $DEVICE_TYPE_DISK 1 \
643 "" "" "" "" "$capacity"
646 # Detect ``dangerously dedicated'' filesystems (errors ignored)
647 f_device_probe_disk_fs device "$devname" "$capacity" &&
653 f_dprintf "Found DOS partition labeled %s" "$devname"
654 debug= f_device_register device "$devname" "DOS file system" \
655 "/dev/$devname" $DEVICE_TYPE_DOS 1 \
656 f_media_init_dos f_media_get_dos \
657 f_media_shutdown_dos "" "$capacity"
661 f_dprintf "Found UFS partition labeled %s" "$devname"
662 debug= f_device_register device "$devname" "UFS file system" \
663 "/dev/$devname" $DEVICE_TYPE_UFS 1 \
664 f_media_init_ufs f_media_get_ufs \
665 f_media_shutdown_ufs "" "$capacity"
668 ext2fs/*|ntfs/*|reiserfs/*)
669 return $FAILURE # No media device handlers for these labels
673 # Unable to classify GEOM label
677 # f_device_probe_geom_part $var_to_set $gpart_type $devname $capacity [$magic]
679 # Given a gpart(8) partition type and a device name, register the device if it
680 # is a known partition type that we can handle. If $var_to_set is non-NULL,
681 # upon success holds the DEVICE struct name of the registered device.
683 # Returns success if the device was successfully registered, failure otherwise.
685 f_device_probe_geom_part()
687 local __var_to_set="$1" __gpart_type="$2" __devname="$3"
688 local __capacity="${4:--1}" __magic="$5"
691 # Register device based on partition type
692 # NB: !0 equates to `unused' bsdlabel
694 case "$__gpart_type" in
696 f_dprintf "Found DOS partition named %s" "$__devname"
697 debug= f_device_register "$__var_to_set" \
698 "$__devname" "DOS file system" \
699 "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
700 f_media_init_dos f_media_get_dos \
701 f_media_shutdown_dos "" "$__capacity"
704 freebsd|!0) # Commonly used inappropriately, taste for FreeBSD
705 [ -r "/dev/$__devname" -a ! "$__magic" ] &&
706 __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
708 *"Unix Fast File system"*)
709 f_dprintf "Found UFS partition named %s" "$__devname"
710 debug= f_device_register "$__var_to_set" \
711 "$__devname" "UFS file system" \
712 "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
713 f_media_init_ufs f_media_get_ufs \
714 f_media_shutdown_ufs "" "$__capacity"
720 f_dprintf "Found UFS partition named %s" "$__devname"
721 debug= f_device_register "$__var_to_set" \
722 "$__devname" "UFS file system" \
723 "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
724 f_media_init_ufs f_media_get_ufs \
725 f_media_shutdown_ufs "" "$__capacity"
728 apple-*|linux-*|ms-*|netbsd-*|ntfs|vmware-*)
729 return $FAILURE # No device types for these
731 bios-*|ebr|efi|mbr|freebsd-boot|freebsd-swap)
732 return $FAILURE # Not a source for media
734 freebsd-nandfs|freebsd-vinum|freebsd-zfs)
735 return $FAILURE # Unsupported as media source
739 return $FAILURE # Unknown partition type
742 # f_device_probe_disk_fs $var_to_set $devname [$capacity [$magic]]
744 # Given a device name, taste it and register the device if it is a so-called
745 # ``dangerously dedicated'' file system written without a partition table.
746 # Tasting is done using file(1) (specifically `file -bs') but if $magic is
747 # present and non-NULL it is used instead. If $var_to_set is non-NULL, upon
748 # success holds the DEVICE struct name of the registered device.
750 # Returns success if the device was successfully registered, failure otherwise.
752 f_device_probe_disk_fs()
754 local __var_to_set="$1" __devname="$2" __capacity="${3:--1}"
757 [ -r "/dev/${__devname#/dev/}" -a ! "$__magic" ] &&
758 __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
762 f_dprintf "Found CDROM device for disk %s" "$__devname"
763 debug= f_device_register "$__var_to_set" \
764 "$__devname" "ISO9660 file system" \
765 "/dev/$__devname" $DEVICE_TYPE_CDROM 1 \
766 f_media_init_cdrom f_media_get_cdrom \
767 f_media_shutdown_cdrom "" "$__capacity"
770 *"Unix Fast File system"*)
771 f_dprintf "Found UFS device for disk %s" "$__devname"
772 debug= f_device_register "$__var_to_set" \
773 "$__devname" "UFS file system" \
774 "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
775 f_media_init_ufs f_media_get_ufs \
776 f_media_shutdown_ufs "" "$__capacity"
779 *"FAT (12 bit)"*|*"FAT (16 bit)"*|*"FAT (32 bit)"*)
780 f_dprintf "Found DOS device for disk %s" "$__devname"
781 debug= f_device_register "$__var_to_set" \
782 "$__devname" "DOS file system" \
783 "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
784 f_media_init_dos f_media_get_dos \
785 f_media_shutdown_dos "" "$__capacity"
790 return $FAILURE # Unknown file system type
793 # f_device_catalog_get $type $name [$var_to_set]
795 # Fetch the struct name of the catalog device matching device $name. If $type
796 # is either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
797 # Returns success if a match was found, otherwise failure.
799 # If $var_to_set is missing or NULL, the struct name is printed to standard out
800 # for capturing in a sub-shell (which is less-recommended because of
801 # performance degredation; for example, when called in a loop).
803 f_device_catalog_get()
805 local __type="$1" __name="$2" __var_to_set="$3"
808 # Return failure if no $name
809 [ "$__name" ] || return $FAILURE
811 # Disable debugging to keep debug output light
815 # Attempt to create an alternate-form of $__name that contains the
816 # first contiguous string of numbers replaced with `%d' for comparison
817 # against stored pattern names (see MAIN).
819 local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}"
820 if [ "$__left" != "$__name" ]; then
821 # Chop leading digits from right 'til we hit first non-digit
824 [0-9]*) __right="${__right#[0-9]}" ;;
828 __dname="${__left}%d$__right"
831 [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
832 local __dev __dev_name __dev_type
833 for __dev in $DEVICE_CATALOG; do
834 catalog_device_$__dev get name __dev_name
835 [ "$__dev_name" = "$__name" -o "$__dev_name" = "$__dname" ] ||
837 catalog_device_$__dev get type __dev_type
838 [ "${__type:-$__dev_type}" = "$__dev_type" ] || continue
839 if [ "$__var_to_set" ]; then
840 setvar "$__var_to_set" $__dev
847 [ "$__var_to_set" ] && setvar "$__var_to_set" ""
851 # f_device_catalog_set $type $name $desc
853 # Store a description (desc) in-association with device $type and $name.
854 # Returns success unless $name is NULL or missing. Use f_device_catalog_get()
855 # routine with the same $name and optionally $type to retrieve catalog device
856 # structure (see CATALOG_DEVICE struct definition in GLOBALS section).
858 f_device_catalog_set()
860 local type="$1" name="$2" desc="$3"
861 local struct dev dev_type found=
863 [ "$name" ] || return $FAILURE
865 # Disable debugging to keep debug output light
868 f_str2varname "$name" struct
869 if [ ! "$DEVICE_CATALOG_APPEND_ONLY" ]; then
870 for dev in $DEVICE_CATALOG; do
871 [ "$dev" = "$struct" ] || continue
875 if [ "$found" ]; then
876 f_struct_free "catalog_device_$struct"
878 DEVICE_CATALOG="$DEVICE_CATALOG $struct"
880 f_struct_new CATALOG_DEVICE "catalog_device_$struct" || return $FAILURE
881 catalog_device_$struct set type "$type"
882 catalog_device_$struct set name "$name"
883 catalog_device_$struct set desc "$desc"
887 # f_device_desc $device_name $device_type [$var_to_set]
889 # Print a description for a device name (eg., `fxp0') given a specific device
892 # If $var_to_set is missing or NULL, the device description is printed to
893 # standard out for capturing in a sub-shell (which is less-recommended because
894 # of performance degredation; for example, when called in a loop).
898 local __name="$1" __type="$2" __var_to_set="$3"
899 local __devname __devunit __cp
902 [ "$__name" ] || return $SUCCESS
903 [ "$__type" = "$DEVICE_TYPE_ANY" ] && type=
904 [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; }
907 # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, otherwise fall
908 # through to further alternate methods.
910 if f_have sysctl; then
911 __devname="${__name%%[0-9]*}"
912 __devunit="${__name#$__devname}"
913 __devunit="${__devunit%%[!0-9]*}"
914 if [ "$__var_to_set" ]; then
916 sysctl -n "dev.$__devname.$__devunit.%desc" \
919 setvar "$__var_to_set" "$__cp" &&
923 sysctl -n "dev.$__devname.$__devunit.%desc" \
924 2> /dev/null && return $SUCCESS
928 # Look up device in catalog for default description
929 local __catalog_struct
930 debug= f_device_catalog_get "$__type" "$__name" __catalog_struct
931 debug= f_struct "catalog_device_$__catalog_struct" get \
932 desc "$__var_to_set" && return $SUCCESS
935 # Sensible fall-backs for specific types
938 $DEVICE_TYPE_CDROM) __cp="<unknown cdrom device type>" ;;
939 $DEVICE_TYPE_DISK) __cp="<unknown disk device type>" ;;
940 $DEVICE_TYPE_FLOPPY) __cp="<unknown floppy device type>" ;;
941 $DEVICE_TYPE_USB) __cp="<unknown USB storage device type>" ;;
942 $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>" ;;
944 __cp="<unknown device type>"
947 if [ "$__var_to_set" ]; then
948 setvar "$__var_to_set" "$__cp"
956 # f_device_is_ethernet $device
958 # Returns true if $device is a wired Ethernet network interface. Otherwise
959 # returns false. Example wired interfaces include: fxp0 em0 bge0 rl0 etc.
961 f_device_is_ethernet()
963 local dev="$1" type flags
965 # Make sure we have an actual device by that name
966 f_struct "$dev" || return $FAILURE
968 # Make sure that the device is a network device
970 [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
972 # Make sure that the media flags indicate that it is Ethernet
974 [ $(( ${flags:-0} & $IF_ETHERNET )) -eq $IF_ETHERNET ]
977 # f_device_is_wireless $device
979 # Returns true if $device is a Wireless network interface. Otherwise returns
980 # false. Examples of wireless interfaces include: iwn0
982 f_device_is_wireless()
984 local dev="$1" type flags
986 # Make sure we have an actual device by that name
987 f_struct "$dev" || return $FAILURE
989 # Make sure that the device is a network device
991 [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
993 # Make sure that the media flags indicate that it is 802.11 wireless
995 [ $(( ${flags:-0} & $IF_WIRELESS )) -eq $IF_WIRELESS ]
998 # f_device_is_active $device
1000 # Returns true if $device is active. Otherwise returns false. Currently this
1001 # only works for network interfaces.
1003 f_device_is_active()
1005 local dev="$1" type flags=0
1007 # Make sure we have an actual device by that name
1008 f_struct "$dev" || return $FAILURE
1012 $DEVICE_TYPE_NETWORK)
1013 # Make sure that the media flags indicate that it is active
1014 $dev get flags flags
1015 [ $(( ${flags:-0} & $IF_ACTIVE )) -eq $IF_ACTIVE ]
1022 # f_device_find [-1] $name [$type [$var_to_set]]
1024 # Find one or more registered devices by name, type, or both. Returns a space-
1025 # separated list of devices matching the search criterion.
1027 # If `-1' option flag is given, only the first matching device is returned.
1029 # If $var_to_set is missing or NULL, the device name(s) are printed to standard
1030 # out for capturing in a sub-shell (which is less-recommended because of
1031 # performance degredation; for example, when called in a loop).
1035 local OPTIND OPTARG flag only_one=
1036 while getopts 1 flag; do
1041 shift $(( $OPTIND - 1 ))
1043 local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
1044 local __n=1 __devname __devtype __found=
1045 while [ $__n -le $NDEVICES ]; do
1046 device_$__n get name __devname
1047 device_$__n get type __devtype
1048 if [ "$__name" = "$__devname" -o ! "$__name" ] &&
1049 [ "$__type" = "$DEVICE_TYPE_ANY" -o \
1050 "$__type" = "$__devtype" ]
1052 __found="$__found device_$__n"
1053 [ "$only_one" ] && break
1058 if [ "$__var_to_set" ]; then
1059 setvar "$__var_to_set" "${__found# }"
1063 [ "$__found" ] # Return status
1066 # f_device_init $device
1068 # Initialize a device by evaluating its `init' function. The $device argument
1069 # is a DEVICE struct name.
1073 local device="$1" init_func
1074 f_struct "$device" || return $?
1075 $device get init init_func
1076 ${init_func:-:} "$device"
1079 # f_device_get $device $file [$probe]
1081 # Read $file by evaluating the device's `get' function. The file is commonly
1082 # produced on standard output (but it truly depends on the function called).
1083 # The $device argument is a DEVICE struct name.
1087 local device="$1" file="$2" probe="$3" get_func
1088 f_struct "$device" || return $?
1089 $device get get get_func
1090 ${get_func:-:} "$device" "$file" ${3+"$probe"}
1093 # f_device_shutdown $device
1095 # Shutdown a device by evaluating its `shutdown' function. The $device argument
1096 # is a DEVICE struct name.
1100 local device="$1" shutdown_func
1101 f_struct "$device" || return $?
1102 $device get shutdown shutdown_func
1103 ${shutdown_func:-:} "$device"
1106 # f_devices_sort_by $property $var_to_get [$var_to_set]
1108 # Take list of devices from $var_to_get (separated by whitespace, newline
1109 # included) and sort them by $property (e.g., `name'). The sorted list of
1110 # DEVICE struct names is returned on standard output separated by whitespace
1111 # (newline to be specific) unless $var_to_set is present and non-NULL.
1113 # This function is a two-parter. Below is the awk(1) portion of the function,
1114 # afterward is the sh(1) function which utilizes the below awk script.
1116 f_device_sort_by_awk='
1117 # Variables that should be defined on the invocation line:
1118 # -v prop="property"
1119 function _asorti(src, dest)
1122 for (i in src) dest[++nitems] = i
1123 for (i = 1; i <= nitems; k = i++) {
1125 while ((k > 0) && (dest[k] > idx)) {
1126 dest[k+1] = dest[k]; k--
1135 name = ENVIRON["_struct_value_" devs[d] "_" prop]
1136 devices[name] = devs[d]
1140 nitems = _asorti(devices, devices_sorted)
1141 for (i = 1; i <= nitems; i++) print devices[devices_sorted[i]]
1146 local __property="${1:-name}" __var_to_get="$2" __var_to_set="$3"
1148 f_isset "$__var_to_get" || return $FAILURE
1151 for __dev in $( f_getvar "$__var_to_get" ); do
1152 export _struct_value_${__dev}_$__property
1156 setvar "${__var_to_set:-__cp}" "$(
1157 f_getvar "$__var_to_get" |
1158 awk -v prop="$__property" "$f_device_sort_by_awk"
1160 [ "$__var_to_set" ] || echo "$__cp"
1163 # f_device_menu $title $prompt $hline $device_type [$helpfile]
1165 # Display a menu listing all the devices of a certain type in the system.
1170 local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
1171 f_dialog_title_restore
1173 local prompt="$2" hline="$3" type="$4" helpfile="$5"
1176 f_device_find "" "$type" devs || return $DIALOG_CANCEL
1178 local name desc menu_list=
1179 f_device_sort_by name devs devs
1180 for dev in $devs; do
1183 f_shell_escape "$name" name
1184 f_shell_escape "$desc" desc
1185 menu_list="$menu_list
1186 '$name' '$desc'" # END-QUOTE
1188 menu_list="${menu_list#$NL}"
1190 local height width rows
1191 eval f_dialog_menu_size height width rows \
1199 case $- in *e*) errexit=1; esac
1204 mtag=$( eval $DIALOG \
1205 --title \"\$title\" \
1206 --backtitle \"\$btitle\" \
1207 --hline \"\$hline\" \
1208 --ok-label \"\$msg_ok\" \
1209 --cancel-label \"\$msg_cancel\" \
1212 --help-label \"\$msg_help\" \
1213 ${USE_XDIALOG:+--help \"\"} \
1215 --menu \"\$prompt\" \
1216 $height $width $rows \
1218 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
1222 [ $retval -ne $DIALOG_HELP ] && break
1223 # Otherwise, the Help button was pressed
1224 f_show_help "$helpfile"
1225 # ...then loop back to menu
1227 f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
1229 [ "$errexit" ] && set -e
1231 if [ $retval -eq $DIALOG_OK ]; then
1232 # Clean up the output of [X]dialog(1)
1233 f_dialog_data_sanitize mtag
1235 # Map the user's choice back to a struct name
1237 index=$( eval f_dialog_menutag2index \"\$mtag\" $menu_list )
1238 device=$( set -- $devs; eval echo \${$index} )
1249 f_cdrom() { f_device_catalog_set $DEVICE_TYPE_CDROM "$1" "$2"; }
1250 f_disk() { f_device_catalog_set $DEVICE_TYPE_DISK "$1" "$2"; }
1251 f_floppy() { f_device_catalog_set $DEVICE_TYPE_FLOPPY "$1" "$2"; }
1252 f_usb() { f_device_catalog_set $DEVICE_TYPE_USB "$1" "$2"; }
1253 f_network() { f_device_catalog_set $DEVICE_TYPE_NETWORK "$1" "$2"; }
1255 ############################################################ MAIN
1258 # The below classifications allow us to re-group the GEOM devices from the
1259 # `DEV' GEOM class appropriately while providing fall-back descriptions both
1260 # for making the below code more maintainable and handling the rare case the
1261 # GEOM device lacks a description.
1264 DEVICE_CATALOG_APPEND_ONLY=1 # Make initial loading faster
1266 # CDROM, Disk, Floppy, and USB devices/names
1267 f_cdrom "cd%d" "SCSI CDROM drive"
1268 f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive"
1269 f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type"
1270 f_disk "aacd%d" "Adaptec FSA RAID array"
1271 f_disk "ada%d" "ATA/SATA disk device"
1272 f_disk "amrd%d" "AMI MegaRAID drive"
1273 f_disk "da%d" "SCSI disk device"
1274 f_disk "idad%d" "Compaq RAID array"
1275 f_disk "ipsd%d" "IBM ServeRAID RAID array"
1276 f_disk "md%d" "md(4) disk device"
1277 f_disk "mfid%d" "LSI MegaRAID SAS array"
1278 f_disk "mlxd%d" "Mylex RAID disk"
1279 f_disk "twed%d" "3ware ATA RAID array"
1280 f_disk "vtbd%d" "VirtIO Block Device"
1281 f_floppy "fd%d" "Floppy Drive unit A"
1282 f_usb "da%da" "USB Mass Storage Device"
1284 # Network interfaces/names
1285 f_network "ae%d" "Attansic/Atheros L2 Fast Ethernet"
1286 f_network "age%d" "Attansic/Atheros L1 Gigabit Ethernet"
1287 f_network "alc%d" "Atheros AR8131/AR8132 PCIe Ethernet"
1288 f_network "ale%d" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
1289 f_network "an%d" "Aironet 4500/4800 802.11 wireless adapter"
1290 f_network "ath%d" "Atheros IEEE 802.11 wireless adapter"
1291 f_network "aue%d" "ADMtek USB Ethernet adapter"
1292 f_network "axe%d" "ASIX Electronics USB Ethernet adapter"
1293 f_network "bce%d" "Broadcom NetXtreme II Gigabit Ethernet card"
1294 f_network "bfe%d" "Broadcom BCM440x PCI Ethernet card"
1295 f_network "bge%d" "Broadcom BCM570x PCI Gigabit Ethernet card"
1296 f_network "bm%d" "Apple BMAC Built-in Ethernet"
1297 f_network "bwn%d" "Broadcom BCM43xx IEEE 802.11 wireless adapter"
1298 f_network "cas%d" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
1299 f_network "cc3i%d" "SDL HSSI sync serial PCI card"
1300 f_network "cue%d" "CATC USB Ethernet adapter"
1301 f_network "cxgb%d" "Chelsio T3 10Gb Ethernet card"
1302 f_network "dc%d" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
1303 f_network "de%d" "DEC DE435 PCI NIC or other DC21040-AA based card"
1304 f_network "disc%d" "Software discard network interface"
1305 f_network "ed%d" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
1306 f_network "el%d" "3Com 3C501 Ethernet card"
1307 f_network "em%d" "Intel(R) PRO/1000 Ethernet card"
1308 f_network "en%d" "Efficient Networks ATM PCI card"
1309 f_network "ep%d" "3Com 3C509 Ethernet card/3C589 PCMCIA"
1310 f_network "et%d" "Agere ET1310 based PCI Express Gigabit Ethernet card"
1311 f_network "ex%d" "Intel EtherExpress Pro/10 Ethernet card"
1312 f_network "fe%d" "Fujitsu MB86960A/MB86965A Ethernet card"
1313 f_network "fpa%d" "DEC DEFPA PCI FDDI card"
1314 f_network "fwe%d" "FireWire Ethernet emulation"
1315 f_network "fwip%d" "IP over FireWire"
1316 f_network "fxp%d" "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
1317 f_network "gem%d" "Apple GMAC or Sun ERI/GEM Ethernet adapter"
1318 f_network "hme%d" "Sun HME (Happy Meal Ethernet) Ethernet adapter"
1319 f_network "ie%d" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
1320 f_network "igb%d" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
1321 f_network "ipw%d" "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
1322 f_network "iwi%d" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
1323 f_network "iwn%d" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
1324 f_network "ix%d" "Intel Etherexpress Ethernet card"
1325 f_network "ixgb%d" "Intel(R) PRO/10Gb Ethernet card"
1326 f_network "ixgbe%d" "Intel(R) PRO/10Gb Ethernet card"
1327 f_network "jme%d" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
1328 f_network "kue%d" "Kawasaki LSI USB Ethernet adapter"
1329 f_network "le%d" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
1330 f_network "lge%d" "Level 1 LXT1001 Gigabit Ethernet card"
1331 f_network "lnc%d" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
1332 f_network "lo%d" "Loop-back (local) network interface"
1333 f_network "lp%d" "Parallel Port IP (PLIP) peer connection"
1334 f_network "malo%d" "Marvell Libertas 88W8335 802.11 wireless adapter"
1335 f_network "msk%d" "Marvell/SysKonnect Yukon II Gigabit Ethernet"
1336 f_network "mxge%d" "Myricom Myri10GE 10Gb Ethernet card"
1337 f_network "nfe%d" "NVIDIA nForce MCP Ethernet"
1338 f_network "ng%d" "Vimage netgraph(4) bridged Ethernet device"
1339 f_network "nge%d" "NatSemi PCI Gigabit Ethernet card"
1340 f_network "nve%d" "NVIDIA nForce MCP Ethernet"
1341 f_network "nxge%d" "Neterion Xframe 10GbE Server/Storage adapter"
1342 f_network "pcn%d" "AMD Am79c79x PCI Ethernet card"
1343 f_network "plip%d" "Parallel Port IP (PLIP) peer connection"
1344 f_network "ral%d" "Ralink Technology IEEE 802.11 wireless adapter"
1345 f_network "ray%d" "Raytheon Raylink 802.11 wireless adapter"
1346 f_network "re%d" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
1347 f_network "rl%d" "RealTek 8129/8139 PCI Ethernet card"
1348 f_network "rue%d" "RealTek USB Ethernet card"
1349 f_network "rum%d" "Ralink Technology USB IEEE 802.11 wireless adapter"
1350 f_network "sf%d" "Adaptec AIC-6915 PCI Ethernet card"
1351 f_network "sge%d" "Silicon Integrated Systems SiS190/191 Ethernet"
1352 f_network "sis%d" "SiS 900/SiS 7016 PCI Ethernet card"
1353 f_network "sk%d" "SysKonnect PCI Gigabit Ethernet card"
1354 f_network "sn%d" "SMC/Megahertz Ethernet card"
1355 f_network "snc%d" "SONIC Ethernet card"
1356 f_network "sr%d" "SDL T1/E1 sync serial PCI card"
1357 f_network "ste%d" "Sundance ST201 PCI Ethernet card"
1358 f_network "stge%d" "Sundance/Tamarack TC9021 Gigabit Ethernet"
1359 f_network "ti%d" "Alteon Networks PCI Gigabit Ethernet card"
1360 f_network "tl%d" "Texas Instruments ThunderLAN PCI Ethernet card"
1361 f_network "tx%d" "SMC 9432TX Ethernet card"
1362 f_network "txp%d" "3Com 3cR990 Ethernet card"
1363 f_network "uath%d" "Atheros AR5005UG and AR5005UX USB wireless adapter"
1364 f_network "upgt%d" "Conexant/Intersil PrismGT USB wireless adapter"
1365 f_network "ural%d" "Ralink Technology RT2500USB 802.11 wireless adapter"
1366 f_network "urtw%d" "Realtek 8187L USB wireless adapter"
1367 f_network "vge%d" "VIA VT612x PCI Gigabit Ethernet card"
1368 f_network "vlan%d" "IEEE 802.1Q VLAN network interface"
1369 f_network "vr%d" "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
1370 f_network "vx%d" "3COM 3c590 / 3c595 Ethernet card"
1371 f_network "wb%d" "Winbond W89C840F PCI Ethernet card"
1372 f_network "wi%d" "Lucent WaveLAN/IEEE 802.11 wireless adapter"
1373 f_network "wpi%d" "Intel 3945ABG IEEE 802.11 wireless adapter"
1374 f_network "wx%d" "Intel Gigabit Ethernet (82452) card"
1375 f_network "xe%d" "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
1376 f_network "xl%d" "3COM 3c90x / 3c90xB PCI Ethernet card"
1377 f_network "zyd%d" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
1379 DEVICE_CATALOG_APPEND_ONLY= # Additional loading modifies existing devices
1381 f_count NCATALOG_DEVICES $DEVICE_CATALOG
1382 f_dprintf "%s: Initialized device catalog with %u names/descriptions." \
1383 device.subr $NCATALOG_DEVICES
1386 # Scan for the above devices unless requeted otherwise
1388 f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL"
1389 case "$DEVICE_SELF_SCAN_ALL" in
1390 ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
1394 f_dprintf "%s: Successfully loaded." device.subr
1396 fi # ! $_DEVICE_SUBR