aboutsummaryrefslogtreecommitdiffstats
path: root/main/openrc/modloop.initd
blob: e26bdcbb49130dfe979fe16256a54a25bc4b99ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/sbin/runscript

# script that will mount image with modules

depend() {
	need dev
	before checkfs fsck hwdrivers modules hwclock
	keyword novserver
}

# read kernel options
init_KOPT() {
	eval set -- $(cat /proc/cmdline 2>/dev/null)
	# in case syslinux does not set BOOT_IMAGE
	KOPT_BOOT_IMAGE="${1}"
	for opt; do
	        case "$opt" in
			alpine_dev=*|modloop=*|BOOT_IMAGE=*)
				eval "KOPT_${opt%%=*}='${opt#*=}'" ;;
        	esac
	done
}

resolve_dev() {
	case "$1" in
	UUID=*|LABEL=*) findfs "$1";;
	*) readlink -f "$1";;
	esac
}

find_mnt() {
	local search_dev="$1" fstab="$2"
	local dev mnt fs mntopts chk
	case "$search_dev" in
		UUID=*|LABEL=*|/dev/*);;
		*) search_dev=/dev/$search_dev;;
	esac
	local search_real_dev=$(resolve_dev $search_dev)
	while read dev mnt fs mntopts chk; do
		local real_dev=$(resolve_dev $dev)
		local i j
		for i in "$search_dev" "$search_real_dev"; do
			[ -z "$i" ] && continue
			for j in "$dev" "$real_dev"; do
				[ -z "$j" ] && continue
				if [ "$i" = "$j" ]; then
					echo "$mnt"
					return
				fi
			done
		done
	done < $fstab 2>/dev/null
}

# initialies: alpine_dev, alpine_mnt, alpine_fs, alpine_mounted
find_media() {
	init_KOPT
	[ -z "$KOPT_alpine_dev" ] && return 0
	alpine_mounted=
	alpine_dev=${KOPT_alpine_dev%%:*}
	alpine_fs=${KOPT_alpine_dev#*:}
	[ "$alpine_fs" = "$KOPT_alpine_dev" ] && unset alpine_fs
	# first we check if alpine_dev is mounted and use this
	alpine_mnt=$(find_mnt $alpine_dev /proc/mounts)
	if [ -z "$alpine_mnt" ]; then
		# then we check fstab
		alpine_mnt=$(find_mnt /dev/$alpine_dev /etc/fstab)
	else
		alpine_mounted=yes
	fi
	# finally we fallback to /media/<devicename>
	[ -z "$alpine_mnt" ] && alpine_mnt=/media/$alpine_dev
}

start() {
	local modloop= mount_opts= modloop_dldir="/lib"

	find_media

	case "$KOPT_modloop" in
		http://*|https://|ftp://*)
			wget -P "$modloop_dldir" "$KOPT_modloop" \
				&& modloop=$modloop_dldir/${KOPT_modloop##/*}
			;;
		*)
			if [ -z "$alpine_dev" ]; then
				return 0
			fi
			if [ -z "$alpine_mounted" ]; then
				ebegin "Mounting $alpine_mnt"
				[ -n "$alpine_fs" ] && mount_opts="-t $alpine_fs"
				mount $mount_opts /dev/$alpine_dev $alpine_mnt 2>/dev/null
				eend $? || return 1
			fi
			for modloop in ${alpine_mnt}$KOPT_modloop \
				${alpine_mnt}$KOPT_BOOT_IMAGE.modloop.*; do

				[ -f "$modloop" -o -n "$KOPT_modloop" ] && break
			done
			;;
	esac

	ebegin "Mounting modloop $modloop"
	mkdir -p /.modloop /lib
	mount -o loop,ro $fs_opt $modloop /.modloop
	eend $? || return 1

	#use unionfs is available and configured
	if grep -q -w "unionfs$" /proc/filesystems && [ -n "$unionfs_size" ]; then
		ebegin "UnionFS detected. Mounting modloop rw"
		mkdir -p /.modunisonfs/modules /lib/modules
		mount -t tmpfs -o size="$unionfs_size" tmpfs /.modunisonfs/modules
		mount -t unionfs -o dirs=/.modunisonfs/modules=rw:/.modloop/modules=ro unionfs /lib/modules
		eend $? || return 1
	else
		rm -rf /lib/modules && ln -sf /.modloop/modules /lib/
	fi

	# copy firmware if there are any
	if [ -d $alpine_mnt/firmware ]; then
	        ebegin "Copying firmware from $alpine_mnt/firmware"
	        cp -R -a $alpine_mnt/firmware /lib/
	        eend $?
	elif  [ -d /lib/modules/firmware ]; then
		rmdir /lib/firmware 2>/dev/null \
			&& ln -s /lib/modules/firmware /lib/
	fi
	return 0
}

stop() {
	local rc=0
	find_media
	[ -z "$alpine_dev" ] && return 0
	if mountinfo --quiet /.modloop; then
		ebegin "Unmounting /.modloop"
		umount -d /.modloop
		eend $? || return 1
	fi
	if mountinfo --quiet $alpine_mnt; then
		ebegin "Unmounting $alpine_mnt"
		umount $alpine_mnt
		eend $?
	fi
}