在normal命令的回调函数grub_cmd_normal 中会执行grub.cfg中定义的命令
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;
}
grub_cmd_normal 首先找到prefix,也就是grub.cfg存放的路径,如果prefix中含有tftp则调用grub_net_search_configfile 在网络上找到grub.cfg
然后会调用grub_normal_execute 来一行一行执行grub.cfg中定义的命令
grub_normal_execute (const char *config, int nested, int batch)
{
grub_menu_t menu = 0;
const char *prefix;
if (! nested)
{
prefix = grub_env_get ("prefix");
read_lists (prefix);
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
}
grub_boot_time ("Executing config file");
if (config)
{
menu = read_config_file (config);
/* Ignore any error. */
grub_errno = GRUB_ERR_NONE;
}
grub_boot_time ("Executed config file");
if (! batch)
{
if (menu && menu->size)
{
grub_boot_time ("Entering menu");
grub_show_menu (menu, nested, 0);
if (nested)
grub_normal_free_menu (menu);
}
}
}
其中grub_normal_execute 又调用read_config_file 来读取menu信息,也就是执行grub.cfg中的命令,注意在调用grub_normal_execute的时候第三个参数batch==0,因此会调用grub_show_menu 来显示grub菜单.
其中在read_config_file 函数中会逐行执行grub.cfg中的命令,其核心代码如下:
while (1)
{
char *line;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
if ((read_config_file_getline (&line, 0, file)) || (! line))
break;
grub_normal_parse_line (line, read_config_file_getline, file);
grub_free (line);
}
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;
}
grub_cmd_normal 首先找到prefix,也就是grub.cfg存放的路径,如果prefix中含有tftp则调用grub_net_search_configfile 在网络上找到grub.cfg
然后会调用grub_normal_execute 来一行一行执行grub.cfg中定义的命令
grub_normal_execute (const char *config, int nested, int batch)
{
grub_menu_t menu = 0;
const char *prefix;
if (! nested)
{
prefix = grub_env_get ("prefix");
read_lists (prefix);
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
}
grub_boot_time ("Executing config file");
if (config)
{
menu = read_config_file (config);
/* Ignore any error. */
grub_errno = GRUB_ERR_NONE;
}
grub_boot_time ("Executed config file");
if (! batch)
{
if (menu && menu->size)
{
grub_boot_time ("Entering menu");
grub_show_menu (menu, nested, 0);
if (nested)
grub_normal_free_menu (menu);
}
}
}
其中grub_normal_execute 又调用read_config_file 来读取menu信息,也就是执行grub.cfg中的命令,注意在调用grub_normal_execute的时候第三个参数batch==0,因此会调用grub_show_menu 来显示grub菜单.
其中在read_config_file 函数中会逐行执行grub.cfg中的命令,其核心代码如下:
while (1)
{
char *line;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
if ((read_config_file_getline (&line, 0, file)) || (! line))
break;
grub_normal_parse_line (line, read_config_file_getline, file);
grub_free (line);
}