在 Grub 2.02 源代码中查找倒数计时器
Finding countdown timer in Grub 2.02 source code
将 Grub 的超时更改为 1/10 或 1/100 秒间隔
在 AMD64 架构的 UEFI 系统上使用 Grub 2.02。我想将 grub 的超时计数器从 1 秒间隔更改为 1/10 秒或 1/100 秒间隔。原因是为了让 gfxmenu
循环进度倒计时不那么“断断续续”。下面的启动 GIF 以循环 1 秒“块”的形式显示 5 秒倒计时:
修改源代码并重新编译成功后,/etc/default/grub
会变成如下:
- 如果间隔为 1/10 秒,则 2.5 秒倒计时将为
GRUB_TIMEOUT=25
。
- 如果间隔为 1/100 秒,则 2.5 秒倒计时将为
GRUB_TIMEOUT=250
。
Grub 2.02 源代码为 1/2 百万行
我已按照此处所述下载源代码: 并花时间浏览源文件。但是有 477k 行要搜索:
~/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
我在 Ask Ubuntu 中完成了很多 bash 项目,但这将是我的第一个 C/Assembler Linux 项目.作为一个“新手”,我的想法是:
- 哪个文件包含倒数计时器源代码?
- 如何将间隔更改为 1/10 秒或 1/100 秒?
- 将源代码放在我的主目录下是一种常规方法吗?
- 任何有关在 Virtualbox 中编译和测试的提示都会有所帮助。
请注意只有第一个问题是相关的。其他问题供作者选择更详细的答案。
变量 GRUB_TIMEOUT
在 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
请注意,这是一个生成脚本的脚本,这就是为什么它看起来很奇怪的原因。 make_timeout
看起来像这样(同上):
make_timeout ()
{
if [ "x" != "x" ] ; then
timeout=""
style=""
elif [ "x" != "x" ] && [ "x" != "x0" ] ; then
# Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme.
timeout=""
if [ "x" != "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=""
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
}
如您所见,它只是在最后调用 sleep
并带有一些选项。此命令在 grub-core/commands/sleep.c
中定义。虽然 sleep
命令只能以整秒为增量休眠,但底层函数 grub_millisleep
可以做得更好。
通过将所有 grub_millisleep(1000)
调用更改为 grub_millisleep(100)
来修补此函数应该很容易,但请记住,这会破坏 sleep
的所有使用。一个更清晰的选项是向 sleep
添加一个新选项,以便可以根据具体情况选择行为。
感谢接受的答案的帮助,我能够使用不同的方法实现目标。成功更改 Grub 2.02 源代码并重新编译后,/etc/default/grub
更改为 3.5 秒倒计时 GRUB_TIMEOUT=35
。
注意循环进度现在是如何平滑的,没有“块”:
要更改的代码:
/grub-2.02/grub-core/normal/menu.c
第 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;
}
换行:
if (current_time - *saved_time >= 1000)
至:
if (current_time - *saved_time >= 100)
Voila! 只需更改一行代码。加上两个注释行,以达到良好的效果。
如何编译grub 2.02
在遵循 Grub 的 website 说明之前:
sudo apt install bison
sudo apt install flex
然后按照 grub 的网站说明进行操作:
cd grub-2.02
./configure
运行 Grub 网站上的下一个命令:
make install
文件在 /usr/local/bin
中创建(惊喜!!!)以及预期的 .../grub-2.02
目录。
编译 grub 的其他问题
我最终将源代码克隆到 VM (Lubuntu 16.04) 并在那里重新编译。使用新编译的 grub-install
搞砸了,我不得不使用 sudo apt install grub2
进行全新安装。然后手动复制新编译的文件到/boot/grub/i386-pc
我的接线盒歪斜了,所以我必须创建一个新的 grub 背景图像。在下图中,我将 GRUB_TIMEOUT=35
更改为 3.5 秒倒计时。
2018 年 7 月 16 日更新
想出一个参数来获得 X86,EFI 支持:
./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)
*******************************************************
但是make install
之后出现错误:
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
我向 Grub 人员提交了错误报告(2018 年 7 月),但没有收到任何回复。 EFI 系统的下一步是使用 Ubuntu 的存储库而不是 Grub 的网站说明在全新安装时下载源代码。
将 Grub 的超时更改为 1/10 或 1/100 秒间隔
在 AMD64 架构的 UEFI 系统上使用 Grub 2.02。我想将 grub 的超时计数器从 1 秒间隔更改为 1/10 秒或 1/100 秒间隔。原因是为了让 gfxmenu
循环进度倒计时不那么“断断续续”。下面的启动 GIF 以循环 1 秒“块”的形式显示 5 秒倒计时:
修改源代码并重新编译成功后,/etc/default/grub
会变成如下:
- 如果间隔为 1/10 秒,则 2.5 秒倒计时将为
GRUB_TIMEOUT=25
。 - 如果间隔为 1/100 秒,则 2.5 秒倒计时将为
GRUB_TIMEOUT=250
。
Grub 2.02 源代码为 1/2 百万行
我已按照此处所述下载源代码:
~/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
我在 Ask Ubuntu 中完成了很多 bash 项目,但这将是我的第一个 C/Assembler Linux 项目.作为一个“新手”,我的想法是:
- 哪个文件包含倒数计时器源代码?
- 如何将间隔更改为 1/10 秒或 1/100 秒?
- 将源代码放在我的主目录下是一种常规方法吗?
- 任何有关在 Virtualbox 中编译和测试的提示都会有所帮助。
请注意只有第一个问题是相关的。其他问题供作者选择更详细的答案。
变量 GRUB_TIMEOUT
在 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
请注意,这是一个生成脚本的脚本,这就是为什么它看起来很奇怪的原因。 make_timeout
看起来像这样(同上):
make_timeout ()
{
if [ "x" != "x" ] ; then
timeout=""
style=""
elif [ "x" != "x" ] && [ "x" != "x0" ] ; then
# Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme.
timeout=""
if [ "x" != "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=""
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
}
如您所见,它只是在最后调用 sleep
并带有一些选项。此命令在 grub-core/commands/sleep.c
中定义。虽然 sleep
命令只能以整秒为增量休眠,但底层函数 grub_millisleep
可以做得更好。
通过将所有 grub_millisleep(1000)
调用更改为 grub_millisleep(100)
来修补此函数应该很容易,但请记住,这会破坏 sleep
的所有使用。一个更清晰的选项是向 sleep
添加一个新选项,以便可以根据具体情况选择行为。
感谢接受的答案的帮助,我能够使用不同的方法实现目标。成功更改 Grub 2.02 源代码并重新编译后,/etc/default/grub
更改为 3.5 秒倒计时 GRUB_TIMEOUT=35
。
注意循环进度现在是如何平滑的,没有“块”:
要更改的代码:
/grub-2.02/grub-core/normal/menu.c
第 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;
}
换行:
if (current_time - *saved_time >= 1000)
至:
if (current_time - *saved_time >= 100)
Voila! 只需更改一行代码。加上两个注释行,以达到良好的效果。
如何编译grub 2.02
在遵循 Grub 的 website 说明之前:
sudo apt install bison
sudo apt install flex
然后按照 grub 的网站说明进行操作:
cd grub-2.02
./configure
运行 Grub 网站上的下一个命令:
make install
文件在 /usr/local/bin
中创建(惊喜!!!)以及预期的 .../grub-2.02
目录。
编译 grub 的其他问题
我最终将源代码克隆到 VM (Lubuntu 16.04) 并在那里重新编译。使用新编译的 grub-install
搞砸了,我不得不使用 sudo apt install grub2
进行全新安装。然后手动复制新编译的文件到/boot/grub/i386-pc
我的接线盒歪斜了,所以我必须创建一个新的 grub 背景图像。在下图中,我将 GRUB_TIMEOUT=35
更改为 3.5 秒倒计时。
2018 年 7 月 16 日更新
想出一个参数来获得 X86,EFI 支持:
./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)
*******************************************************
但是make install
之后出现错误:
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
我向 Grub 人员提交了错误报告(2018 年 7 月),但没有收到任何回复。 EFI 系统的下一步是使用 Ubuntu 的存储库而不是 Grub 的网站说明在全新安装时下载源代码。