GRUB's DSL (Domain-Specific Language) is fairly extensive, and capable of doing some interesting things. One thing I haven't found is a way to capture the output of a command or feed it back into another. I described this problem to a friend who said "aren't pipes the foundation of Unix?" Yes, they are. So that's disappointing.
If you're reading this, you should familiarize yourself with my previous posts about GRUB: The GRUB Command Line, The GRUB 'grubenv' Variable (although that isn't used here), and particularly GRUB - Pseudo-Graphical Mode and Fonts.
Understand that what I'm doing is writing scripts in a language nobody bothers to script (aside from building menu systems), so I have very few examples to work from ... The stuff I've created may be a bit rough around the edges.
# grub.cfg
export pager=1
loadfont $prefix/fonts/terminus20.pf2
set gfxmode=1920x1200,1920x1080,1280x800,1366x768,1280x1024,1024x768,800x600,640x480,auto
insmod all_video
insmod gfxterm
terminal_output gfxterm
function_folder='(hd0,msdos1)/boot/grub/grubbits'
for func in chfont chres colours cpuinfo dell memtest ; do
source ${function_folder}/${func}
done
We're already seeing where feeding the output of one command into the input of another would be a huge help: I want to source all files in the ${function_folder} folder, but I have to name them individually instead of using a Bash expansion like *. Each of the files in that folder contains a function with the same name as the file: here they are.
The videoinfo
command (not available at the Fedora GRUB HD command line, but available everywhere else, including USB sticks made by Fedora) will show you what resolutions are available on your monitor. You can change to one of the other named resolutions:
function chres {
if [ ${1}x = x ]
then
echo "Please supply a resolution (ie. '800x600') from the"
echo "output of the 'videoinfo' command."
exit 1
else
set gfxmode=${1} # load the new resolution
terminal_output console # toggle the console to activate the new resolution
terminal_output gfxterm
fi
}
If you have alternate .pf2 fonts (see my blog entry on making them), you can change to them with this command (this assumes they're stored in the boot/grub/fonts/ folder):
function _chfont_help {
echo "Usage:"
echo " chfont <fontname>"
echo "Please supply a font name (without the .pf2 extension) from the"
echo "${prefix}/fonts/ directory."
}
function chfont {
newfont=${prefix}/fonts/${1}.pf2
if [ ${2}x != x ]
then
_chfont_help
elif [ ${1}x = x ]
then
_chfont_help
elif ! [ -f ${newfont} ]
then
echo "'${newfont}' doesn't appear to exist."
_chfont_help
else
loadfont ${newfont} # load the named font
terminal_output console # toggle the console to activate the new font
terminal_output gfxterm
fi
}
Apparently pretty colours has been a priority for the GRUB community: they're easy to use and there are quite a few (well - by command line standards). Note that colour availability varies by platform: I use i386 and amd64, and colours are well supported there.
# This file echoes a bunch of color codes to the terminal to demonstrate
# what's available.
function colours {
for bg in 'black' 'blue' 'green' 'cyan' 'red' 'magenta' 'brown' \
'light-gray' 'dark-gray' 'light-blue' 'light-green' \
'light-cyan' 'light-red' 'light-magenta' 'yellow' 'white'
do
color_normal=light-gray/black # reset to readable
echo -n "$bg bg: "
for fg in 'black' 'blue' 'green' 'cyan' 'red' 'magenta' 'brown' \
'light-gray' 'dark-gray' 'light-blue' 'light-green' \
'light-cyan' 'light-red' 'light-magenta' 'yellow' 'white'
do
color_normal=${fg}/${bg}
echo -n "${fg} "
done
echo ""
done
color_normal=light-gray/black # reset to readable
echo ""
}
GRUB has rudimentary knowledge of the CPU it's running on:
function cpuinfo {
# only able to determine: 32/64 bit, and is it PAE
echo "GRUB's ability to analyse processors is limited, we can only tell you:"
if cpuid -p; then
pae_assessment="PAE"
else
pae_assessment="NO PAE"
fi
if cpuid -l; then
echo "64-bit processor, $pae_assessment"
else
echo "32-bit processor, $pae_assessment"
fi
}
I have an old Dell laptop that has a specific and slightly problematic video card. It was common enough that people wrote a lot of code to support it under Linux (and GRUB). Don't try running this unless you know you have a 915 and it supports this specific resolution, although it could act as an example to access a different 915-supported resolution:
function dell {
# override video mode 30 (usually 640x480x8) with a res for the
# Dell Inspiron 700m:
# ( http://915resolution.mango-lang.org/ )
915resolution 30 1280 800
set gfxmode=1280x800,1024x768,800x600,640x480,auto
terminal_output console ; terminal_output gfxterm
}
GRUB is mostly used as a menu system, but you can just as well boot from the command line. This requires the memtest86+-5.01.bin binary in the isos subfolder of boot/grub/. Most ISOs or kernels are A) bigger, and B) require more settings to boot properly: I chose this as the simplest possible test (it works).
function memtest {
memtestbin=${_prefix}/isos/memtest86+-5.01.bin
if [ -f ${memtestbin} ]
then
linux16 ${memtestbin}
boot
fi
}
Note the addition of the boot
keyword to start the boot process: it's assumed in menu entries in GRUB, but is required if you're writing scripts like this.
Bibliography
The reference manual you need to read: https://www.gnu.org/software/grub/manual/grub/html_node/ (very short on examples).