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