aboutsummaryrefslogtreecommitdiffstats
path: root/packages/altboot/files/altboot.func
blob: 1c21a5f2f86f016c1cf701ed1d6519fb78b9dacc (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#! /bin/sh
# This function checks for the presence of a real filesystem and loop-images on the target
# $1 = folder of rootfs, $2 = runlevel (defaults to 5)
check_target() {
	# Check if there is a /sbin/init or /sbin/init.sysvinit on the card
	if test -x $1/sbin/init -o -x $1/$REAL_INIT
	then
		real_fs_found=1
	else
		echo -e "Note: No INIT [$REAL_INIT] found on target"
	fi
	
	# Check for loop-images
	if (ls $1/$IMAGE_PATH/*rootfs.bin) >/dev/null 2>&1
	then
		image_found=1
	else
		echo "Note: No boot-images found in [$1/$IMAGE_PATH]"
	fi
	
	# Check if we have both, a real fs and boot-images. If so, ask the user what to boot
	if test "$real_fs_found" = 1 -a "$image_found" = 1
	then
		echo -e "\nI have found a real filesystem and boot-images on the target"
		echo -e "What do you want to boot?\n"
		
		echo -e "\t[1] The real filesystem"
		echo -e "\t[2] A loop-image"
		echo ""
		
		while test -z "$ans"
		do
			echo -n "Your choice: "
			read junk < /dev/tty1
			
			if test "$junk" = 1 -o "$junk" = 2
			then
				ans="$junk"
			fi
		done
		
		case "$ans" in
		1)	pivot_realfs "$1" "$2">/dev/tty0;;
		2)	pivot_image "$1" "$2">/dev/tty0;;
		esac
				
		exit 0
	fi

	# Boot a real filesystem	
	test "$real_fs_found" = 1 && pivot_realfs "$1" >/dev/tty0
	
	# Boot a loop-image
	test "$image_found" = 1 && pivot_image "$1" >/dev/tty0
		
	if test "$real_fs_found" != 1 -a "$image_found" != 1
	then
		die "Nothing to do!"
	fi
}

# This function pivot_root's into a real filesystem calling $newrootfs/sbin/init
# $1 = The new rootfs
pivot_realfs() {
	test -z "$2" && RL="5" || RL="$2"
	mkdir -p $1/media/ROM || die "mkdir -p $1/media/ROM failed"

	mount -o remount,ro /

	echo -n "Pivoting root..."
	if (/sbin/pivot_root $1 $1/media/ROM) 
	then
		echo "Success"

		# Interestingly, this doesn't work with the "real" mount
		# Without this command, /dev would be mounted under /media/ROM/dev after pivoting root
		/bin/busybox mount -o move /media/ROM/dev /dev

		cd /

		# Boot /sbin/init if it is available or use /sbin/init.sysvinit instead
		if test -x $/sbin/init
		then
			echo "Calling INIT [/sbin/init $RL]"
			exec /usr/sbin/chroot . /sbin/init $RL >/dev/tty0 2>&1			
		else
			echo "Calling INIT [$REAL_INIT $RL]"			
			exec /usr/sbin/chroot . $REAL_INIT $RL >/dev/tty0 2>&1			
		fi
	else
		echo "FAILED"
		die "* * * pivot_root failed! * * *" 
	fi
}

# This function loop-mounts an image-file and pivot_root's into it
# $1: The new rootfs
pivot_image() {
	test -z "$2" && RL="5" || RL="$2"
	cd $1/$IMAGE_PATH

	# Check for rootfs images on the card
	if test "`ls *rootfs.bin | wc -l | tr -d " "`" -gt 1
	then
		echo -e "\n\nPlease select a rootfs:\n"

		# Show all available images
		x=0
		for file in `ls *rootfs.bin`
		do
			let x=$x+1
			echo -e "\t\t[$x] $file"
		done

		echo ""			

		IMAGE_NAME=""
		while test -z "$IMAGE_NAME"
		do
			echo -en "Please choose one of the above: "
			read junk < /dev/tty1

			x=0
			for file in `ls *rootfs.bin`
			do
				let x=$x+1
				if test "$x" = "$junk"
				then
					IMAGE_NAME="$file"						
				fi
			done	
		done
	else
		IMAGE_NAME="`ls *rootfs.bin`"		
		test -z "$IMAGE_NAME" && die "No rootfs found (*rootfs.bin) in $1/$IMAGE_PATH"
	fi

	echo "Using [$IMAGE_NAME]"

	mkdir -p /media/image || die "mkdir -p /media/image failed"

	echo "Setting up loopback (/dev/loop0) for $IMAGE_NAME"
	losetup /dev/loop0 $1/$IMAGE_PATH/$IMAGE_NAME || die "losetup /dev/loop0 $1/$IMAGE_PATH/$IMAGE_NAME failed!"
	check_fs /dev/loop0 $IMAGE_TYPE

	echo -e "\n* * * Booting rootfs image * * *\n"


	# Busybox's "mount" doesn't seem to like "-o loop" for some reason
	# It works on collie and b0rks on poodle.
	if [ "$IMAGE_TYPE" = "" ]; then
		IMAGE_TYPE="auto"
	fi
	# If mount fails it has the tendency to spew out a _lot_ of error messages.
	# We direct the output to /dev/null so the user can see which step actually failed.
	mount -t $IMAGE_TYPE /dev/loop0 /media/image >/dev/null 2>&1 || die "mount -t $IMAGE_TYPE  /dev/loop0 /media/image failed!"

	mkdir -p /media/image/media/ROM || die "mkdir -p /media/image/media/ROM failed"

	echo -n "Pivoting root..."
	if (/sbin/pivot_root /media/image /media/image/media/ROM) 
	then
		echo "Success"

		# This is important since we are still cd'ed into the old root
		cd /
		
		! test -d "$1" && mkdir -p "$1"
		
		# Move mountpoints from the old rootfs into the new one.
		# The *real* mount is kinda touchy feely about that
		/bin/busybox mount -o move /media/ROM$1 $1
		/bin/busybox mount -o move /media/ROM/dev /dev
		/bin/busybox mount -o move /media/ROM/proc /proc >/dev/null 2>&1

		echo "Calling INIT"
		exec /usr/sbin/chroot . /sbin/init $RL >/dev/tty0 2>&1
	else
		echo "FAILED"
		die "* * * pivot_root failed! * * *" 
	fi


}

# This functions configures the master password for altboot if none is set
set_password() {
	mount -o remount,rw /
	if test -z "$MASTER_PASSWORD"
	then
		echo -e "\nAltboot is a boot-manager which allows to boot from SD,\nCF and NFS"
		echo -e "\nFor security reasons altboot requires a password\nto boot into init=/bin/sh."
		echo -e "${C_RED}This is *not* your root password!\nIt is used by altboot alone!${C_RESET}\n"
		#echo -e "${C_BLUE}\nNote:\tThe password will be echoed to the screen\n\tand it will be asked twice for confirmation.${C_RESET}"
		#echo -e "\nPlease enter a new master password:\n"

		while true
		do
			echo -en "\nNew password: "

			stty -echo
			read junk1 < /dev/tty0
			stty echo

			if ! test -z "$junk1"
			then
				echo -en "\nRepeat: "
				
				stty -echo
				read junk2  < /dev/tty0
				stty echo
				echo ""
				
				if test "$junk1" = "$junk2"
				then
					crypt_pw="`echo "$junk1" | md5sum | awk '{print $1}'`"
					
					if test -e /etc/altboot.cfg
					then
						sed "/^MASTER_PASSWORD/s/\(.*\=\).*/\1\"$crypt_pw\"/" /etc/altboot.cfg > /etc/altboot.cfg_
						mv /etc/altboot.cfg_ /etc/altboot.cfg
						MASTER_PASSWORD="$crypt_pw"
						echo "Password changed."
					else
						echo "/etc/altboot.cfg is missing, no password saved"
					fi
					
					break
				else
					echo -e "Passwords didn't match, try again\n"
				fi
			fi	
		done
	fi
	
}

# This function asks for altboots master password. It only returns if the correct password was supplied
verify_master_pw() {
	if ! test -z "$MASTER_PASSWORD"
	then
		auth_timeout="3"

		echo "Please enter your altboot master password"

		cnt=0
		while true
		do
			let cnt=$cnt+$auth_timeout
			echo -n "Password: "
			read junk < /dev/tty0

			if test "`echo "$junk" | md5sum | awk '{print $1}'`" = "$MASTER_PASSWORD"
			then
				break
			else
				echo "[`echo "$junk" | md5sum | awk '{print $1}'`]"
				echo "[$MASTER_PASSWORD]"
				echo "Wrong password, sleeping $cnt seconds..."
				sleep $cnt

#				if test "$cnt" -gt 10
#				then
#					break
#				fi
			fi
		done
	fi
}


check_fs() {
	if [ "$FSCK_IMAGES" = "yes" ]
	then
                FSCK=""
		if [ "$2" = "" ]; then
			FSTYPE="ext2"
		else
			FSTYPE="$2"
		fi
		case "$FSTYPE" in
		ext2 | ext3)
	        	if [ -e /sbin/fsck.ext3 ]; then
		       		FSCK="/sbin/fsck.ext3"
			elif [ -e /sbin/e3fsck ]; then
		       		FSCK="/sbin/e3fsck"
			elif [ -e /sbin/fsck.ext2 ]; then
		       		FSCK="/sbin/fsck.ext2"
			elif [ -e /sbin/e2fsck ]; then
		       		FSCK="/sbin/e2fsck"
			fi
			FSCK="$FSCK -p"
		;;
		vfat)
		    if [ -e /sbin/dosfsck ]; then
			FSCK="/sbin/dosfsck -a"
		    fi
		;;
		esac
		if [ "$FSCK" = "" ]; then
		        echo "Could not find fsck for $FSTYPE!"
		else
			echo "Checking file system on $1"
			$FSCK $1 || sleep 2
		fi
	fi
}