Skip to the content.

QEMU 如何加载 Linux kernel image

QEMU 提供了 -kernel 参数来指定 Guest 的内核,这对于调试内核非常的方便,现在说明一下 -kernel 选项是如何实现的:

阅读本文需要大致了解 fw_cfg 的知识

x86 + seabios 下如何工作的

QEMU 侧的准备

static void machine_set_kernel(Object *obj, const char *value, Error **errp)
{
    MachineState *ms = MACHINE(obj);

    g_free(ms->kernel_filename);
    ms->kernel_filename = g_strdup(value);
}
  1. 在 x86_load_linux 中添加 linuxboot_dma.bin 到 option_rom 数组中
    f = fopen(kernel_filename, "rb");

    if (fread(kernel, 1, kernel_size, f) != kernel_size) { // 读去文件内容
        fprintf(stderr, "fread() failed\n");
        exit(1);
    }

    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); // 通过 FW_CFG_KERNEL_DATA 告知 seabios

    option_rom[nb_option_roms].bootindex = 0;
    option_rom[nb_option_roms].name = "linuxboot.bin";
    if (linuxboot_dma_enabled && fw_cfg_dma_enabled(fw_cfg)) {
        option_rom[nb_option_roms].name = "linuxboot_dma.bin";
    }
  1. 在 pc_memory_init 中调用 rom_add_option 添加到 fw_cfg 中,之后 seabios 就可以通过 fw_cfg 读取 linuxboot_dma.bin
     for (i = 0; i < nb_option_roms; i++) {
         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
    
  2. rom_add_option 会进一步调用 add_boot_device_path 中,记录到 fw_boot_order,从而让 get_boot_devices_list 可以返回 “/rom@genroms/linuxboot_dma.bin”

  3. fw_cfg_machine_reset 中修改 “bootorder”
     buf = get_boot_devices_list(&len); // 返回内容 /rom@genroms/linuxboot_dma.bin
     ptr = fw_cfg_modify_file(s, "bootorder", (uint8_t *)buf, len);
    

到此,QEMU 的准备完成,实际上就是修改 “bootorder”,让 seabios 通过执行 linuxboot_dma.bin 来启动

Seabios 的基本执行流程

其实,总体来说,seabios 做了两个事情:

linuxboot_dma.bin 源代码解析

linuxboot_dma.bin 是通过 pc-bios/optionrom/linuxboot_dma.c 编译出来的,通过前面的分析,其实我们已经可以大致的猜测出来到底

第一个部分是 pnp optionrom 规范的内容,第二个就是通过 fw_cfg 获取到 kernel image 的地址,然后跳转过去了

ARM

如果配置了 BIOS

带 –bios QEMU_EFI.fd

基本执行流程为 QEMU → EDK2 → EFI stub → Linux

因此,如果 ARM virtme 的目标是严格意义上的 -kernel/-initrd 直启,那么在 collei/scripts/collei.py 的 ColleiQemuBuilder.build() 中仅 对 ARM virtme 跳过 setup_bios() 是正确的。

arm 是可以完全绕开的 BIOS 的,但是 x86 不可以

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。