grub2 boot kernel

grub/grub-core/kern/arm64/efi中的startup.s 是grub2的入口函数
FUNCTION(_start)
    /*
     *  EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0.
     */
    ldr    x2, efi_image_handle_val
    str    x0, [x2]
    ldr    x2, efi_system_table_val
    str    x1, [x2]
    ldr    x2, grub_main_val
    br    x2
grub_main_val:
    .quad    EXT_C(grub_main)
一般uefi->grub2的时候会把uefi中的efi_system_table_val传递过来,这样
grub2就可以通过uefi的efi_system_table_val来boot kernel
这个函数最后会调用grub_main_val,也就是grub_main。grub_main -> grub_load_normal_mode ();这样就又跳回uefi中boot kernel,如果失败就进入救援模式grub_rescue_run ()
我们先看正常的flow
static void
grub_load_normal_mode (void)
{
  /* Load the module.  */
  grub_dl_load ("normal");

  /* Print errors if any.  */
  grub_print_error ();
  grub_errno = 0;

  grub_command_execute ("normal", 0, 0);
}
grub_load_normal_mode 这个函数首先会通过grub_dl_load ("normal");load normal这个命令
然后调用grub_command_execute来执行,即grub2是命令驱动型,这点和uboot有点类似.
这个命令的注册在grub-core/normal中实现
GRUB_MOD_FINI(normal)
{
  grub_context_fini ();
  grub_script_fini ();
  grub_menu_fini ();
  grub_normal_auth_fini ();

  grub_xputs = grub_xputs_saved;

  grub_set_history (0);
  grub_register_variable_hook ("pager", 0, 0);
  grub_fs_autoload_hook = 0;
  grub_unregister_command (cmd_clear);
}
通过GRUB_MOD_FINI(normal)来注册normal命令
 grub_register_command ("normal", grub_cmd_normal, 0, N_("Enter normal mode."));
normal命令的回调函数是grub_cmd_normal。
static grub_err_t
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
         int argc, char *argv[])
{
  if (argc == 0)
    {
      /* Guess the config filename. It is necessary to make CONFIG static,
     so that it won't get broken by longjmp.  */
      char *config;
      const char *prefix;

      prefix = grub_env_get ("prefix");
      if (prefix)
        {
          grub_size_t config_len;
          config_len = grub_strlen (prefix) +
                      sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
          config = grub_malloc (config_len);

          if (! config)
            goto quit;

          grub_snprintf (config, config_len, "%s/grub.cfg", prefix);

          if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
            grub_net_search_configfile (config);

      grub_enter_normal_mode (config);
      grub_free (config);
    }
      else
    grub_enter_normal_mode (0);
    }
  else
    grub_enter_normal_mode (argv[0]);

quit:
  return 0;
}
从这个函数中可以看到主要是parse grub.cfg 后,将grub.cfg传入grub_enter_normal_mode
void
grub_enter_normal_mode (const char *config)
{
  grub_boot_time ("Entering normal mode");
  nested_level++;
  grub_normal_execute (config, 0, 0);
  grub_boot_time ("Entering shell");
  grub_cmdline_run (0, 1);
  nested_level--;
  if (grub_normal_exit_level)
    grub_normal_exit_level--;
  grub_boot_time ("Exiting normal mode");
}
grub_enter_normal_mode->grub_normal_execute来显示grub的启动菜单
void
grub_normal_execute (const char *config, int nested, int batch)
{
   grub_show_menu (menu, nested, 0);
}

grub_show_menu->show_menu
show_menu (grub_menu_t menu, int nested, int autobooted)
{
  while (1)
    {
      int boot_entry;
      grub_menu_entry_t e;
      int auto_boot;

      boot_entry = run_menu (menu, nested, &auto_boot);
      if (boot_entry < 0)
    break;

      e = grub_menu_get_entry (menu, boot_entry);
      if (! e)
    continue; /* Menu is empty.  */

      grub_cls ();

      if (auto_boot)
    grub_menu_execute_with_fallback (menu, e, autobooted,
                     &execution_callback, 0);
      else
    grub_menu_execute_entry (e, 0);
      if (autobooted)
    break;
    }

  return GRUB_ERR_NONE;
}
show_menu 首先通过run_menu显示menu,然后通过grub_menu_get_entry得到用户选择的开机启动项。最后通过grub_menu_execute_entry执行用户选择的启动项
在grub.cfg中一定要定义linux命令,这个命令是在grub中定义的linux 命令,执行这个
menuentry "test" --id test {
    linux /1122/Image

}
linux命令后,grub就会通过ueif的boot service将kernel image load到dram中,然后在grub_menu_execute_entry 中执行boot 命令,就返回到uefi中,再从uefi->kernelstub->kernel

grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot)
{
 
  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
    /* Implicit execution of boot, only if something is loaded.  */
    grub_command_execute ("boot", 0, 0);
 }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值