slitaz-arm view rpi/piboot @ rev 219

dot command may not search current directory first
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Jul 23 13:50:45 2017 +0200 (2017-07-23)
parents 4e7726c49011
children
line source
1 #!/bin/sh
2 #
3 # /sbin/piboot: SliTaz Raspberry Pi bootloader and web boot!
4 #
5 # (C) 2014-2017 SliTaz GNU/Linux - ...
6 #
7 # usage: insert 'rdinit=/sbin/piboot' (if you load an initramfs)
8 # or 'init=/sbin/piboot' in the kernel command line /boot/cmdline.txt
9 #
10 # AUTHORS: Pascal Bellard <pascal.bellard@slitaz.org>
11 #
13 [ -z "$(which dialog)" ] && echo "Please install dialog." && exec /init
15 cmdlinearg()
16 {
17 sed "/$1=/!d;s/.*$1=\([^ ]*\).*/\1/" < /proc/cmdline
18 }
20 cmdvararg()
21 {
22 echo " $CMDLINE" | sed "/ $1=/!d;s/.* $1=\([^ ]*\).*/\1/"
23 }
25 get()
26 {
27 grep -sq ^$1 $2 && sed "/^$1/!d;s/$1[ :=]*//" $2
28 }
30 list_entry()
31 {
32 n=0
33 while true ; do
34 n=$(($n+1))
35 eval KEYWORD="\$KEYWORD_$n"
36 eval ENTRY="\$ENTRY_$n"
37 [ "$KEYWORD" ] || break
38 [ "$KEYWORD" == "$default" ] && ENTRY="$ENTRY (default)"
39 echo -n "$KEYWORD \"$ENTRY\" "
40 done
41 }
43 edit_menu()
44 {
45 while true; do
47 eval KERNEL="\$KERNEL_$1"
48 eval INITRD="\$INITRD_$1"
49 eval CMDLINE="\$CMDLINE_$1"
50 extra="--extra-button --extra-label ${msgsave:-Save}"
51 [ "$READONLY" ] && extra=''
53 exec 3>&1
54 value=$($DIALOG --clear \
55 --title "${edittitle:-Edit menu}" \
56 --ok-label "${msgedit:-Edit}" \
57 --cancel-label "${msgdone:-Done}" \
58 $extra \
59 --menu "$msgmenu" 20 72 14 \
60 Kernel "$KERNEL" \
61 Initramfs "$INITRD" \
62 Cmdline "$CMDLINE" 2>&1 1>&3 )
63 retval=$?
64 exec 3>&-
66 case $retval in
67 1|255) return ;;
68 3) cp $mnt/$KEYWORD/config.txt /tmp/config.txt
69 sed -i '/^kernel\|^initrd/d' /tmp/config.txt
70 echo "kernel=$KERNEL" >> /tmp/config.txt
71 [ "$INITRD" ] && echo "initrd $INITRD" >> /tmp/config.txt
72 mount -o remount,rw $mnt
73 [ "$CMDLINE" ] && echo "$CMDLINE" > $mnt/$KEYWORD/cmdline.txt ||
74 rm -f $mnt/$KEYWORD/cmdline.txt
75 cp /tmp/config.txt $mnt/$KEYWORD/config.txt
76 mount -o remount,ro $mnt ;;
77 esac
79 exec 3>&1
80 case $value in
81 Kernel)
82 data=$($DIALOG --clear --title "${msgselectkernel:-Select the kernel}" \
83 --fselect "$mnt/$KEYWORD/$KERNEL" 10 72 2>&1 1>&3) ;;
84 Initramfs)
85 data=$($DIALOG --clear --title "${msgselectinitrd:-Select the initramfs}" \
86 --fselect "$mnt/$KEYWORD/$INITRD" 10 72 2>&1 1>&3) ;;
87 Cmdline)
88 data=$($DIALOG --clear --title "${msgeditcmdline:-Edit cmdline}" \
89 --inputbox "Cmdline" 20 72 2>&1 "$CMDLINE" 1>&3) ;;
90 esac
91 retval=$?
92 exec 3>&-
94 case $retval in
95 1|255) continue ;;
96 esac
98 case $value in
99 Kernel) [ -f $data ] && eval KERNEL_$1=\$data ;;
100 Initramfs) [ -f $data ] && eval INITRD_$1=\$data ;;
101 Cmdline) eval CMDLINE_$1=\$data ;;
102 esac
103 done
104 }
106 web_boot_entry()
107 {
108 [ "$USING_WEBBOOT" == "1" ] ||
109 echo -n 'WebBoot "boot from Internet"'
110 }
112 web_boot()
113 {
114 USING_WEBBOOT=1
115 [ -s $mnt/network.conf ] && cp $mnt/network.conf /etc
116 /etc/init.d/network.sh start
117 webpath=$(get webpath $mnt/menu.txt)
118 [ "$webpath" ] || webpath=http://mirror.slitaz.org/pxe/arm/boot.php
119 for url in ${webpath//,/ }; do
120 wget -O /root/webboot.sh "$url?mac=$(cat \
121 /sys/class/net/eth0/address /sys/class/net/*/address \
122 | sed q)&amp;serial=$(sed '/Serial/!d;s/.*: //' \
123 /proc/cpuinfo)&amp;cpu=$(sed '/Hardware/!d;s/.*: //' \
124 /proc/cpuinfo)" 2>&1 > /dev/null
125 [ -s /root/webboot.sh ] || continue
126 . /root/webboot.sh
127 webprefix=$(dirname $url)
128 editbutton=""
129 break
130 done
131 }
133 web_get()
134 {
135 if [ -z "$webprefix" ]; then
136 cat $mnt/$1 >> $2
137 return
138 fi
139 case "$1" in
140 *torrent) # See http://sl-lab.it/dokuwiki/doku.php/tesi:boottorrent_en
141 [ -z "$(which aria2)" ] &&
142 echo "Can't find aria2." >> $LOG &&
143 exec /init
145 wget -O /root/webboot.torrent "$webprefix/$1"
146 aria2c --enable-dht=false --disable-ipv6=true --seed-time=0 \
147 --file-allocation=none -j5 /root/webboot.torrent
149 if ls | grep -q rootfs; then
150 file=$(ls | grep -q rootfs)
151 cat $file >> $2
152 rm -f $file
153 else
154 mv $(ls *mage* *linu* 2> /dev/null) $2
155 fi
156 rm -f /root/webboot.torrent ;;
157 *)
158 wget -O - "$webprefix/$1" >> $2
159 esac
160 }
162 : ${DIALOG=dialog}
164 mount -t proc proc /proc
165 mount -t sysfs sys /sys
166 mnt=$PWD
167 if [ ! -s "$mnt/menu.txt" ]; then
168 BOOTDEV=$(cmdlinearg bootdev)
169 mnt=/mnt
170 mount -t devtmpfs /dev /dev
171 mount -r /dev/${BOOTDEV:-mmcblk0p1} $mnt
172 umount /dev
173 fi
176 # Get global variables
178 title="$(get title $mnt/menu.txt)"
179 subtitle="$(get subtitle $mnt/menu.txt)"
181 timeout="$(get timeout $mnt/menu.txt)"
182 timeout="${timeout:-30}"
184 default="$(get default $mnt/menu.txt)"
186 editbutton='--extra-button --extra-label "Edit"'
187 grep -qs ^noedit $mnt/menu.txt && editbutton=
189 READONLY=
190 grep -qs ^readonly $mnt/menu.txt && READONLY=ON
192 USING_WEBBOOT=
193 grep -qs ^nowebboot $mnt/menu.txt && USING_WEBBOOT=1
195 kmap="$(get kmap $mnt/menu.txt)"
196 [ "$kmap" ] && ! loadkeys $kmap && loadkmap < /usr/share/kmap/$kmap.kmap
198 edittitle="$(get edittitle $mnt/menu.txt)"
200 # Get locale
202 msgsave="$(get msgsave $mnt/menu.txt)"
203 msgedit="$(get msgedit $mnt/menu.txt)"
204 msgmenu="$(get msgmenu $mnt/menu.txt)"
205 msgdone="$(get msgdone $mnt/menu.txt)"
206 msgboot="$(get msgboot $mnt/menu.txt)"
207 msghalt="$(get msghalt $mnt/menu.txt)"
208 msgselectkernel="$(get msgselectkernel $mnt/menu.txt)"
209 msgselectinitrd="$(get msgselectinitrd $mnt/menu.txt)"
210 msgeditcmdline="$(get msgeditcmdline $mnt/menu.txt)"
211 msgkexec="$(get msgkexec $mnt/menu.txt)"
213 # Get OS variables
215 n=0
216 for i in $mnt/*/ ; do
217 [ -s "$i/menu.txt" ] || continue
218 KERNEL="$(get kernel $i/config.txt)"
219 [ -z "$KERNEL" ] && [ -s "$i/kernel.img" ] && KERNEL="kernel.img"
220 [ -z "$KERNEL" ] && [ -s "$i/cmdline.txt" ] && KERNEL="../kernel.img"
221 n=$(($n+1))
222 eval KERNEL_$n="\$KERNEL"
223 eval INITRD_$n="\$(get initramfs \$i/config.txt)"
224 eval CMDLINE_$n="\$(cat \$i/cmdline.txt 2> /dev/null)"
225 eval SAVEDEFAULT_$n="\$(get savedefault \$i/config.txt)"
226 eval KEYWORD_$n="\$(basename \$i)"
227 eval ENTRY_$n="\$(get entry \$i/menu.txt)"
228 done
231 # Main loop
233 while true; do
235 exec 3>&1
236 value=$(sh 2>&1 1>&3 <<EOT
237 $DIALOG --clear \
238 --title "${title:-Boot menu}" \
239 $editbutton \
240 --ok-label "${msgboot:-Boot}" \
241 --cancel-label "${msghalt:-Halt}" \
242 --timeout $timeout \
243 --default-item ${default:-$KEYWORD_1} \
244 --menu "${subtitle:-Default boot in $timeout seconds}" 20 72 14 \
245 $(list_entry) $(web_boot_entry) \
246 Continue "${msgkexec:-Execute SliTaz boot sequence}"
247 EOT
248 )
249 retval=$?
250 exec 3>&-
252 n=0
253 while true; do
254 n=$(($n+1))
255 eval KEYWORD="\$KEYWORD_$n"
256 [ "$KEYWORD" ] || break
257 [ "$KEYWORD" == "$value" ] && break
258 case $value in
259 *timeout) [ "$KEYWORD" == "${default:-$KEYWORD}" ] && break ;;
260 esac
261 done
263 case $retval in
264 0)
265 case "$value" in
266 *WebBoot) web_boot ;;
267 *) break ;;
268 esac ;;
269 1|255)
270 case "$value" in
271 *timeout) break ;;
272 esac
273 umount $mnt
274 umount /sys
275 umount /proc
276 poweroff -f ;;
277 3)
278 [ "$KEYWORD" ] && edit_menu $n ;;
279 esac
280 done
283 # Start OS
285 KEXEC=
286 case "$KEYWORD" in
288 ''|Continue) ;;
289 *)
290 eval KERNEL="\$KERNEL_$n"
291 eval INITRD="\$INITRD_$n"
292 eval CMDLINE="\$CMDLINE_$n"
293 eval SAVEDEFAULT="\$SAVEDEFAULT_$n"
295 grep -qs ARMv6 /proc/cpuinfo || case "$KERNEL" in
296 *BCM*|*7*) ;;
297 *) KERNEL=${KERNEL/.img/7.img}
298 esac
300 if [ -z "$READONLY" ] && [ "$SAVEDEFAULT" ] &&
301 [ -s $mnt/$SAVEDEFAULT/config.txt ]; then
302 cp $mnt/menu.txt /tmp
303 sed -i '/^default/d' /tmp/menu.txt
304 echo "default=$SAVEDEFAULT" >> /tmp/menu.txt
305 mount -o remount,rw $mnt
306 cp /tmp/menu.txt $mnt/menu.txt
307 fi
309 [ "$INITRD" ] && ! kexec -u 2> /dev/null && mount -t tmpfs tmpfs /media
311 for i in ${INITRD//,/ }; do
312 echo "Loading $(basename $i)"
313 web_get $KEYWORD/$i /rootfs
314 if ! kexec -u; then
315 ( zcat /rootfs || unlzma < /rootfs ) | \
316 ( cd /media ; cpio -idmu )
317 rm -f /rootfs
318 else
319 n=$(($(ls -l /rootfs | awk '{ print $5 }') % 4))
320 [ $n -ne 0 ] &&
321 dd if=/dev/zero bs=1 count=$((4 - $n)) >> /rootfs
322 fi 2> /dev/null
323 done
325 cd /
326 if ! kexec -u 2> /dev/null; then
327 umount $mnt
328 ROOTDIR=$(cmdvararg "subroot")
329 TMPDIR=$ROOTDIR/dev/shm
330 TMPDIR=${TMPDIR#/}
331 ROOTDEV=$(cmdvararg "root")
332 [ "$ROOTDEV" == "/dev/null" ] && ROOTDEV=$(cmdvararg "mount")
333 K=$(cmdvararg "kmap")
334 [ "$K" ] && echo $K > /etc/keymap.conf
335 L=$(cmdvararg "lang")
336 [ "$L" ] && echo -e "LANG=$L\nLC_ALL=$L" > /etc/locale.conf
337 TZ=$(cmdvararg "tz")
338 [ "$TZ" ] && echo $TZ > /etc/TZ
339 RDINIT=$(cmdvararg "rdinit")
340 INIT=$(cmdvararg "init")
341 INIT=${INIT:-/sbin/init}
342 if [ -z "$ROOTDEV" ] || ! mount $ROOTDEV $mnt; then
343 INIT=${RDINIT:-/init}
344 mnt=/media
345 for i in $(seq 2 5); do
346 mount -r /dev/mmcblk0p$i /tmp 2> /dev/null || continue
347 echo "Get modules from /dev/mmcblk0p$i"
348 cp -a /tmp/lib/modules /tmp/lib/firmware \
349 $mnt/$ROOTDIR/lib ||
350 cp -a /tmp/shared/lib/modules \
351 /tmp/shared/lib/firmware \
352 $mnt/$ROOTDIR/lib
353 umount /tmp
354 break
355 done
356 fi
357 KEXEC="exec /sbin/switch_root $mnt $INIT"
358 if [ "$ROOTDIR" ] && mount -t tmpfs tmpfs $mnt/$TMPDIR ; then
359 CHROOT=/usr/sbin/chroot
360 cp $(LD_TRACE_LOADED_OBJECTS=1 /lib/ld*.so $CHROOT \
361 | sed 's|.*=> \(/lib/l[^ ]*\).*|\1|;/^\//!d') \
362 $CHROOT $mnt/$TMPDIR
363 CHROOT="$(cd $mnt ; ls $TMPDIR/ld-*so) $TMPDIR/chroot"
364 export LD_LIBRARY_PATH=/$TMPDIR:/lib
365 KEXEC="exec /sbin/switch_root $mnt $CHROOT $ROOTDIR/ $INIT"
366 fi
367 [ -s $mnt/$ROOTDIR/$INIT ] || KEXEC="echo 'No $ROOTDIR/$INIT'"
368 else
369 echo "Loading $(basename $KERNEL)"
370 web_get $KEYWORD/$KERNEL /vmlinuz
371 umount $mnt
372 kexec -l /vmlinuz ${INITRD+=--initrd /rootfs} --command-line \
373 "$(sed 's| .*||' /proc/cmdline) $CMDLINE" --atags
374 KEXEC="kexec -e"
375 fi ;;
376 esac
378 umount /sys
379 umount /proc
380 $KEXEC
381 exec /init