在grub2 中最重要的三个命令就是linux/initrd/boot 命令,那个命令只有linux/initrd 是需要用户在grub.cfg中指定的
boot 命令系统会自动调用。
在grub2中通过GRUB_MOD_INIT来初始化一个模块,就想kernel中的module_init一样
GRUB_MOD_INIT (linux)
{
cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
N_("Load initrd."));
my_mod = mod;
}
这个模块中注册linux/initrd 命令的回调函数,也就是说在grub.cfg中调用linux命令的时候实际会call grub_cmd_linux
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
if (grub_file_read (file, kernel_addr, kernel_size)
< (grub_int64_t) kernel_size)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
goto fail;
}
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
linux_args = grub_malloc (cmdline_size);
if (!linux_args)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
linux_args + sizeof (LINUX_IMAGE) - 1,
cmdline_size);
if (grub_errno == GRUB_ERR_NONE)
{
grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
loaded = 1;
}
}
这个函数首先通过grub_file_read将kernel image read到kernel_addr,然后在通过grub_create_loader_cmdline 生成传递给kernel的cmdline
这些准备工作做完后,调用grub_loader_set 注册两个回调函数。
void
grub_loader_set (grub_err_t (*boot) (void),
grub_err_t (*unload) (void),
int flags)
{
if (grub_loader_loaded && grub_loader_unload_func)
grub_loader_unload_func ();
grub_loader_boot_func = boot;
grub_loader_unload_func = unload;
grub_loader_flags = flags;
grub_loader_loaded = 1;
}
这个函调被调用之后
grub_loader_boot_func = grub_linux_boot
grub_loader_unload_func = grub_linux_unload;
grub_loader_flags = 0;
这几个函数会在执行boot的命令的时候用到。
再来看看initrd 命令
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
initrd_size = grub_get_initrd_size (&initrd_ctx);
grub_dprintf ("linux", "Loading initrd\n");
initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
if (!initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}
if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
goto fail;
initrd_start = (grub_addr_t) initrd_mem;
initrd_end = initrd_start + initrd_size;
grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
(void *) initrd_start, initrd_size);
}
这个函数首先通过grub_efi_allocate_pages 申请initrd_mem,然后通过grub_initrd_load 把initrd 搬到initrd_mem,最后对
initrd_start/initrd_end 这两个全局变量赋值,这样执行boot命令的时候就知道在哪里找到initrd了。
boot 命令系统会自动调用。
在grub2中通过GRUB_MOD_INIT来初始化一个模块,就想kernel中的module_init一样
GRUB_MOD_INIT (linux)
{
cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
N_("Load initrd."));
my_mod = mod;
}
这个模块中注册linux/initrd 命令的回调函数,也就是说在grub.cfg中调用linux命令的时候实际会call grub_cmd_linux
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
if (grub_file_read (file, kernel_addr, kernel_size)
< (grub_int64_t) kernel_size)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
goto fail;
}
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
linux_args = grub_malloc (cmdline_size);
if (!linux_args)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
linux_args + sizeof (LINUX_IMAGE) - 1,
cmdline_size);
if (grub_errno == GRUB_ERR_NONE)
{
grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
loaded = 1;
}
}
这个函数首先通过grub_file_read将kernel image read到kernel_addr,然后在通过grub_create_loader_cmdline 生成传递给kernel的cmdline
这些准备工作做完后,调用grub_loader_set 注册两个回调函数。
void
grub_loader_set (grub_err_t (*boot) (void),
grub_err_t (*unload) (void),
int flags)
{
if (grub_loader_loaded && grub_loader_unload_func)
grub_loader_unload_func ();
grub_loader_boot_func = boot;
grub_loader_unload_func = unload;
grub_loader_flags = flags;
grub_loader_loaded = 1;
}
这个函调被调用之后
grub_loader_boot_func = grub_linux_boot
grub_loader_unload_func = grub_linux_unload;
grub_loader_flags = 0;
这几个函数会在执行boot的命令的时候用到。
再来看看initrd 命令
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
initrd_size = grub_get_initrd_size (&initrd_ctx);
grub_dprintf ("linux", "Loading initrd\n");
initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
if (!initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}
if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
goto fail;
initrd_start = (grub_addr_t) initrd_mem;
initrd_end = initrd_start + initrd_size;
grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
(void *) initrd_start, initrd_size);
}
这个函数首先通过grub_efi_allocate_pages 申请initrd_mem,然后通过grub_initrd_load 把initrd 搬到initrd_mem,最后对
initrd_start/initrd_end 这两个全局变量赋值,这样执行boot命令的时候就知道在哪里找到initrd了。
版权声明:本文为tiantao2012原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。