summaryrefslogtreecommitdiffstats
path: root/package/base-files/files/sbin/firstboot
blob: d5a0981f43011c34d766fd97254cdd23ba58fb76 (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
#!/bin/sh
. /etc/functions.sh

partname="rootfs_data"
mtdpart="$(find_mtd_part $partname)"

rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)

dupe() { # <new_root> <old_root>
	cd $1
	echo -n "creating directories... "
	{
		cd $2 
		find . -xdev -type d
		echo "./dev ./jffs ./mnt ./proc ./tmp"
		# xdev skips mounted directories
		cd $1 
	} | xargs mkdir -p
	echo "done"

	echo -n "setting up symlinks... "
	for file in $(cd $2; find . -xdev -type f;); do
		case "$file" in
		./rom/note) ;; #nothing
		./etc/config*|\
		./usr/lib/opkg/info/*) cp -af $2/$file $file;;
		*) ln -sf /rom/${file#./*} $file;;
		esac
	done
	for file in $(cd $2; find . -xdev -type l;); do
		cp -af $2/${file#./*} $file
	done
	echo "done"
}

pivot() { # <new_root> <old_root>
	mount -o move /proc $1/proc && \
	pivot_root $1 $1$2 && {
		mount -o move $2/dev /dev
		mount -o move $2/tmp /tmp
		mount -o move $2/sys /sys 2>&-
		mount -o move $2/jffs /jffs 2>&-
		return 0
	}
}

fopivot() { # <rw_root> <ro_root> <dupe?>
	root=$1
	{
		if grep -q mini_fo /proc/filesystems; then
			mount -t mini_fo -o base=/,sto=$1 "mini_fo:$1" /mnt 2>&- && root=/mnt
		else
			mount --bind / /mnt
			mount --bind -o union "$1" /mnt && root=/mnt 
		fi
	} || {
		[ "$3" = "1" ] && {
		mount | grep "on $1 type" 2>&- 1>&- || mount -o bind $1 $1
		dupe $1 $rom
		}
	}
	pivot $root $2
}

ramoverlay() {
	mkdir -p /tmp/root
	mount -t tmpfs root /tmp/root
	fopivot /tmp/root /rom 1
}

# invoked as an executable
[ "${0##*/}" = "firstboot" ] && {

	[ -z "$mtdpart" ] && {
		echo "MTD partition not found."
		exit 1
	}

	[ -z "$rom" ] && {
		echo "You do not have a squashfs partition; aborting"
		echo "(firstboot cannot be run on jffs2 based firmwares)"
		exit 1
	}

	[ "$1" = "switch2jffs" ] && {
		if grep -q mini_fo /proc/filesystems; then
			mount "$mtdpart" /rom/jffs -t jffs2 || exit

			# try to avoid fs changing while copying
			mount -o remount,ro none / 2>&-

			# copy ramoverlay to jffs2
			echo -n "copying files ... "
			cp -a /tmp/root/* /rom/jffs 2>&-
			echo "done"

			# switch back to squashfs (temporarily)
			# and park the ramdisk ontop of /tmp/root
			pivot /rom /mnt
			mount -o move /mnt /tmp/root

			# /jffs is the overlay
			# /rom is the readonly
			fopivot /jffs /rom

			# try to get rid of /tmp/root
			# this will almost always fail
			umount /tmp/root 2>&-
		else
			# switch back to squashfs temporarily
			pivot /rom /mnt

			# get rid of the old overlay
			umount -l /mnt

			# another umount to get rid of the bind from /tmp/root
			umount -l /mnt

			# initialize jffs2
			mount "$mtdpart" /jffs -t jffs2 || exit

			# workaround to ensure that union can attach properly
			sync
			ls /jffs >/dev/null

			# switch to the new (empty) jffs2
			fopivot /jffs /rom 1

			# copy ramoverlay to jffs2, must be done after switching
			# to the new rootfs to avoid creating opaque directories
			echo -n "copying files ... "
			cp -a /tmp/root/* / >/dev/null 2>&1
			sync
			echo "done"

			umount -l /jffs
			umount -l /tmp/root
		fi

		exit 0
	}

	# script run manually
	[ \! -z "$jffs" ] && {
		echo "firstboot has already been run"
		echo "jffs2 partition is mounted, only resetting files"
		grep mini_fo /proc/filesystems >&-
		[ $? != 0 ] && {
			dupe $jffs $rom
			exit 0
		} || { 
			rm -rf $jffs/* 2>&-
			mount -o remount $jffs / 2>&-
			exit 0
		}
	}

	mtd erase "$partname"
	mount "$mtdpart" /jffs -t jffs2
	fopivot /jffs /rom 1
}