grub_err_t grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[])
{
struct linux_kernel_header lh;
struct linux_kernel_params *params;
file = grub_file_open (argv[0]); //打开linux文件
grub_file_read (file, &lh, sizeof (lh) //读取linux header
setup_sects = lh.setup_sects; //获取setup.bin占用的扇区
real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; //获取保护模式镜像大小
allocate_pages (prot_size)
=>grub_err_t allocate_pages (grub_size_t prot_size) //为 linux_kernel_params params 和 内核镜像申请内存
{
/* Make sure that each size is aligned to a page boundary. */
real_size = GRUB_LINUX_CL_END_OFFSET;
prot_size = page_align (prot_size);
mmap_size = find_mmap_size (); //确定e820内存结构数组大小
real_mode_pages = ((real_size + mmap_size + efi_mmap_size) >> 12);
prot_mode_pages = (prot_size >> 12);
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
real_mode_target,
(real_size + mmap_size
+ efi_mmap_size)); //实模式 linux_kernel_params params 结构体和e820申请内存
real_mode_mem = get_virtual_current_address (ch);
prot_mode_target = GRUB_LINUX_BZIMAGE_ADDR; //内核放在物理地址1MB的位置
grub_relocator_alloc_chunk_addr (relocator, &ch,
prot_mode_target, prot_size); //为保护模式内核申请内存
prot_mode_mem = get_virtual_current_address (ch);
/* 初始化linux_kernel_params params */
params = (struct linux_kernel_params *) real_mode_mem;
grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET);
grub_memcpy (¶ms->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
len = 0x400 - sizeof (lh);
grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) //读取协议
grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
if (grub_memcmp (argv[i], "mem=", 4) == 0) { //获取内存总大小
char *val = argv[i] + 4;
linux_mem_size = grub_strtoul (val, &val, 0);
int shift = 0;
switch (grub_tolower (val[0]))
{
case 'g':
shift += 10;
case 'm':
shift += 10;
case 'k':
shift += 10;
default:
break;
}
linux_mem_size <<= shift;
} else if (grub_memcmp (argv[i], "quiet", sizeof ("quiet") - 1) == 0)
{
params->loadflags |= GRUB_LINUX_FLAG_QUIET;
}
/* Create kernel command line. */
grub_memcpy ((char *)real_mode_mem + GRUB_LINUX_CL_OFFSET, LINUX_IMAGE,
sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
(char *)real_mode_mem + GRUB_LINUX_CL_OFFSET
+ sizeof (LINUX_IMAGE) - 1,
GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
- (sizeof (LINUX_IMAGE) - 1));
len = prot_size;
grub_file_read (file, prot_mode_mem, len) != len) //加载内核
}
}