接上一篇,最后调用的函数是cmain(),这个函数在stage2.c中定义。
在cmain()中主要做以下事情:
- 寻找启动菜单配置文件。
- 如找不到则尝试寻找程序中的内置菜单。
- 如果找到则尝试解析并执行该启动菜单配置中的脚本。
- 如两者都没有找到,则进入命令行模式。
主要函数如下
//void
//reset (void);
static int config_len, menu_len, num_entries;
/*
menu_entries数组存放"title"命令的内容
config_entries数组既存放在menu中的命令也存放title下的命令,它们之间以两个NULL分割
如:
timeout xxx(NULL)default /default(NULL)(NULL)
[title 0]命令1(NULL)命令2(NULL)(NULL)
[title 1]命令1(NULL)命令2(NULL)(NULL)
*/
static char *config_entries, *menu_entries, *cur_entry;
static void
reset(void)
{
count_lines = -1;
config_len = 0;
menu_len = 0;
num_entries = 0;
config_entries = (char *)mbi.drives_addr + mbi.drives_length;
cur_entry = config_entries;
menu_entries = (char *)MENU_BUF;
init_config();
}
/* 从cmdline中找到下一个词语并返回它的指针,如果参数after_equal
不等于零, 则字符"="被假设为一个空格看待. 注意:此假设是为了向后兼容。*/
extern char * skip_to(int after_equal, char *cmdline);
/* This is the starting function in C. */
void
cmain(void)
{
char *kill_buf = (char *)KILL_BUF; /* #define KILL_BUF (CMDLINE_BUF + CMDLINE_BUFLEN) */
/* grub_setjmp见setjmp.S,这个函数保存栈的内容到restart_env以便将来重启Stage 2的时候用到。 */
grub_setjmp(restart_env);
/* Initialize the kill buffer. */
*kill_buf = 0;
debug = 1;
/* Never return. */
for (;;)
{
extern int use_config_file;
int is_opened, is_preset;
reset();
/* Here load the configuration file. */
//#ifdef GRUB_UTIL
/* 如果启用了配置文件则加载它(在启动过程中如果按下了C键会跳过配置文件的加载进入命令行模式,详见asm.S)*/
if (use_config_file)
//#endif /* GRUB_UTIL */
{
/* 存放默认文件名"/boot/grub/default"的地方.
#define DEFAULT_FILE_BUF (PASSWORD_BUF + PASSWORD_BUFLEN) */
char *default_file = (char *)DEFAULT_FILE_BUF;
int i;
/* Get a saved default entry if possible. */
saved_entryno = 0;
/* 当config_file不为0时将读取该处的字符串,否则读取0x0800处。见asm.S*/
if (*config_file)
{
*default_file = 0; /* initialise default_file */
grub_strncat(default_file, config_file, DEFAULT_FILE_BUFLEN);
/* 截取字符串,丢弃最后一个'/'之后的内容*/
for (i = grub_strlen(default_file); i >= 0; i--)
if (default_file[i] == '/')
{
//i++;
break;
}
default_file[++i] = 0;
/* 然后 + "default" */
grub_strncat(default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
if (debug)
grub_printf("Open %s ... ", default_file);
// i=grub_open (default_file);
// printf("default_file ok=%s\n", default_file);
// for (;;);
/* 打开文件读取十个字节,然后将之从字符串转为数字,保存到saved_entryno。 */
if (grub_open(default_file)) /* grub_open见disk_io.c */
{
char buf[10]; /* This is good enough. */
char *p = buf;
int len;
if (debug)
grub_printf("Read file: ", default_file);
len = grub_read(buf, sizeof(buf));