slitaz-arm annotate rpi/piboot @ rev 195

piboot: add savedefault
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Nov 16 10:42:30 2014 +0100 (2014-11-16)
parents e0ff291ac6e2
children 635fc61b4e63
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 #
pankso@118 5 # (C) 2014 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
pankso@118 13 # Check for depends ...
pascal@123 14 LOG=/var/log/$(basename $0).log
pankso@161 15 mv -f $LOG $LOG.0 >/dev/null
pankso@118 16 while read file pkg ; do
pankso@118 17 [ "$(which $file)" ] && continue
pascal@123 18 echo "Can't find $file. Please install $pkg." >> $LOG
pankso@118 19 done <<EOT
pankso@118 20 kexec kexec-tools
pankso@118 21 dialog dialog
pankso@118 22 EOT
pascal@123 23 [ -s $LOG ] && exec /init
pankso@118 24
pankso@118 25 cmdlinearg()
pankso@118 26 {
pankso@118 27 grep -q $1= /proc/cmdline && sed "s/.*$1=\([^ ]*\).*/\1/" </proc/cmdline
pankso@118 28 }
pankso@118 29
pankso@118 30 get()
pankso@118 31 {
pankso@118 32 grep -sq ^$1 $2 && sed "/^$1/!d;s/$1[ :=]*//" $2
pankso@118 33 }
pankso@118 34
pankso@118 35 list_entry()
pankso@118 36 {
pankso@118 37 n=0
pankso@118 38 while true ; do
pankso@118 39 n=$(($n+1))
pankso@118 40 eval KEYWORD="\$KEYWORD_$n"
pankso@118 41 eval ENTRY="\$ENTRY_$n"
pankso@118 42 [ "$KEYWORD" ] || break
pankso@118 43 [ "$KEYWORD" == "$default" ] && ENTRY="$ENTRY (default)"
pankso@118 44 echo -n "$KEYWORD \"$ENTRY\" "
pankso@118 45 done
pankso@118 46 }
pankso@118 47
pankso@118 48 edit_menu()
pankso@118 49 {
pankso@118 50 while true; do
pankso@118 51
pankso@118 52 eval KERNEL="\$KERNEL_$1"
pankso@118 53 eval INITRD="\$INITRD_$1"
pankso@118 54 eval CMDLINE="\$CMDLINE_$1"
pascal@195 55 extra="--extra-button --extra-label ${msgsave:-Save}"
pascal@195 56 [ "$READONLY" ] && extra=''
pankso@118 57
pankso@118 58 exec 3>&1
pankso@118 59 value=$($DIALOG --clear \
pankso@118 60 --title "${edittitle:-Edit menu}" \
pascal@195 61 --ok-label "${msgedit:-Edit}" \
pascal@195 62 --cancel-label "${msgdone:-Done}" \
pankso@118 63 --menu "" 20 72 14 \
pascal@195 64 $extra \
pankso@118 65 Kernel "$KERNEL" \
pankso@118 66 Initramfs "$INITRD" \
pankso@118 67 Cmdline "$CMDLINE" 2>&1 1>&3 )
pankso@118 68 retval=$?
pankso@118 69 exec 3>&-
pankso@118 70
pankso@118 71 case $retval in
pankso@118 72 1|255) return ;;
pascal@195 73 3) cp $mnt/$KEYWORD/config.txt /tmp/config.txt
pascal@195 74 sed -i '/^kernel/d;/^initrd/d;/^cmdline/d' /tmp/config.txt
pascal@195 75 echo "kernel=$KERNEL" >> /tmp/config.txt
pascal@195 76 [ "$INITRD" ] && echo "initrd $INITRD" >> /tmp/config.txt
pascal@195 77 [ "$CMDLINE" ] && echo "cmdline=$CMDLINE" >> /tmp/config.txt
pascal@195 78 mount -o remount,rw $mnt
pascal@195 79 cp /tmp/config.txt $mnt/$KEYWORD/config.txt
pascal@195 80 mount -o remount,ro $mnt ;;
pankso@118 81 esac
pankso@118 82
pankso@118 83 exec 3>&1
pankso@118 84 case $value in
pankso@118 85 Kernel)
pascal@195 86 data=$($DIALOG --clear --title "${msgselectkernel:-Select the kernel}" \
pankso@118 87 --fselect "$mnt/$KEYWORD/$KERNEL" 10 72 2>&1 1>&3) ;;
pankso@118 88 Initramfs)
pascal@195 89 data=$($DIALOG --clear --title "${msgselectinitrd:-Select the initramfs}" \
pankso@118 90 --fselect "$mnt/$KEYWORD/$INITRD" 10 72 2>&1 1>&3) ;;
pankso@118 91 Cmdline)
pascal@195 92 data=$($DIALOG --clear --title "${msgeditcmdline:-Edit cmdline}" \
pankso@118 93 --inputbox "Cmdline" 20 72 2>&1 "$CMDLINE" 1>&3) ;;
pankso@118 94 esac
pankso@118 95 retval=$?
pankso@118 96 exec 3>&-
pankso@118 97
pankso@118 98 case $retval in
pankso@118 99 1|255) continue ;;
pankso@118 100 esac
pankso@118 101
pankso@118 102 case $value in
pankso@118 103 Kernel) [ -f $data ] && eval KERNEL_$1=\$data ;;
pankso@118 104 Initramfs) [ -f $data ] && eval INITRD_$1=\$data ;;
pankso@118 105 Cmdline) eval CMDLINE_$1=\$data ;;
pankso@118 106 esac
pankso@118 107 done
pankso@118 108 }
pankso@118 109
pankso@118 110 web_boot_entry()
pankso@118 111 {
pankso@118 112 [ "$USING_WEBBOOT" == "1" ] ||
pankso@118 113 echo -n 'WebBoot "boot from Internet"'
pankso@118 114 }
pankso@118 115
pankso@118 116 web_boot()
pankso@118 117 {
pankso@118 118 USING_WEBBOOT=1
pankso@118 119 [ -s $mnt/network.conf ] && cp $mnt/network.conf /etc
pankso@118 120 /etc/init.d/network.sh start
pankso@118 121 webpath=$(get webpath $mnt/menu.txt)
pankso@118 122 [ "$webpath" ] || webpath=http://mirror.slitaz.org/pxe/arm/boot.php
pascal@192 123 for url in ${webpath//,/ }; do
pascal@192 124 wget -O /root/webboot.sh \
pascal@192 125 $url?mac=$(cat /sys/class/net/eth0/address) 2>&1 > /dev/null
pascal@192 126 [ -s /root/webboot.sh ] || continue
pascal@192 127 . /root/webboot.sh
pascal@192 128 webprefix=$(dirname $url)
pascal@192 129 editbutton=""
pascal@192 130 break
pascal@192 131 done
pankso@118 132 }
pankso@118 133
pascal@191 134 web_get()
pascal@191 135 {
pascal@191 136 case "$1" in
pascal@191 137 *torrent) # See http://sl-lab.it/dokuwiki/doku.php/tesi:boottorrent_en
pascal@191 138 [ -z "$(which aria2)" ] &&
pascal@191 139 echo "Can't find aria2." >> $LOG &&
pascal@191 140 exec /init
pascal@191 141
pascal@191 142 wget -O /root/webboot.torrent $1
pascal@191 143 aria2c --enable-dht=false --disable-ipv6=true --seed-time=0 \
pascal@191 144 --file-allocation=none -j5 /root/webboot.torrent
pascal@191 145
pascal@191 146 if ls | grep -q rootfs; then
pascal@191 147 file=$(ls | grep -q rootfs)
pascal@191 148 cat $file >> $2
pascal@191 149 rm -f $file
pascal@191 150 else
pascal@191 151 mv $(ls *mage* *linu* 2> /dev/null) $2
pascal@191 152 fi
pascal@191 153 rm -f /root/webboot.torrent ;;
pascal@191 154 *)
pascal@191 155 wget -O - $1 >> $2
pascal@191 156 esac
pascal@191 157 }
pascal@191 158
pankso@118 159 : ${DIALOG=dialog}
pankso@118 160
pankso@118 161 mount -t proc proc /proc
pascal@191 162 mount -t sysfs sys /sys
pankso@118 163 BOOTDEV=$(cmdlinearg bootdev)
pankso@118 164 mnt=/mnt
pankso@118 165 mount -t devtmpfs /dev /dev
pankso@118 166
pankso@118 167 # A dirty hack: why devtmpfs does not mount ?
pankso@118 168 # pankso@20140421: It mount fine on my side
pankso@118 169 [ -b /dev/mmcblk0p1 ] || mknod -m 660 /dev/mmcblk0p1 b 179 1
pankso@118 170
pankso@118 171 mount -r /dev/${BOOTDEV:-mmcblk0p1} $mnt
pankso@118 172 umount /dev
pankso@118 173
pankso@118 174
pankso@118 175 # Get global variables
pankso@118 176
pankso@118 177 title=$(get title $mnt/menu.txt)
pankso@118 178 subtitle=$(get subtitle $mnt/menu.txt)
pankso@118 179
pankso@118 180 timeout=$(get timeout $mnt/menu.txt)
pankso@118 181 timeout=${timeout:-30}
pankso@118 182
pankso@118 183 default=$(get default $mnt/menu.txt)
pankso@118 184
pankso@118 185 editbutton='--extra-button --extra-label "Edit"'
pankso@118 186 grep -qs ^noedit i$mnt/menu.txt && editbutton=
pankso@118 187
pascal@195 188 READONLY=
pascal@195 189 grep -qs ^readonly i$mnt/menu.txt && READONLY=ON
pascal@195 190
pascal@195 191 USING_WEBBOOT=
pascal@195 192 grep -qs ^nowebboot i$mnt/menu.txt && USING_WEBBOOT=1
pascal@195 193
pankso@118 194 kmap=$(get kmap $mnt/menu.txt)
pankso@118 195 [ "$kmap" ] && ! loadkeys $kmap && loadkmap < /usr/share/kmap/$kmap.kmap
pankso@118 196
pankso@118 197 edittitle=$(get edittitle $mnt/menu.txt)
pankso@118 198
pascal@195 199 # Get locale
pascal@195 200
pascal@195 201 msgsave=$(get msgsave $mnt/menu.txt)
pascal@195 202 msgedit=$(get msgedit $mnt/menu.txt)
pascal@195 203 msgdone=$(get msgdone $mnt/menu.txt)
pascal@195 204 msgboot=$(get msgboot $mnt/menu.txt)
pascal@195 205 msghalt=$(get msghalt $mnt/menu.txt)
pascal@195 206 msgselectkernel=$(get msgselectkernel $mnt/menu.txt)
pascal@195 207 msgselectinitrd=$(get msgselectinitrd $mnt/menu.txt)
pascal@195 208 msgeditcmdline=$(get msgeditcmdline $mnt/menu.txt)
pascal@195 209 msgkexec=$(get msgkexec $mnt/menu.txt)
pankso@118 210
pankso@118 211 # Get OS variables
pankso@118 212
pankso@118 213 n=0
pankso@118 214 for i in $mnt/*/ ; do
pankso@118 215 grep -qs ^kernel $i/config.txt || continue
pankso@118 216 n=$(($n+1))
pankso@118 217 eval KERNEL_$n="\$(get kernel \$i/config.txt)"
pankso@118 218 eval INITRD_$n="\$(get initramfs \$i/config.txt)"
pankso@118 219 eval CMDLINE_$n="\$(cat \$i/cmdline.txt)"
pascal@195 220 eval SAVEDEFAULT_$n="\$(get savedefault \$i/config.txt)"
pankso@118 221 eval KEYWORD_$n="\$(basename \$i)"
pankso@118 222 eval ENTRY_$n="\$(get entry \$i/menu.txt)"
pankso@118 223 done
pankso@118 224
pankso@118 225
pankso@118 226 # Main loop
pankso@118 227
pankso@118 228 while true; do
pankso@118 229
pankso@118 230 exec 3>&1
pankso@118 231 value=$(sh 2>&1 1>&3 <<EOT
pankso@118 232 $DIALOG --clear \
pankso@118 233 --title "${title:-Boot menu}" \
pankso@118 234 $editbutton \
pascal@195 235 --ok-label "${msgboot:-Boot}" \
pascal@195 236 --cancel-label "${msghalt:-Halt}" \
pankso@118 237 --timeout $timeout \
pankso@118 238 --menu "${subtitle:-Default boot in $timeout seconds}" 20 72 14 \
pankso@118 239 $(list_entry) $(web_boot_entry) \
pascal@195 240 Continue "${msgkexec:-Execute SliTaz boot sequence}"
pankso@118 241 EOT
pankso@118 242 )
pankso@118 243 retval=$?
pankso@118 244 exec 3>&-
pankso@118 245
pankso@118 246 n=0
pankso@118 247 while true; do
pankso@118 248 n=$(($n+1))
pankso@118 249 eval KEYWORD="\$KEYWORD_$n"
pankso@118 250 [ "$KEYWORD" ] || break
pankso@118 251 [ "$KEYWORD" == "$value" ] && break
pankso@118 252 case $value in
pankso@118 253 *timeout) [ "$KEYWORD" == "$default" ] && break ;;
pankso@118 254 esac
pankso@118 255 done
pankso@118 256
pankso@118 257 case $retval in
pankso@118 258 0)
pankso@118 259 case "$value" in
pankso@118 260 *WebBoot) web_boot ;;
pankso@118 261 *) break ;;
pankso@118 262 esac ;;
pankso@118 263 1|255)
pankso@118 264 case "$value" in
pankso@118 265 *timeout) break ;;
pankso@118 266 esac
pankso@118 267 umount $mnt
pascal@191 268 umount /sys
pankso@118 269 umount /proc
pankso@118 270 poweroff -f ;;
pankso@118 271 3)
pankso@118 272 [ "$KEYWORD" ] && edit_menu $n ;;
pankso@118 273 esac
pankso@118 274 done
pankso@118 275
pankso@118 276
pankso@118 277 # Start OS
pankso@118 278
pankso@118 279 case "$KEYWORD" in
pankso@118 280
pankso@118 281 ''|Continue)
pascal@191 282 KEXEC= ;;
pankso@118 283
pankso@118 284 *)
pankso@118 285 eval KERNEL="\$KERNEL_$n"
pankso@118 286 eval INITRD="\$INITRD_$n"
pankso@118 287 eval CMDLINE="\$CMDLINE_$n"
pascal@195 288 eval SAVEDEFAULT="\$SAVEDEFAULT_$n"
pankso@118 289
pankso@118 290 if [ "$webprefix" ]; then
pankso@118 291 cd /root
pascal@191 292 web_get $webprefix/$KEYWORD/$KERNEL vmlinuz
pascal@191 293 KERNEL=vmlinuz
pascal@124 294 for i in ${INITRD//,/ }; do
pascal@191 295 web_get $webprefix/$KEYWORD/$i rootfs.gz
pascal@191 296 n=$(stat -c %s rootfs.gz)
pascal@124 297 n=$(($n % 4))
pascal@124 298 [ $n -eq 0 ] && continue
pascal@191 299 dd if=/dev/zero bs=1 count=$((4 - $n)) >> rootfs.gz
pascal@124 300 done
pankso@118 301 else
pankso@118 302 cd $mnt/$KEYWORD
pascal@124 303 cp $KERNEL /root
pascal@124 304 for i in ${INITRD//,/ }; do
pascal@124 305 cat $i >> /root/rootfs.gz
pascal@124 306 n=$(stat -c %s /root/rootfs.gz)
pascal@124 307 n=$(($n % 4))
pascal@124 308 [ $n -eq 0 ] && continue
pascal@124 309 dd if=/dev/zero bs=1 count=$((4 - $n)) >> /root/rootfs.gz
pascal@124 310 done
pankso@118 311 cd /root
pankso@118 312 fi
pascal@195 313 if [ -z "$READONLY" ] && [ "$SAVEDEFAULT" ] &&
pascal@195 314 [ -s $mnt/$SAVEDEFAULT/config.txt ]; then
pascal@195 315 cp $mnt/menu.txt /tmp
pascal@195 316 sed -i '/^default/d' /tmp/menu.txt
pascal@195 317 echo "default=$SAVEDEFAULT" >> /tmp/menu.txt
pascal@195 318 mount -o remount,rw $mnt
pascal@195 319 cp /tmp/menu.txt $mnt/menu.txt
pascal@195 320 fi
pascal@124 321 [ "$INITRD" ] && INITRD="--initrd rootfs.gz"
pankso@118 322 [ "$CMDLINE" ] && CMDLINE="--command-line \"$CMDLINE\""
pankso@118 323
pankso@118 324 kexec -l $(basename $KERNEL) $INITRD $CMDLINE --atags
pascal@191 325 KEXEC="kexec -e" ;;
pankso@118 326
pankso@118 327 esac
pascal@191 328
pascal@191 329 umount $mnt
pascal@191 330 umount /sys
pascal@191 331 umount /proc
pascal@191 332 $KEXEC
pascal@191 333 exec /init