diff --git a/Booting/images/bss.png b/Booting/images/bss.png new file mode 100644 index 0000000..b7a1e9b Binary files /dev/null and b/Booting/images/bss.png differ diff --git a/Booting/images/kernel_first_address.png b/Booting/images/kernel_first_address.png new file mode 100644 index 0000000..ba746f9 Binary files /dev/null and b/Booting/images/kernel_first_address.png differ diff --git a/Booting/images/linear_address.png b/Booting/images/linear_address.png new file mode 100644 index 0000000..244de42 Binary files /dev/null and b/Booting/images/linear_address.png differ diff --git a/Booting/images/minimal_stack.png b/Booting/images/minimal_stack.png new file mode 100644 index 0000000..ac1ac9a Binary files /dev/null and b/Booting/images/minimal_stack.png differ diff --git a/Booting/images/simple_bootloader.png b/Booting/images/simple_bootloader.png new file mode 100644 index 0000000..53e4d65 Binary files /dev/null and b/Booting/images/simple_bootloader.png differ diff --git a/Booting/images/stack1.png b/Booting/images/stack1.png new file mode 100644 index 0000000..78d4c99 Binary files /dev/null and b/Booting/images/stack1.png differ diff --git a/Booting/images/stack2.png b/Booting/images/stack2.png new file mode 100644 index 0000000..3e27895 Binary files /dev/null and b/Booting/images/stack2.png differ diff --git a/Booting/images/try_vmlinuz_in_qemu.png b/Booting/images/try_vmlinuz_in_qemu.png new file mode 100644 index 0000000..5b44d69 Binary files /dev/null and b/Booting/images/try_vmlinuz_in_qemu.png differ diff --git a/Booting/images/video_mode_setup_menu.png b/Booting/images/video_mode_setup_menu.png new file mode 100644 index 0000000..99162ac Binary files /dev/null and b/Booting/images/video_mode_setup_menu.png differ diff --git a/Booting/linux-bootstrap-1.md b/Booting/linux-bootstrap-1.md index 25e6d6f..28c4c4e 100644 --- a/Booting/linux-bootstrap-1.md +++ b/Booting/linux-bootstrap-1.md @@ -132,7 +132,7 @@ nasm -f bin boot.nasm && qemu-system-x86_64 boot 将看到: -![Simple bootloader which prints only `!`](https://github.com/0xAX/linux-insides/raw/master/Booting/images/simple_bootloader.png) +![Simple bootloader which prints only `!`](images/simple_bootloader.png) 在这个例子中,这段代码被执行在16位的实模式,起始于内存0x7c00。之后调用 [0x10](http://www.ctyme.com/intr/rb-0106.htm) 中断打印 `!` 符号。用0填充剩余的510字节并用两个Magic Bytes `0xaa` 和 `0x55` 结束。 @@ -245,7 +245,7 @@ X+08000 +------------------------+ 上面的公式中, `X` 是 kernel bootsector 被引导入内存的位置。在我的机器上, `X` 的值是 `0x10000`,我们可以通过 memory dump 来检查这个地址: -![kernel first address](https://github.com/0xAX/linux-insides/raw/master/Booting/images/kernel_first_address.png) +![kernel first address](images/kernel_first_address.png) 到这里,引导程序完成它的使命,并将控制权移交给了 Linux kernel。下面我们就来看看 kernel setup code 都做了些什么。 @@ -260,7 +260,7 @@ X+08000 +------------------------+ qemu-system-x86_64 vmlinuz-3.18-generic ``` -![Try vmlinuz in qemu](https://github.com/0xAX/linux-insides/raw/master/Booting/images/try_vmlinuz_in_qemu.png) +![Try vmlinuz in qemu](images/try_vmlinuz_in_qemu.png) 为了能够作为 bootloader 来使用, `header.S` 开始处定义了 [MZ] [MZ](https://en.wikipedia.org/wiki/DOS_MZ_executable) 魔术数字, 并且定义了 [PE](https://en.wikipedia.org/wiki/Portable_Executable) 头,在 PE 头中定义了输出的字符串: @@ -387,7 +387,7 @@ cs = 0x1020 这段代码首先将 `dx` 寄存器的值(就是当前`sp` 寄存器的值)4字节对齐,然后检查是否为0(如果是0,堆栈就不对了,因为堆栈是从大地址向小地址发展的),如果是0,那么就将 `dx` 寄存器的值设置成 `0xfffc` (64KB地址段的最后一个4字节地址)。如果不是0,那么就保持当前值不变。接下来,就将 `ax` 寄存器的值( 0x10000 )设置到 `ss` 寄存器,并根据 `dx` 寄存器的值设置正确的 `sp`。这样我们就得到了正确的堆栈设置,具体请参考下图: -![stack](https://github.com/0xAX/linux-insides/raw/master/Booting/images/stack1.png) +![stack](images/stack1.png) * 下面让我们来看 `ss` != `ds`的情况,首先将 setup code 的结束地址 [_end](http://lxr.free-electrons.com/source/arch/x86/boot/setup.ld?v=3.18#L52) 写入 `dx` 寄存器。然后检查 `loadflags` 中是否设置了 `CAN_USE_HEAP` 标志。 根据 kernel boot protocol 的定义,[loadflags](http://lxr.free-electrons.com/source/arch/x86/boot/header.S?v=3.18#L321) 是一个标志字段。这个字段的 `Bit 7` 就是 `CAN_USE_HEAP` 标志: @@ -413,11 +413,11 @@ Field name: loadflags 如果 `CAN_USE_HEAP` 被置位,那么将 `heap_end_ptr` 放入 `dx` 寄存器,然后加上 `STACK_SIZE` (最小堆栈大小是 512 bytes)。在加法完成之后,如果结果没有溢出(CF flag 没有置位,如果置位那么程序就出错了),那么就跳转到标号为 `2` 的代码处继续执行(这段代码的逻辑在1中已经详细介绍了),接着我们就得到了如下图所示的堆栈: -![stack](https://github.com/0xAX/linux-insides/raw/master/Booting/images/stack2.png) +![stack](images/stack2.png) * 最后一种情况就是 `CAN_USE_HEAP` 没有置位, 那么我们就将 `dx` 寄存器的值加上 `STACK_SIZE`,然后跳转到标号为 `2` 的代码处继续执行,接着我们就得到了如下图所示的堆栈: -![minimal stack](https://github.com/0xAX/linux-insides/raw/master/Booting/images/minimal_stack.png) +![minimal stack](images/minimal_stack.png) BSS段设置 -------------------------------------------------------------------------------- @@ -444,7 +444,7 @@ BSS 段用来存储那些没有被初始化的静态变量。对于这个段使 在这段代码中,首先将 [__bss_start](http://lxr.free-electrons.com/source/arch/x86/boot/setup.ld?v=3.18#L47) 地址放入 `di` 寄存器,然后将 `_end + 3` (4字节对齐) 地址放入 `cx`,接着使用 `xor` 指令将 `ax` 寄存器清零,接着计算 BSS 段的大小 ( `cx` - `di` ),然后将大小放入 `cx` 寄存器。接下来将 `cx` 寄存器除4,最后使用 `rep; stosl` 指令将 `ax` 寄存器的值(0)写入 寄存器整个 BSS 段。 代码执行完成之后,我们将得到如下图所示的 BSS 段: -![bss](https://github.com/0xAX/linux-insides/raw/master/Booting/images/bss.png) +![bss](images/bss.png) 跳转到 main 函数 -------------------------------------------------------------------------------- diff --git a/Booting/linux-bootstrap-2.md b/Booting/linux-bootstrap-2.md index 275b658..8bacf02 100644 --- a/Booting/linux-bootstrap-2.md +++ b/Booting/linux-bootstrap-2.md @@ -163,7 +163,7 @@ lgdt gdt * CPU根据`段选择子`从GDT中找到一个匹配的段描述符,然后将段描述符放入段寄存器的隐藏部分 * 在没有使用向下扩展段的时候,那么内存段的基地址就是`段描述符中的基地址`,段描述符的`limit + 1`就是内存段的长度。如果你知道一个内存地址的`偏移`,那么在没有开启分页机制的情况下,这个内存的物理地址就是`基地址+偏移` -![linear address](http://oi62.tinypic.com/2yo369v.jpg) +![linear address](images/linear_address.png) 当代码要从实模式进入保护模式的时候,需要执行下面的操作: diff --git a/Booting/linux-bootstrap-3.md b/Booting/linux-bootstrap-3.md index b3defc4..e839987 100644 --- a/Booting/linux-bootstrap-3.md +++ b/Booting/linux-bootstrap-3.md @@ -40,7 +40,7 @@ vga= 根据上面的描述,我们可以通过将 `vga` 选项写入 grub 或者写到引导程序的配置文件,从而让内核命令行得到相应的显示模式设置信息。这个选项可以接受不同类型的值来表示相同的意思。比如你可以传入 0XFFFD 或者 ask,这2个值都表示需要显示一个菜单让用户选择想要的显示模式。下面的链接就给出了这个菜单: -![video mode setup menu](http://oi59.tinypic.com/ejcz81.jpg) +![video mode setup menu](images/video_mode_setup_menu.png) 通过这个菜单,用户可以选择想要进入的显示模式。不过在我们进一步了解显示模式的设置过程之前,让我们先回头了解一些重要的概念。