# 90-genmen, the brains of the uboot boot.scr generator
#
# Copyright 2013 Red Hat, Inc.  All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

PATH=/sbin:/bin:$PATH

. /etc/sysconfig/uboot

: ${UBOOT_DIR:="/boot"}
: ${UBOOT_KLIST:="$UBOOT_DIR/klist.txt"}

###############################
cd /boot

# First, find all the dtbs
FDTCOUNT=0
declare -A dtbmap
for dtb in `ls dtb-*/*.dtb | sed 's,.*/,,' | sort -u`; do
  FDTCOUNT=$[ $FDTCOUNT + 1 ]
  echo kd_$FDTCOUNT=$dtb
  dtbmap[${FDTCOUNT}]=${dtb}
done

# Second, find all the kernels and which dtbs they provide
KCOUNT=0
declare -A kmap
for k in `tac $UBOOT_KLIST`; do
  if [ ! -f vmlinuz-$k ] || [ ! -f initramfs-$k.img ]; then
    echo "$UBOOT_KLIST showed $k but an associated vmlinuz or initramfs does not exist in /boot. Exiting."
    exit 1
  fi
  KCOUNT=$[ $KCOUNT + 1 ]
  KLIST="$KLIST $k"

  case $k in
    *armv7l|*armv7hl) ktype=unified; ;;
    *) ktype="`echo $k | sed 's/.*armv7[hl]*.//'`" ;;
  esac

  kmap[${KCOUNT}]=$k
  kmap[${KCOUNT}_type]=$ktype

  if [ -d dtb-$k ]; then
    kd=""
    for i in `seq 1 $FDTCOUNT`; do
      if [ -f dtb-$k/${dtbmap[$i]} ]; then
        kd="$kd $i"
      fi
    done
  else
    echo "Did not find dtb directory in /boot/dtb-$k, exiting."
    exit 1
  fi
  echo "kfdtc$KCOUNT='`echo $kd | sed s/^\ //`'"
done

echo "k_count='`seq -s \  1 $KCOUNT`'"
for k in `seq 1 $KCOUNT`; do
  echo "kv${k}=${kmap[$k]}"
  echo "ka${k}=${kmap[${k}_type]}"
done

# u_k # (# corresponding to bottom of klist.txt)
# k_count # (number of kernels)
# kv# (name of kernel#)
# ka# arch (name of kernel architecture)
# kfdtc# # (number of dtbs for this kernel)
# k#_# dtbfile (name of each dtbfile)

for k in `seq 1 $KCOUNT`; do
  echo "setenv k$k \"u_k=$k; run kl_picked\""
done

cat << EOF

#Infra for klist command
setenv klist 'echo; echo Kernel List; echo -----------; run kl_enum kl_default'
setenv kl_enum 'for i in \$k_count;do setenv catin ka\$i;run catcat ; setenv tmpktype \$catout;setenv catin kv\$i;run catcat ;echo k\$i: \$catout for \$tmpktype ;done'
setenv kl_default 'echo (Currently selected: k\$u_k: \$u_kernel); echo; echo Type \\\\\"run kX\\\\\" where X is the kernel number to use.'

#Run each time a new kernel is selected
setenv kl_picked 'have_k=""; have_i=""; have_d=""; setenv catin kv\$u_k;run catcat ;setenv u_kernel \$catout; echo Using kernel k\$u_k (\$u_kernel).'

#Infra for dtblist command
setenv dtblist 'run dtb_check dtb_enum dtb_end'
setenv dtb_check 'if test X\$u_kernel = X; then echo "No kernel selected.  Use klist first."; run false; else echo; echo "Device Tree Blob (DTB) list"; echo; echo "Kernel \$u_kernel has the following dtbs available:"; fi'
setenv dtb_enum 'setenv catin kfdtc\$u_k;run catcat ;for i in \$catout;do setenv catin kd_\$i; run catcat ; echo dtb\$i: \$catout;setenv dtb\$i "u_dtb=\$catout\; run dtb_ok";done'
setenv dtb_end 'echo Type \\"run dtbX\\" where X is the dtb number to use.; echo (Currently selected: \$u_dtb); echo'
setenv dtb_ok echo DTB selected. Type \\\\\"boot\\\\\" to start.

#Set a default kernel
setenv set_u_k 'if test -n \$u_dtb ; then u_kernel="";for on_k in \$k_count; do if test -n \$u_kernel\;then run true ;else setenv catin kfdtc\$on_k ;run catcat ; for on_d in \$catout; do setenv catin kd_\${on_d}; run catcat ;if test \$catout = \$u_dtb ;then run k\$on_k ;fi ;done ;fi ;done; if test -n \$u_kernel;then run true;else echo "No kernel provides dtb named \$u_dtb";run false;fi ;else run set_u_k_nodtb help ;fi'
setenv set_u_k_nodtb 'echo "No value for u_dtb.  Use klist and dtblist to select."'

#Infra for clist command
setenv clist 'echo; echo Board Configuration List; echo ------------------------; for i in \$c_count;do setenv catin ca\$i;run catcat ;echo c\$i: \$catout ;done; echo Type \\\"run cX\\\" where X is the board configuration number to use.'

EOF
