Linux0.11 boot分析总结

    xiaoxiao2022-07-14  149

    最近在看linux启动过程,把看的过程中一些问题记了下来(有错误,麻烦大神指正!)推荐使用https://github.com/tinyclub/linux-0.11-lab.git可以一边运行,一边分析。该代码与原始代码有点不同,把system改成了kernel.bin,大部分是一样的。下载完之后运行make编译,然后make debug开始调试,调试的时候要打开另一个终端输入gdb src/kernel.sym。

    初始断点设置需要修改目录下的.kernel_gdbinit.

    target remote :1234 b startup_32 c b main c bt l

    “b”是设置断点位置,startup_32就是head.s中的开头。“c”是继续运行,然后又停在main。

    如果需要调试bootsect, 运行make debug DST=src/boot/bootsect.sym,打开另一个终端输入gdb src/boot/bootsect.sym,同样的设置初始断点位置编辑.boot_gdbinit。

    linux启动过程如下图所示:

    在Makefile中也可以看出linux image由bootsectsetupkernel.bin组成,并且tools\build.sh合成,bootsect大小正是512byte

    Image: boot/bootsect boot/setup kernel.bin FORCE

        $(BUILD) boot/bootsect boot/setup kernel.bin Image

        $(Q)rm -f kernel.bin

        $(Q)sync

    目前所有的chip中bootloader都要放在第一个存储区,这样方便读取,也是芯片设计决定的,大小呢一般由第一块存储扇区决定(3.5英寸软区的扇区大小是512byte)。其实大小并不一定要是第一个扇区大小,现在有的芯片把bootloader长度信息放在最开头的128字节,只要芯片可以读到这个值就行。为什么bootsect正好是512?看下面代码:org 508+.word ROOT_DEV + .word 0xAA55=512

    msg1:

        .byte 13,10

        .ascii "Loading system ..."

        .byte 13,10,13,10

     

        .org 508

    root_dev:

        .word ROOT_DEV

    boot_flag:

        .word 0xAA55

    bootloader的主要作用就是加载kernel。上电之后bios就会将第一个扇区的内容加载到0x7c00的内存处(X86计算机启动流程分析之BIOS),若是芯片移植,这个地址不一定是0x7c00,要看一下芯片的datasheet)。下面这个图画的非常准确,内存分布在各个阶段很清楚:

    最开头的0地址由bios中断会使用,然后bootsect又将自已移动到0x90000。

    为什么要移动?因为后面要把kernel移动到0x0开始的位置,kernel一般比较大,有可能将0x7c00这个地址覆盖掉,这个地址只需要满足后续读取kernel就可以了,并不一定要是0x90000。

    然后就是读setup与kernel。这里有个问题为什么要分成setup与kernel,而不是一个bin,岂不更简单?

    bootsect使用bios,bios是个非常简单的系统,可以理解为只有读取数据功能,读取完了之后将系统由bios切换到chip也就是setup接管之后将kernel移动到0位置,setup另一个工作便是从16位转到32位,也就是运行在保护模式,所以加载gdt与idt,也只作了最简单的初始化。细节部分以下这几篇文章分析的很清楚了。

    linux 0.11_boot启动详解1一站式linux0.11内核head.s代码段图表详解bootsect.s 分析—— Linux-0.11 学习笔记(一)setup.s 分析—— Linux-0.11 学习笔记(二)

             我们接着说head.s ,kernel中的最开始部分是head.s也在boot目录。该工作就是初始化idt与gdt,与setup.s相比更详细一些。Linux0.1的时候就没有bootsect.s至setup.s切换,直接到了head.s( head.s 分析——Linux-0.11 学习笔记(三))。linux中的head.s是AT&T汇编,因为使用 GNU 的 as 和 ld 进行编译和连接。嵌入式移植应该都有toolchain,装好就行了。

    为什么要初始化堆栈,setup.s中并没有,而且初始化时还作了两次?

    startup_32:     movl $0x10,
    转载请注明原文地址: https://yun.8miu.com/read-58552.html
    最新回复(0)