Repository URL to install this package:
|
Version:
0.4.2+3 ▾
|
#!/bin/bash
OLD_GFX_CONFIG_FILE="/live/config/gfxsave.conf"
GFX_SUFFIX=".def"
GFX_SAVE_ON="gfxsave.on"
CPIO_FILE="gfx-cpio"
CPIO_DIR="/live/tmp/cpio"
hbar="======================================================================"
tab="----------------------------------------------------------------------"
main() {
local GFX_BOOT_DIR=$1
local gfx_cmd=$2
local GFX_MESSAGE_FILE
local GFX_OUTPUT_DIRS
[ -n "$CMDLINE" ] || CMDLINE="$(cat /proc/cmdline)"
local PROC_CMDLINE=$CMDLINE
# kernel built-in boot parameter
local CONF_CMDLINE=$(grep ^CONFIG_CMDLINE= /boot/config-$(uname -r) 2>/dev/null | cut -d\" -f2 | tail -1)
CMDLINE=""
local conf param x
for param in $PROC_CMDLINE; do
x=x
for conf in $CONF_CMDLINE; do
[ "$conf" = "$param" ] && x="" && break
done
[ -n "$x" ] && CMDLINE="$CMDLINE $param"
done
case $VERBOSE in
[0-9]|[0-9][0-9]) ;;
*) VERBOSE=5 ;;
esac
# Width of some printfs with no color codes
MSG8_W=30
set_colors "$NO_COLOR" "$LO_COLOR"
case "$gfx_cmd" in
menus|custom|both|reset) ;;
*) err "Bad gfxsave parameter $cheat_co$gfx_cmd$CO_ERR. \
Expected$cheat_co menus custom both$err_co or$cheat_co reset"
return ;;
esac
if [ -n "$CONF_CMDLINE" ]; then
vmsg 6 "Boot parameters built into the kernel:"
vmsg 6 "$cheat_co$CONF_CMDLINE"
fi
vmsg 6 "Current bootcodes:"
vmsg 6 "$cheat_co$CMDLINE"
# Do this once for both directories
write_boot_param_hash
local pre
for pre in ext sys; do
TYPE=${pre}linux
NAME=${pre}Linux
XXX_LINUX_DIR=$GFX_BOOT_DIR/$TYPE
is_writable $XXX_LINUX_DIR/ dir $NAME || continue
case $pre in
ext) XXX_LINUX_CFG=$XXX_LINUX_DIR/$TYPE.conf ;;
sys) XXX_LINUX_CFG=$XXX_LINUX_DIR/$TYPE.cfg ;;
esac
is_writable "$XXX_LINUX_CFG" file $NAME || continue
msg
msg " Found directory:$cheat_co $XXX_LINUX_DIR"
local new_config_file=$XXX_LINUX_DIR/gfxsave.cfg
if [ -r $new_config_file ]; then
msg "Using$cheat_co $new_config_file"
GFX_CONFIG_FILE=$new_config_file
else
GFX_CONFIG_FILE=$OLD_GFX_CONFIG_FILE
fi
if ! [ -r "$GFX_CONFIG_FILE" ]; then
err "Could not find gfxsave config file: $GFX_CONFIG_FILE"
continue
fi
MENU_DIR=$XXX_LINUX_DIR
unpack_cpio $XXX_LINUX_DIR/$CPIO_FILE $CPIO_DIR && MENU_DIR=$CPIO_DIR
# FIXME: will this work with gfx-cpio?
# Handle the "always" parameter and then work like "both"
# Must do this for each directory
local gfx_def_file=$MENU_DIR/gfxsave.def
if [ "$gfx_cmd" = "always" ]; then
test -e $gfx_def_file || echo gfxsave=always > $gfx_def_file
gfx_cmd=both
else
test -e $gfx_def_file && rm -f $gfx_def_file 2>/dev/null
fi
case $gfx_cmd in
menus|both|custom)
write_gfx_menu_defaults prep $MENU_DIR ""
msg " popup params:$cheat_co$ALL_MENU_PARAMS"
msg "main menu params:$cheat_co" $(extra_cmdline_params) ;;
esac
case $gfx_cmd in
custom|both) create_custom_main_entry $NAME $XXX_LINUX_CFG
update_main_menu_default $XXX_LINUX_CFG ;;
esac
case $gfx_cmd in
reset|menus|both) reset_one_dir $NAME $MENU_DIR ;;
esac
case $gfx_cmd in
menus|both) update_gfxmenus $MENU_DIR;;
esac
repack_cpio $XXX_LINUX_DIR/$CPIO_FILE $CPIO_DIR
if [ -n "$GFX_LOG_FILE" -a -z "$NO_LOG" ]; then
mkdir -p $(dirname $GFX_LOG_FILE)
echo -e "$LOG" | /bin/sed -r "s:\x1B\[[0-9;]*[mK]::g" > $GFX_LOG_FILE
[ -n "$NO_COLOR" ] || echo -e "$LOG" > $GFX_LOG_FILE.color
fi
done
}
unpack_cpio() {
local file=$1 dir=$2
test -r $file || return 1
rm -rf $dir
mkdir -p $dir || return 1
msg " Unpack CPIO file:$cheat_co $file"
(cd $dir && cpio -idum --quiet < $file)
return 0
}
repack_cpio() {
local file=$1 dir=$2
test -r $file || return 1
msg " Repack CPIO file:$cheat_co $file"
(cd $dir && find . | cpio -o --quiet) > $file
return 0
}
#==============================================================================
# Update Panel menus defaults
#==============================================================================
write_boot_param_hash() {
for param in $CMDLINE; do
param=$(echo $param | sed -r -e 's/^(nouveau|video)\./\1_/' -e 's/^(persist|frugal)-/\1_/')
# only let through parameter names made of word chars
# so we can turn them into variables names. This is
# a poor man's ash hash.
# skip parameter names with non-word characters
echo $param | grep -q "^[^=]*[^A-Za-z0-9_=]" && continue
case "$param" in
*=*)
nam=${param%%=*}
val=${param#*=}
eval GFX_P_$nam="$val";;
*)
eval GFX_F_$param=true;;
esac
done
# No output dirs, just check if anything needs to be done
# FIXME: move this to main()
}
update_gfxmenus() {
local dir=$1
msg
bold "Update bootloader menu defaults"
if [ $GFX_MENU_CNT -eq 0 ]; then
msg "No defaults were found to update"
return
fi
pmsg $GFX_MENU_CNT "Found $num_co%n$m_co default setting%s to update"
# This time it's for real
write_gfx_menu_defaults write $dir
}
# This routine gets called twice. First as prep to find the popup params
# so we can find the parameters that go in the main menu. Then a second
# time (if we are updating menus) to actually update the menus. I'm sure
# all of this could be greatly improved.
write_gfx_menu_defaults() {
GFX_MENU_CNT=0
ALL_MENU_PARAMS=
local type=$1 dir=$2
local quiet write save
case $type in
write) write=true ; quiet=true ;;
prep) save=true ;;
*) exit 3;;
esac
local m_config
for m_config in $(grep '^[A-Za-z]' $GFX_CONFIG_FILE); do
local title=$(echo $m_config | cut -d"|" -f1)
local fname=$(echo $m_config | cut -d"|" -f2)
local out=
fields=$(echo $m_config | cut -d"|" -f3-30)
for field in $(echo $fields | sed 's/|/ /g'); do
eval local nam="\$GFX_P_$field"
[ -n "$nam" ] && out="$out${out:+ }$field=$nam"
eval local cmd="\$GFX_F_$field"
[ -n "$cmd" ] && out="$out${out:+ }$field"
done
local entry=$(echo "$out" | sed -r \
-e 's/^ //' \
-e 's/\<(nouveau|video)_/\1./g' \
-e 's/\<lang=//' \
-e 's/\<nouveau\.modeset=0$//' \
-e 's/\<tz=//')
[ -n "$out" ] || continue
local menu_file=$dir/$fname.men
if [ -r $menu_file ]; then
[ "$quiet" ] || vmsg 6 " Found menu file:$cheat_co $(basename $menu_file)"
if ! grep -q "\`$entry$" $menu_file; then
local found=
while [ -n "$entry" -a -z "${entry##* *}" ]; do
# Strip off params from the end of the string
entry=${entry% *}
out=${out% *}
grep -q "\`$entry$" $menu_file || continue
found=true
break
done
if [ -z "$found" ]; then
[ "$quiet" ] || msg "Menu file$cheat_co $fname.men$m_co does not contain "$cheat_co$entry$m_co". Skipping."
continue
fi
fi
fi
GFX_MENU_CNT=$(($GFX_MENU_CNT + 1))
[ "$save" ] && ALL_MENU_PARAMS="$ALL_MENU_PARAMS ${out# }"
[ "$write" ] || continue
msg "$(printf " %12s:$from_co %-14s $cheat_co%s\n" \
"$title" "$fname$GFX_SUFFIX" "$entry")"
echo "$entry" > $dir/$fname$GFX_SUFFIX
done
}
reset_one_dir() {
local name="$1" dir="$2"
[ -n "$dir" ] || return
bold
bold "Reset bootloader menu defaults"
local fcnt=0
for file in $(grep '^[A-Za-z]' $GFX_CONFIG_FILE | cut -d"|" -f2); do
local full=$dir/$file$GFX_SUFFIX
[ -e "$full" ] || continue
fcnt=$(( $fcnt + 1 ))
rm -rf $full
done
pmsg $fcnt "Deleted$num_co %n$from_co $name$m_co file%s"
}
is_writable() {
local file=$1 name=$2 type=$3
[ "$file" ] || return 1
#msg8e "Could not find" $type "$name" $file
#msg8e "Cannot write to" $type "$name" $file
if ! [ -e "$file" ]; then
msg8e "Could not find" $type "$name" $file
return 1
fi
[ -w "$file" ] || chmod u+w $file
if ! [ -w "$file" ]; then
msg8e "Cannot write to" $type "$name" $file
return 1
fi
[ -n "$name" ] && msg8 "Found" $type "$name" $file
return 0
}
_msg8() { vmsg 7 "$1$(printf %${MSG8_W}s "$2$from_co $3$1 $4")$to_co $5" ; }
msg8() { _msg8 "$m_co" "$@"; }
msg8e() { _msg8 "$err_co" "$@"; }
msg7() {
local c1=$1 pre=$2 c2=$3 file=$4
vmsg 7 "$c1$(printf %30s "$pre")$c2 $file"
}
#==============================================================================
# Update default main menu entry
#==============================================================================
update_main_menu_default() {
local file=$1
[ "$DEFAULT_LABEL" ] || return
bold "Update main menu default to$cheat_co $DEFAULT_LABEL"
if grep -q "^default\>" "$file"; then
sed -r -i "s/^default\>.*/default $DEFAULT_LABEL/" "$file"
elif [ "$FIRST_LABEL_LINE" ]; then
sed -i "$FIRST_LABEL_LINE idefault $DEFAULT_LABEL\n" "$file"
sed -i "$FIRST_LABEL_LINE G" "$file"
fi
}
set_main_menu_default() {
local type=$1; shift
local file=$1
[ -n "$file" ] || return
local sorted_params="$(get_all_cfg_params $@ | sort -u)"
cmdline_params=$(cmdline_only $sorted_params)
cmdline_params=$(echo $cmdline_params)
vmsg 8 "Cmdline params: $cmdline_params"
find_main_entry "$cmdline_params" "$@"
if ! [ -n "$FOUND_ENTRY" ]; then
msg "Failed to resolve default$from_co $type$m_co entry"
return
fi
local pre="Set$from_co $type$m_co default to"
msg "$(printf %${MSG8_W}s "$pre") ($num_co$FOUND_ENTRY$m_co)$high_co $FOUND_TITLE"
if grep -q "^\s*default\>" $file; then
sed -i -r "s/^(\s*default\>).*/\1 $FOUND_ENTRY/" $file
else
sed -i "1i\
default $FOUND_ENTRY" $file
fi
}
get_all_cfg_params() {
local file=$1
local counter=$2
local target=$3
local first=$4
while read a1 a2 a3 a4 a5 a6 a7 a8 a9; do
[ "$a1" = "$target" ] || continue
for i in $(seq $first 9); do
eval val=\$a$i
[ -n "$val" ] || break
echo $val
done | sort
done <<Config_File
$(cat $file)
Config_File
}
cmdline_only() {
for param; do
case " $CMDLINE " in
*" $param "*) echo $param;;
esac
done
}
find_main_entry() {
local cmdline=$1
local file=$2
local counter=$3
local target=$4
local first=$5
local title val
FOUND_ENTRY=
FOUND_TITLE=
[ -n "$file" ] || return
local count=-1 line=0
while read a1 a2 a3 a4 a5 a6 a7 a8 a9; do
line=$((line + 1))
if [ "$a1" = "$counter" ]; then
count=$((count + 1))
: ${FIRST_LABEL_LINE:=$line}
local title=
for i in $(seq 2 9); do
eval val=\$a$i
[ -n "$val" ] || break
title="$title $val"
done
title=${title# }
#echo "$count: $title"
fi
[ "$a1" = "$target" ] || continue
local params=$(
for i in $(seq $first 9); do
eval val=\$a$i
[ -n "$val" ] || break
echo $val
done | sort)
# Ignore entries with no parameters
[ -n "$params" ] || continue
params=$(echo $params)
#-- echo " params: $params"
#-- echo "cmdline: $cmdline"
#-- continue
[ "$params" = "$cmdline" ] || continue
#vmsg 8 "Found entry $count: $title"
FOUND_TITLE=$title
FOUND_ENTRY=$count
break
done <<Config_File
$(cat $file)
Config_File
}
#==============================================================================
# Create custom main menu entry
#==============================================================================
create_custom_main_entry() {
local name=$1 file=$2
local alpha_params=$(extra_cmdline_params | tr ' ' '\n' | sort -u)
alpha_params=$(echo $alpha_params)
vmsg 9 "Main menu params:$cheat_co $alpha_params"
if ! [ -n "$alpha_params" ]; then
msg "No non-menu parameters found"
return
fi
local ordered_params=$(extra_cmdline_params)
ordered_params=$(echo $ordered_params)
find_main_entry "$alpha_params" "$file" LABEL APPEND 2
if ! [ -n "$FOUND_ENTRY" ]; then
bold
bold "Create Custom bootloader entry"
add_custom_entry $name "$file" LABEL KERNEL "" "APPEND" INITRD "$ordered_params"
else
pre="${from_co}$name$m_co entry already exists:"
msg "$(printf %${MSG8_W}s "$pre") ($num_co$FOUND_ENTRY$m_co)$high_co $FOUND_TITLE"
DEFAULT_LABEL=$FOUND_TITLE
fi
}
add_custom_entry() {
local type=$1
local file=$2
local title_tag=$3
local kernel_tag=$4
local kernel_sed=$5
local append_tag=$6
local initrd_tag=$7
local params=$8
[ -n "$file" ] || return
local date=$(date "+%e %B %Y")
local title_text="Custom ($date)"
local title="$title_tag $title_text\n"
local state=1 kernel append initrd
case $type in
*Linux) title="LABEL custom\n MENU LABEL $title_text\n" ;;
esac
[ -n "$append_tag" ] && append=" $append_tag $params\n"
local replace target pre="$from_co $type$m_co entry labeled:"
if grep -q "^\s*$title_tag\s\+custom" $file; then
replace=true
target="$title_tag\s\+custom"
msg "$(printf %${MSG8_W}s "Replace$pre")$cheat_co $title_text"
else
target="$title_tag"
msg "$(printf %${MSG8_W}s "Create$pre")$cheat_co $title_text"
fi
msg "$(printf %30s "Params:")$cheat_co $params"
local backup=${file%.*}.bak
local file2=${file%.*}.tmp
[ -e "$backup" ] || cp $file $backup
rm -f $file2
local old_ifs=$IFS
IFS=''
while read line; do
#echo "$state: $line"
case $state in
1) if echo $line | grep -q "^\s*$target\>"; then
state=2
[ -n "$replace" ] && continue
fi;;
2) if echo $line | grep -q "^\s*$kernel_tag\>"; then
if [ -n "$kernel_sed" ]; then
kernel="$(echo $line | sed -r "s/$kernel_sed/\1 $params/")\n"
else
kernel="$line\n"
fi
fi
echo $line | grep -q "^\s*$initrd_tag" && initrd="$line\n"
if echo $line | grep -q "^\s*$title_tag"; then
echo -e "$title$kernel$append$initrd" >> $file2
vmsg_nc 8 "$(echo -e "$title$kernel$append$initrd \n")"
state=3
else
[ -n "$replace" ] && continue
fi;;
3) ;;
esac
echo "$line" >> $file2
vmsg_nc 8 "$line"
done <<Config_File
$(cat $file)
Config_File
IFS=$old_ifs
if [ "$state" -lt 3 ]; then
err "Failed to update$from_co $type$err_co config file"
return
fi
mv $file2 $file
DEFAULT_LABEL=custom
}
#------------------------------------------------------------------------------
# Only echo cmdline params that *don't* match any of the names in menu_params.
# Equal signs and values after equal signs are ignored.
#------------------------------------------------------------------------------
extra_cmdline_params() {
local param menu_params=$1
for param in $CMDLINE; do
case $param in
gfxsave|gfxsave=*) continue ;;
bootsave|bootsave=*) continue ;;
BOOT_IMAGE=*) continue ;;
savestate|nosavestate) continue ;;
nostore|dostore) continue ;;
checkmd5|checkfs) continue ;;
automount|mount=*) continue ;;
hwclock=*) continue ;;
desktop=*) continue ;;
nouveau.modeset=0) continue ;;
esac
case " $ALL_MENU_PARAMS " in
*" ${param%%=*} "*) ;;
*" ${param} "*) ;;
*) echo $param ;;
esac
done
}
#------------------------------------------------------------------------------
# Utilities
#------------------------------------------------------------------------------
set_colors() {
local noco=$1 loco=$2
[ "$noco" ] && return
# Adjust this printf width for added color codes
MSG8_W=$((MSG8_W + 14))
local e=$(printf "\e")
black="$e[0;30m"; blue="$e[0;34m"; green="$e[0;32m"; cyan="$e[0;36m";
red="$e[0;31m"; purple="$e[0;35m"; brown="$e[0;33m"; lt_gray="$e[0;37m";
dk_gray="$e[1;30m"; lt_blue="$e[1;34m"; lt_green="$e[1;32m"; lt_cyan="$e[1;36m";
lt_red="$e[1;31m"; magenta="$e[1;35m"; yellow="$e[1;33m"; white="$e[1;37m";
nc="$e[0m";
cheat_co=$white; err_co=$red; hi_co=$white; nc_co=$nc;
cmd_co=$white; from_co=$lt_green; mp_co=$magenta; num_co=$magenta;
dev_co=$magenta; head_co=$yellow; m_co=$lt_cyan; ok_co=$lt_green;
[ "$loco" ] || return
from_co=$brown
hi_co=$white
m_co=$nc_co
num_co=$white
warn_co=$yellow
}
bold() { vmsg 3 "$high_co$@"; }
warn() { vmsg 3 "$warn_co$@"; }
err() { vmsg 1 "$err_co$@" >&2; }
vmsg() {
local level="$1"
shift;
local msg
if [ "$1" = "-n" ]; then
shift;
msg="$m_co$@$nc_co"
vsay $level -n "$msg"
else
msg="$m_co$@$nc_co"
vsay $level "$msg"
msg="$msg\n"
fi
[ -n "$NO_LOG" ] || LOG="$LOG$msg"
return 0
}
vmsg_if() {
local level="$1"
shift
[ "$VERBOSE" -ge "$level" ] || return
vmsg $level "$@"
}
msg() { vmsg 5 "$@"; }
msg_nc() { vmsg 5 "$nc_co$@"; }
vmsg_nc() {
local level="$1"
shift;
vmsg $level "$nc_co$@"
}
heading() {
vmsg_nc 6 $tab
vmsg 3 "${head_co}$_Start_ $@"
}
vsay() {
local msg_level="$1"
shift;
[ "$msg_level" -le "$VERBOSE" ] && echo "$@"
return 0
}
plural() {
local n=$1 str="$2"
case "$n" in
1) local s= ies=y are=is;;
*) local s=s ies=ies are=are;;
esac
echo "$str" | sed -e "s/%s/$s/g" -e "s/%ies/$ies/g" -e "s/%are/$are/g" -e "s/%n/$n/g"
}
pmsg() { msg "$(plural "$@")"; }
vpmsg() {
local v=$1; shift
vmsg $v "$(plural "$@")"
}
main "$@"