grub中的程序像kenrel一样可以是buildin的,也可以build成模块。在需要时候通过insmod 加载进来
例如下面这个grub.cfg 中的code
menuentry "Microsoft Windows 8.1" {
echo "Loading Microsoft Windows 8.1..."
insmod part_gpt
insmod fat
insmod search_fs_uuid
insmod chain
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}
这些新加载的模块是需要grub 在memroy中找一段位置来加载,那因此在grub初始化的时候会提供这段加载模块的memory
具体源码在grub-core/kern/efi/mm.c 中
static void
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
grub_efi_uintn_t desc_size,
grub_efi_memory_descriptor_t *memory_map_end,
grub_efi_uint64_t required_pages)
{
grub_efi_memory_descriptor_t *desc;
for (desc = memory_map;
desc < memory_map_end;
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{
grub_efi_uint64_t pages;
grub_efi_physical_address_t start;
void *addr;
start = desc->physical_start;
pages = desc->num_pages;
if (pages > required_pages)
{
start += PAGES_TO_BYTES (pages - required_pages);
pages = required_pages;
}
//通过bootservice向bios申请memory
addr = grub_efi_allocate_pages (start, pages);
if (! addr)
grub_fatal ("cannot allocate conventional memory %p with %u pages",
(void *) ((grub_addr_t) start),
(unsigned) pages);
//将memory通过grub_mm_init_region 添加到grub_mm_base 这个list中
grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
required_pages -= pages;
if (required_pages == 0)
break;
}
if (required_pages > 0)
grub_fatal ("too little memory");
}
这样当加载模块时会通过grub_memalign来申请memory。从下面的源码中可以看到grub_memalign 会向grub_mm_base 这个list中查找符合的memory
void *
grub_memalign (grub_size_t align, grub_size_t size)
{
grub_mm_region_t r;
grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
int count = 0;
if (!grub_mm_base)
goto fail;
if (size > ~(grub_size_t) align)
goto fail;
/* We currently assume at least a 32-bit grub_size_t,
so limiting allocations to <adress space size> - 1MiB
in name of sanity is beneficial. */
if ((size + align) > ~(grub_size_t) 0x100000)
goto fail;
align = (align >> GRUB_MM_ALIGN_LOG2);
if (align == 0)
align = 1;
again:
for (r = grub_mm_base; r; r = r->next)
{
void *p;
p = grub_real_malloc (&(r->first), n, align);
if (p)
return p;
}
/* If failed, increase free memory somehow. */
switch (count)
{
case 0:
/* Invalidate disk caches. */
grub_disk_cache_invalidate_all ();
count++;
goto again;
#if 0
case 1:
/* Unload unneeded modules. */
grub_dl_unload_unneeded ();
count++;
goto again;
#endif
default:
break;
}
fail:
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
return 0;
}
grub中为加载模块申请memory的初始化
最新推荐文章于 2024-07-08 16:47:21 发布