趣谈Linux操作系统随笔——2.0 从BIOS到bootloader:创业伊始,有活儿老板自己上

这篇博客详细介绍了从BIOS启动到Linux操作系统的加载过程,包括BIOS的初始化、bootloader加载、实模式到保护模式的切换、操作系统选择以及最终启动。主要内容涉及Grub2在加载内核和配置文件中的作用,以及启动内核和加载initrd的步骤。文章深入探讨了计算机启动流程的关键环节,适合对系统启动原理感兴趣的读者。
摘要由CSDN通过智能技术生成

从BIOS到bootloader:创业伊始,有活儿老板自己上

  • 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
  • 开发环境:Linux-4.19-rc3内核


一、BIOS启动(实模式)

BIOS程序固化在ROM(Read Only Memory)

环境假设:1M内存空间,x86系统

ROM地址:0xF0000~0xFFFF

电脑刚刚加电时:

  1. 设置CS = 0xFFFF, IP = 0x00000, 第一条指令就会指向0xFFFF0

  2. 执行JMP指令跳到ROM中,执行BIOS,完成部分初始化功能

    2.1 建立中断向量表和中断服务程序(鼠标、键盘)

    2.2 建立内存映射显存空间(显示器)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7DB5hCI-1606189065396)(C:\Users\12544\AppData\Roaming\Typora\typora-user-images\image-20201113193945246.png)]

二、bootloader启动(实模式–>保护模式)

BIOS完成初始化工作之后,需要加载操作系统(放在硬盘),按照约定:一般来说在第一个扇区,占512字节,而且以0xAA55结束

当满足这个条件的时候,就说明这是一个启动盘,在512字节以内会启动相关的代码。

在Linux中,通常使用Grub2这个工具来把操作系统放入到上述扇区中,步骤如下:

  1. 门卫boot.img

    安装boot.img(由boot.S编译而成,大小为512字节),形成第一个扇区MBR(Master Boot Record,主引导扇区)。

    主要工作内容:加载core.img

  2. 管理处core.img

    组成:diskboot.img、lzma_decompress.img、kernel.img和一系列的模块

    1. 1 由boot.img这个门卫引导到管理处core.img的第一个模块diskboot.img

      工作内容:

      diskboot.img获得控制权,把core.img的其他模块引导进来

      ​ 2.1.1 解压缩 lzma_decompress.img,由于此时所需要的内存空间太大,所以会调用real_to_prot,切换到保护模式,获取更大的寻址空间。

      ​ 2.1.2 解压缩 kernel.img(Grub2的内核)

      ​ 2.1.3 各个模块module对应的映像

​             [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pYNuUZ1M-1606189065406)(C:\Users\12544\AppData\Roaming\Typora\typora-user-images\image-20201113200444323.png)]

三、实模式切换到保护模式的具体工作( lzma_decompress.img)

  1. 建立分段:建立段描述符表,把段寄存器设置为段选择子,建立对应关系
  2. 建立分页:获得更大的内存空间
  3. 打开地址线:由于实模式采用的是20位宽的地址线,所以保护模式此时要打开第21根地址线——Gate A20
  4. 有了更大的内存空间,这个时候就解压缩kernel.img

四、选择操作系统(kernel.img)

解压得到startup.S以及一堆c文件,在startup.S中会调用grub_main,这是grub kernel的主函数。

  1. grub_load_config()——获取配置信息

    static void
    grub_load_config (void)
    {
      struct grub_module_header *header;
      FOR_MODULES (header)
      {
        /* Not an embedded config, skip.  */
        if (header->type != OBJ_TYPE_CONFIG)
          continue;
    
        load_config = grub_malloc (header->size - sizeof (struct grub_module_header) + 1);
        if (!load_config)
          {
    	grub_print_error ();
    	break;
          }
        grub_memcpy (load_config, (char *) header +
    		 sizeof (struct grub_module_header),
    		 header->size - sizeof (struct grub_module_header));
        load_config[header->size - sizeof (struct grub_module_header)] = 0;
        break;
      }
    }
    
  2. 进行一系列的初始化

  3. 正常启动后,则调用grub_command_execute()

    static inline grub_err_t
    grub_command_execute (const char *name, int argc, char **argv)
    {
      grub_command_t cmd;
    
      cmd = grub_command_find (name);
      return (cmd) ? cmd->func (cmd, argc, argv) : GRUB_ERR_FILE_NOT_FOUND;
    }
    

    —>调用grub_command_execute (“normal”, 0, 0)

    —>最终会调用grub_normal_execute()函数:grub_show_menu()会显示出让你选择的那个操作系统的列表

五、启动操作系统

  1. 调用 grub_menu_execute_entry() ,开始解析并执行你选择的那一项

  2. 例如里面的linux16命令,表示装载指定的内核文件,并传递内核启动参数

    2.1 grub_cmd_linux()函数会被调用

    • 首先读取Linux内核镜像头部的一些数据结构,放到内存中的数据结构来,进行检查
    • 如果检查通过,则会读取整个Linux内核镜像到内存
  3. 如果配置文件里面还有initrd命令,用于为即将启动的内核传递init ramdisk路径

    3.1 grub_cmd_initrd()函数会被调用,将initramfs加载到内存中来

  4. grub_command_execute (“boot”, 0, 0)才开始真正地启动内核

六、总流程图

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值