1#!/bin/sh
2#
3#
4
5# PROVIDE: cfumass
6# REQUIRE: var
7# KEYWORD: nojail
8
9. /etc/rc.subr
10
11name="cfumass"
12desc="Configure the LUN for device mode USB mass storage"
13rcvar="cfumass_enable"
14
15start_cmd="${name}_start"
16stop_cmd="${name}_stop"
17
18extra_commands="reload"
19reload_cmd="${name}_start"
20
21: ${cfumass_dir:=/var/cfumass}
22: ${cfumass_image:=/var/tmp/cfumass.img}
23: ${cfumass_vendor:="FreeBSD"}
24: ${cfumass_product:="cfumass(4)"}
25
26remove_luns()
27{
28	local _lun _luns
29
30	_luns=`ctladm devlist -b block -v | awk '
31
32	$1 ~ /^[0-9]+$/ {
33		lun = $1
34	}
35
36	$1 == "file='"${cfumass_image}"'" {
37		print lun
38	}'`
39
40	for _lun in ${_luns}; do
41		ctladm remove -b block -l "${_lun}" > /dev/null
42	done
43}
44
45cfumass_start()
46{
47	local err _files _template _new_template
48
49	if [ ! -d "${cfumass_dir}" ]; then
50		warn "${cfumass_dir} does not exist"
51		return 1
52	fi
53
54	_files=`find "${cfumass_dir}" -newer "${cfumass_image}" -print 2> /dev/null`
55	if [ ! -e "${cfumass_image}" -o -n "${_files}" ]; then
56		# The image doesn't exist or is out of date.
57		makefs -t cd9660 -o label="${cfumass_vendor}" \
58		    -o rockridge "${cfumass_image}" "${cfumass_dir}"
59		err=$?
60		if [ "${err}" -ne 0 ]; then
61			warn "unable to create ${cfumass_image}"
62			return "${err}"
63		fi
64	fi
65
66	remove_luns
67
68	ctladm create -b block -o file="${cfumass_image}" -o readonly=on \
69	    -o vendor="${cfumass_vendor}" -o product="${cfumass_product}" \
70	    -S 0 > /dev/null
71	err=$?
72	if [ "${err}" -ne 0 ]; then
73		warn "unable to create CTL LUN"
74		return "${err}"
75	fi
76
77	load_kld -e cfumass cfumass
78
79	# If the template is already switched to Mass Storage, then reset
80	# it to -1 to force the host to reenumerate it; otherwise it might
81	# not notice the new LUN.
82	_template=`sysctl -n hw.usb.template`
83	if [ "${_template}" -eq 0 ]; then
84		sysctl hw.usb.template=-1 > /dev/null
85		err=$?
86		if [ "${err}" -ne 0 ]; then
87			warn "unable to set hw.usb.template sysctl"
88			return "${err}"
89		fi
90	fi
91
92	# Set the template number based on the current one.
93	_template=`sysctl -n hw.usb.template`
94	case "${_template}" in
95	-1)
96		_new_template="0"
97		;;
98	8)
99		_new_template="10"
100		;;
101	*)
102		warn "hw.usb.template sysctl set to neither -1 nor 8; not changing"
103		_new_template=""
104		;;
105	esac
106		
107	if [ -n "${_new_template}" ]; then
108		sysctl hw.usb.template="${_new_template}" > /dev/null
109		err=$?
110		if [ "${err}" -ne 0 ]; then
111			warn "unable to set hw.usb.template sysctl to ${_new_template}"
112			return "${err}"
113		fi
114	fi
115}
116
117cfumass_stop()
118{
119	local err _template _new_template
120
121	remove_luns
122
123	_template=`sysctl -n hw.usb.template`
124	case "${_template}" in
125	0)
126		_new_template="-1"
127		;;
128	10)
129		_new_template="8"
130		;;
131	*)
132		warn "hw.usb.template sysctl set to neither 0 nor 10; not changing"
133		_new_template=""
134		;;
135	esac
136		
137	if [ -n "${_new_template}" ]; then
138		sysctl hw.usb.template="${_new_template}" > /dev/null
139		err=$?
140		if [ "${err}" -ne 0 ]; then
141			warn "unable to set hw.usb.template sysctl to ${_new_template}"
142			return "${err}"
143		fi
144	fi
145}
146
147load_rc_config $name
148
149# doesn't make sense to run in a svcj: nojail keyword
150cfumass_svcj="NO"
151
152run_rc_command "$1"
153