慢慢欣赏linux x86 bootloader加载kernel的策略

对于老的x86来说,bootloader把内核看成两部分,实模式部分和保护模式部分。bootloader分别把实模式和保护模式加载到内存的不同地方,然后跳转到实模式部分。实模式最后跳转到保护模式部分。

不同的bootloader必须都按照这个规矩来。

下面以uboot为例讲解流程

 

struct boot_params *load_zimage(char *image, unsigned long kernel_size, ulong *load_addressp)
    =>setup_base = (struct boot_params *)DEFAULT_SETUP_BASE;/* base address for real-mode segment */ 
    /*
     * Memory lay-out:
     *
     * relative to setup_base (which is 0x90000 currently)
     *
     *    0x0000-0x7FFF    Real mode kernel
     *    0x8000-0x8FFF    Stack and heap
     *    0x9000-0x90FF    Kernel command line
     */
     =>/* determine size of setup *///决定内核实模式程序setup.bin的大小
    if (0 == hdr->setup_sects) {
        printf("Setup Sectors = 0 (defaulting to 4)\n");
        setup_size = 5 * 512;
    } else {
        setup_size = (hdr->setup_sects + 1) * 512;
    }
    =>bootproto = get_boot_protocol(hdr);//老内核需要执行setup.bin,新内核应该可以直接进入保护模式,只有hdr等参数有用
    =>/* Determine image type */
    big_image = (bootproto >= 0x0200) &&
            (hdr->loadflags & BIG_KERNEL_FLAG);

    /* Determine load address *///决定保护模式内核uImage的加载地址
    if (big_image)
        *load_addressp = BZIMAGE_LOAD_ADDR;
    else
        *load_addressp = ZIMAGE_LOAD_ADDR;
    =>memset(setup_base, 0, sizeof(*setup_base));//初始化setup_base
    setup_base->hdr = params->hdr;

    if (bootproto >= 0x0204)
        kernel_size = hdr->syssize * 16;
    else
        kernel_size -= setup_size;

    if (bootproto == 0x0100) {
        /*
         * A very old kernel MUST have its real-mode code
         * loaded at 0x90000
         */
        if ((ulong)setup_base != 0x90000) {
            /* Copy the real-mode kernel *///老内核需要实模式的setup.bin引导
            memmove((void *)0x90000, setup_base, setup_size);

            /* Copy the command line */
            memmove((void *)0x99000,
                (u8 *)setup_base + COMMAND_LINE_OFFSET,
                COMMAND_LINE_SIZE);

             /* Relocated */
            setup_base = (struct boot_params *)0x90000;
        }

        /* It is recommended to clear memory up to the 32K mark */
        memset((u8 *)0x90000 + setup_size, 0,
               SETUP_MAX_SIZE - setup_size);
    }
    =>memmove((void *)*load_addressp, image + setup_size, kernel_size);//将保护模式内核拷贝到内存指定地方,保护模式参数作为出参返回
    =>return setup_base;//返回实模式地址

 

如果protocol为0x100才加载setup.bin。所以猜测uboot在保护模式下直接启动linux的保护模式uImage,而跳过了内核的实模式部分。

而grub则不一定,估计是实模式加载setup.bin然后跳转。

将来有机会仔细研究。

 

linux boot 学习
https://blog.csdn.net/zeflove/article/details/7565269

 


    
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值