grub2-efi编译
1. grub2版本2.02~beta2
2. 问题现象
在efi的环境上,现在编译出来的grub2不能支持,表现在报错:
/usr/local/xx/grub-install:1:错误/usr/local/xx/lib/grub/x86_64-efi/modinfo.sh doesn’t exit.Please specify --target or --directory
3. 问题分析
报错的部分来自于grub_install_get_target接口。是在grub-install执行的时候报错退出。
grub-install判断平台的逻辑如下:
static const char *
get_default_platform (void)
{
#ifdef __powerpc__
return "powerpc-ieee1275";
#elif defined (__sparc__) || defined (__sparc64__)
return "sparc64-ieee1275";
#elif defined (__MIPSEL__)
return "mipsel-loongson";
#elif defined (__MIPSEB__)
return "mips-arc";
#elif defined (__ia64__)
return "ia64-efi";
#elif defined (__arm__)
return "arm-uboot";
#elif defined (__aarch64__)
return "arm64-efi";
#elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__)
return grub_install_get_default_x86_platform ();
#else
return NULL;
#endif
}
const char *
grub_install_get_default_x86_platform (void)
{
/*
On Linux, we need the efivars kernel modules.
If no EFI is available this module just does nothing
besides a small hello and if we detect efi we'll load it
anyway later. So it should be safe to
try to load it here.
*/
grub_util_exec_redirect_all ((const char * []){ "modprobe", "efivars", NULL },
NULL, NULL, "/dev/null");
grub_util_info ("Looking for /sys/firmware/efi ..");
if (is_not_empty_directory ("/sys/firmware/efi"))
{
grub_util_info ("...found");
if (is_64_kernel ())
return "x86_64-efi";
else
return "i386-efi";
}
grub_util_info ("... not found. Looking for /proc/device-tree ..");
if (is_not_empty_directory ("/proc/device-tree"))
{
grub_util_info ("...found");
return "i386-ieee1275";
}
grub_util_info ("... not found");
return "i386-pc";
}
而返回return "x86_64-efi"的分支,条件是/sys/firmware/efi这个目录存在。经搜索阅读,确认这个是uefi的环境会有的设置,是硬件相关的操作。
4. 问题解决
解决方案1:
出发点:考虑是否是因为实际运行环境和编译环境的不同(编译环境没有/sys/firmware/efi这个目录,因为不是uefi启动),使用相同的环境,configure的时候不做任何特殊操作,是否能够编译出efi版本的grub2
操作步骤:
- 先使用实际运行环境的镜像,安装一台带有uefi启动设置的虚拟机,这个设置在vmware的高级设置里有。
- 沿用之前的configure配置进行grub2的编译:
./configure --disable-werror --prefix=/usr/local/xxx
编译完成后,看install的目录下生成的目录结构。
root@linx:~/Rocky80/grub2_2.02~beta2-22/BUILD# ll /usr/local/xxx/lib/grub/
总用量 44
drwxr-sr-x 2 root staff 20480 8月 27 10:43 i386-pc
并没有x86_64-efi子目录,这个方案不可以。
解决方案2:
出发点:经过方案1的尝试,考虑grub2的不同平台的编译,应该是需要有什么其他的操作,比如configure,比如需要有什么指明的方式。
经过科学上网(baidu搜出来的东西真的很坑)。
操作步骤:
- 修改configure的参数如下:
./configure --with-platform=efi --target=x86_64 --disable-werror --prefix=/usr/local/xxx
编译后查看生成的目录结构:
root@linx:~/Rocky80/grub2_2.02~beta2-22/BUILD# ll /usr/local/xxx/lib/grub/
总用量 44
drwxr-sr-x 2 root staff 20480 8月 27 10:43 i386-pc
drwxr-sr-x 2 root staff 20480 8月 27 15:15 x86_64-efi
可以生成需要平台的grub2需要的mod文件。
综上,问题解决。
总结
在选择解决方案上,方案1是个弯路,按照通用的编译原理,如果一个源码支持多个平台,不应该是通过“在不同平台的环境上进行编译来获得不同的产品”,这样的思路成本太高,而应该是“一个编译环境,通过不同的编译参数来进行”,这样才能一份代码,多种产品编译支持。