Using Grub 2.02 on UEFI system with AMD64 architecture. I'd like to change grub's timeout counter from 1 second intervals to 1/10th second or 1/100th second intervals. The reason is to make gfxmenu
circular progress countdown less "choppy". Boot GIF below shows 5 second count down in circular 1 second "chunks":
After successful source code change and recompile, /etc/default/grub
would be changed as follows:
GRUB_TIMEOUT=25
.GRUB_TIMEOUT=250
.I've downloaded the source as described here: how to build grub2 bootloader from it's source and test it with qemu emulator and spent time browsing source files. However there are 477k lines to search:
~/src/grub-2.02$ wc -l **/*
20 asm-tests/arm.S
18 asm-tests/i386-pc.S
4 asm-tests/i386.S
11 asm-tests/mips.S
8 asm-tests/powerpc.S
(... SNIP ...)
115 util/spkmodem-recv.c
477316 total
I've done many bash projects in Ask Ubuntu but this will be my first C/Assembler Linux project. As a "newbie" my thoughts are:
Please note only the first question is relevant. The other questions are for answers where the author chooses be more detailed.
The variable GRUB_TIMEOUT
is evaluated in util/grub.d/00_header.in
.
if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then
cat <<EOF
if cmostest $GRUB_BUTTON_CMOS_ADDRESS ; then
EOF
make_timeout "${GRUB_HIDDEN_TIMEOUT_BUTTON}" "${GRUB_TIMEOUT_BUTTON}" "${GRUB_TIMEOUT_STYLE_BUTTON}"
echo else
make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}" "${GRUB_TIMEOUT_STYLE}"
echo fi
else
make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}" "${GRUB_TIMEOUT_STYLE}"
fi
Note that this is a script that generates a script which is why it looks rather weird. make_timeout
looks like this (ibid.):
make_timeout ()
{
if [ "x${3}" != "x" ] ; then
timeout="${2}"
style="${3}"
elif [ "x${1}" != "x" ] && [ "x${1}" != "x0" ] ; then
# Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme.
timeout="${1}"
if [ "x${2}" != "x0" ] ; then
grub_warn "$(gettext "Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.")"
fi
if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then
style="hidden"
verbose=
else
style="countdown"
verbose=" --verbose"
fi
else
# No hidden timeout, so treat as GRUB_TIMEOUT_STYLE=menu
timeout="${2}"
style="menu"
fi
cat << EOF
if [ x\$feature_timeout_style = xy ] ; then
set timeout_style=${style}
set timeout=${timeout}
EOF
if [ "x${style}" = "xmenu" ] ; then
cat << EOF
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
set timeout=${timeout}
EOF
else
cat << EOF
# Fallback hidden-timeout code in case the timeout_style feature is
# unavailable.
elif sleep${verbose} --interruptible ${timeout} ; then
set timeout=0
EOF
fi
cat << EOF
fi
EOF
}
As you can see, it just calls sleep
with some options at the end. This command is defined in grub-core/commands/sleep.c
. While the sleep
command can only sleep in increments of whole seconds, the underlying function grub_millisleep
can do better.
It should be easy to patch this function by changing all the grub_millisleep(1000)
calls to grub_millisleep(100)
, but keep in mind that this breaks all uses of sleep
. A cleaner option is to add a new option to sleep
so the behaviour can be selected on a case-by-case basis.
Thanks to the help of the accepted answer I was able to achieve the goal using a different method. After successful Grub 2.02 source code change and recompile, /etc/default/grub
was changed to a 3.5 second countdown with GRUB_TIMEOUT=35
.
Notice how the circular progress is now smooth with no "chunks":
The code to change in:
/grub-2.02/grub-core/normal/menu.c
Line 546:
/* Check whether a second has elapsed since the last tick. If so, adjust
the timer and return 1; otherwise, return 0. */
static int
has_second_elapsed (grub_uint64_t *saved_time)
{
grub_uint64_t current_time;
current_time = grub_get_time_ms ();
/* July 14, 2018 Use deciseconds - change 1000 to 100 */
if (current_time - *saved_time >= 100)
{
*saved_time = current_time;
return 1;
}
else
return 0;
}
Change the line:
if (current_time - *saved_time >= 1000)
to:
if (current_time - *saved_time >= 100)
grub 2.02
Before following instructions on Grub's website:
sudo apt install bison
sudo apt install flex
Then follow grub's website instructions:
cd grub-2.02
./configure
Run next command on Grub's website:
make install
Files are created in /usr/local/bin
(surprise!!!) along with .../grub-2.02
directory which is to be expected.
I ended up cloning source to VM (Lubuntu 16.04) and recompiling there. Using the newly compiled grub-install
mucked things up and I had to use sudo apt install grub2
to get fresh install. Then manually copying newly compiled files to /boot/grub/i386-pc
My terminal-box got all skewed up so I'll have to create a new grub background image. In the image below I changed GRUB_TIMEOUT=35
for 3.5 second countdown.
Figured out to one parameter to use in order to get X86, EFI support:
./configure –with-platform=efi
*******************************************************
GRUB2 will be compiled with following components:
Platform: x86_64-efi
With devmapper support: No (need libdevmapper header)
With memory debugging: No
With disk cache statistics: No
With boot time statistics: No
efiemu runtime: No (not available on efi)
grub-mkfont: No (need freetype2 library)
grub-mount: No (need FUSE library)
starfield theme: No (No build-time grub-mkfont)
With libzfs support: No (need zfs library)
Build-time grub-mkfont: No (need freetype2 library)
Without unifont (no build-time grub-mkfont)
Without liblzma (no support for XZ-compressed mips images) (need lzma library)
*******************************************************
However, after make install
there is an error:
Making install in grub-core
make[2]: Entering directory '/home/rick/src/grub-2.02/grub-core'
gcc -E -DHAVE_CONFIG_H -Wall -W -DGRUB_MACHINE_EFI=1 -DGRUB_MACHINE=X86_64_EFI -m64 -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/5/include -I../include -I../include -DGRUB_FILE=\"symlist.h\" -I. -I. -I.. -I.. -I../include -I../include -I../grub-core/lib/libgcrypt-grub/src/ -DGRUB_KERNEL=1 -D_FILE_OFFSET_BITS=64 -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1)
symlist.h:25:44: fatal error: ../include/grub/machine/kernel.h: No such file or directory
compilation terminated.
Makefile:42544: recipe for target 'symlist.c' failed
make[2]: *** [symlist.c] Error 1
make[2]: Leaving directory '/home/rick/src/grub-2.02/grub-core'
Makefile:10904: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: Leaving directory '/home/rick/src/grub-2.02'
Makefile:11927: recipe for target 'install' failed
make: *** [install] Error 2
I filed a bug report with Grub folks (July 2018) but haven't heard a thing back. The next step for EFI system is to download the source code on fresh install using Ubuntu's repositories instead of Grub's website instructions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With