linux/arch/i386/boot/compressed/head.S
在setup()结束后,此函数就被移动到物理地址0x00100000处或者0x00001000处,这取决于内核映像是被高装载到ram中还是低装载到ram中。
解读函数:
startup_32:
cld
cli
movl $(__BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
lss stack_start,%esp
其中的boot_ds内存中已经有谈及。初始化了段寄存器和一个临时队栈。
xorl %eax,%eax
1: incl %eax # check that A20 really IS enabled
movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000
je 1b
测试A20是否真的置位。前面在切换到保护模式之前,已经将A20引脚正式置位,不然每个物理地址第21位都会被cpu看作0.此时再验证。
xorl %eax,%eax
movl $_edata,%edi
movl $_end,%ecx
subl %edi,%ecx
cld
rep
stosb
用0填充_edata和_end符号标识的内核未初始化数据区。在linux填充ram时分几个部分。符号_text对应于物理地址0x00100000,表示内核代码的第一个字节的地址。内核代码的结束位置由另外一个类似的符号_etext表示。内核数据分两组,初始化的数据和没初始化的数据。初始化的数据在_etext后开始,在_edata处结束。紧接着是未初始化的数据并以_end结束。这些符号在编译内核时产生,可以在system.map文件中找到这些符号的线性地址。
subl $16,%esp # place for structure on the stack
movl %esp,%eax
pushl %esi # real mode pointer as second arg
pushl %eax # address of structure as first arg
call decompress_kernel
orl %eax,%eax
jnz 3f
popl %esi # discard address
popl %esi # real mode pointer
xorl %ebx,%ebx
ljmp $(__BOOT_CS), $0x100000
decompress_kernel是解压内核映像的。完成解压后内核被放在合适的位置,如果是低装载的在0x00100000,如果是高装载,则在这个压缩映像之后的临时缓冲区中,解压后的映像就被移动到从物理地址0x00100000开始的最终位置。
然后跳转到0x00100000.
linux 2.6源代码情景分析笔记之系统启动2

最新推荐文章于 2025-09-09 22:53:45 发布