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)&serial=$(sed '/Serial/!d;s/.*: //' \ |
pascal@216 | 123 /proc/cpuinfo)&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 |