士官提前退伍程序:Linux Kernel 2.6.37 启动过程:startup
来源:百度文库 编辑:偶看新闻 时间:2024/05/04 14:13:53
一路走来真是内牛满面,现在终于来到了kernel的32位入口了。这就是startup_32。这个入口在arch/x86/boot/compressed/header_32.S里面。至此,请记住,bootloader对于kernel来说意义只有boot_params结构了,其他的一切的一切已经都是浮云了。而boot_params当前地址在esi中。 startup_32缺省在内存的绝对地址0x10000。让我们慢慢解析startup_32。
启动代码终于结束了,明天就要进入真正的kernel了。写得有些乱,就是对代码进行注释,暂时找不到更好的方法来对代码进行解释,可能使大家看起来有点累。希望对大家有帮助
- #include
- #include
- #include
- #include
- #include
- #include
- __HEAD
- ENTRY(startup_32)
- cld
- /*
- * Test KEEP_SEGMENTS flag to see if the bootloader is asking
- * us to not reload segments. BP_loadflags(%esi)即指向boot_params.loadflags.这一位应该是在设置了code32_start Hook的时候使用,因为在protected_mode_jump的最后已经将所有的段都置为_BOOT_DS了。如果bootloader hook了code32_start,返回kernel的时候显然kernel需要去恢复所有的段。
- */
- testb $(1<<6), BP_loadflags(%esi)
- jnz 1f
- cli
- movl $__BOOT_DS, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %fs
- movl %eax, %gs
- movl %eax, %ss
- 1:
- /*
- * Calculate the delta between where we were compiled to run
- * at and where we were actually loaded at. This can only be done
- * with a short local call on x86. Nothing else will tell us what
- * address we are running at. The reserved chunk of the real-mode
- * data at 0x1e4 (defined as a scratch field) are used as the stack
- * for this calculation. Only 4 bytes are needed.
- */
- //仔细阅读了以上的这段英文,不能不说代码构思的巧妙。由于不知道代码是否被加载到0x100000的地址,通过以下的代码就能计算出实际加载的地址和预期地址的差异,也就是说是实际的startup_32的位置。
- leal (BP_scratch+4)(%esi), %esp //boot_params.scratch的地址设置成为堆栈顶。
- call 1f //boot_params.scratch里面就是1:的实际地址
- 1: popl %ebp //ebp就是1:的实际地址
- subl $1b, %ebp //ebp-1:就是实际与预期的差异, 也就是说是实际的startup_32的位置。
- /*
- * %ebp contains the address we are loaded at by the boot loader and %ebx
- * contains the address where we should move the kernel image temporarily
- * for safe in-place decompression.
- */
- #ifdef CONFIG_RELOCATABLE
- movl %ebp, %ebx
- //kernel_alignment里面是kernel地址对齐所需要移动的位移量,这是有bootloader填入的,因为bootloader可能将startup_32装载在非对齐的地址。那么就需要增加移动的位移量来保证对齐而达到更好的性能。下面的代码就是要调整地址的位移而保证对齐。
- movl BP_kernel_alignment(%esi), %eax
- decl %eax
- addl %eax, %ebx
- notl %eax
- andl %eax, %ebx
- #else
- movl $LOAD_PHYSICAL_ADDR, %ebx //LOAD_PHYSICAL_ADDR在 arch/x86/include/asm/boot.h里.实际上应该是0x100000
- #endif
- /* Target address to relocate to for decompression */
- addl $z_extract_offset, %ebx //z_extract_offset由MKpiggy.c 在编译时产生的piggy.S里面定义。在我编译kernel时,z_extract_offset是0x4a0000,现在ebx的值在不考虑reloc的情况下是0x5a0000
- /* Set up the stack */
- leal boot_stack_end(%ebx), %esp //在0x5a0000+boot_stack_end的位置建立栈。
- /* Zero EFLAGS */
- pushl $0
- popfl
- /*
- * Copy the compressed kernel to the end of our buffer
- * where decompression in place becomes safe.
- */
- pushl %esi
- leal (_bss-4)(%ebp), %esi //esi指向源,即ebp+_bss-4的地址,是当前bootloader加载32位kernel的地址空间
- leal (_bss-4)(%ebx), %edi //edi指向目的地址,即ebx+_bss-4的地址,如果kernel不要reloc,就是0x5a0000+_bss-4
- movl $(_bss - startup_32), %ecx //从startup_32d到_bss有多少个字节?
- shrl $2, %ecx //实际我们移动每次4个字节,所以ecx需要除4.
- std
- rep movsl //走咯,我们把自己移动上去
- cld
- popl %esi
- /*
- * Jump to the relocated address.
- */
- leal relocated(%ebx), %eax
- jmp *%eax //跳转到relocated上去即ebx+relocated,即0x5a0000+relocated.
- ENDPROC(startup_32)
- .text
- relocated:
- /*
- * Clear BSS (stack is currently empty)
- */
- xorl %eax, %eax
- leal _bss(%ebx), %edi
- leal _ebss(%ebx), %ecx
- subl %edi, %ecx
- shrl $2, %ecx
- rep stosl
- /*
- * Adjust our own GOT GOT是什么?难道是Global Object Table?为什么GOT里面的每一个项都加上了ebx(0x5a0000)?难道里面是一堆指针需要调整所以加上ebx?
- */
- leal _got(%ebx), %edx
- leal _egot(%ebx), %ecx
- 1:
- cmpl %ecx, %edx
- jae 2f
- addl %ebx, (%edx)
- addl $4, %edx
- jmp 1b
- 2:
- /*
- * Do the decompression, and jump to the new kernel..
- */
- leal z_extract_offset_negative(%ebx), %ebp //ebp=ebx-0x4a0000=0x100000
- /* push arguments for decompress_kernel: */
- pushl %ebp /* output address */ //将Kernel解压缩到0x100000
- pushl $z_input_len /* input_len */ //压缩过的kernel大小
- leal input_data(%ebx), %eax //压缩kernel开始地址
- pushl %eax /* input_data */
- leal boot_heap(%ebx), %eax //工作的堆
- pushl %eax /* heap area */
- pushl %esi /* real mode pointer */ //esi是boot_params
- call decompress_kernel //我不准备去看怎么解压,只要知道它解压了好了
- addl $20, %esp //看来不需要恢复寄存器
- #if CONFIG_RELOCATABLE
- /*
- * Find the address of the relocations.
- */
- leal z_output_len(%ebp), %edi
- /*
- * Calculate the delta between where vmlinux was compiled to run
- * and where it was actually loaded.
- */
- movl %ebp, %ebx
- subl $LOAD_PHYSICAL_ADDR, %ebx
- jz 2f /* Nothing to be done if loaded at compiled addr. */ //如果ebx=0x100000,则不许要reloc
- /*
- * Process relocations. //这段没懂,但应该不影响理解
- */
- 1: subl $4, %edi
- movl (%edi), %ecx
- testl %ecx, %ecx
- jz 2f
- addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
- jmp 1b
- 2:
- #endif
- /*
- * Jump to the decompressed kernel.
- */
- xorl %ebx, %ebx
- jmp *%ebp //重新跳到0x100000开始。
- /*
- * Stack and heap for uncompression
- */
- .bss
- .balign 4
- boot_heap:
- .fill BOOT_HEAP_SIZE, 1, 0
- boot_stack:
- .fill BOOT_STACK_SIZE, 1, 0
- boot_stack_end:
- #include
启动代码终于结束了,明天就要进入真正的kernel了。写得有些乱,就是对代码进行注释,暂时找不到更好的方法来对代码进行解释,可能使大家看起来有点累。希望对大家有帮助
linux kernel 2.6的网卡驱动下栽和设置?
a full Linux 2.4 kernel,翻译
请问,“嵌入式Linux的Kernel的定制与移植”怎么翻译???
Linux Kernel怎么装啊?为什么我运行不了,我家操作系统是XP的。。。
KERNEL不存在?
我装Red Hat Linux.装完进入系统时出现.Kernel panic: Attempted to Kill init是怎么回事??
Microsoft Kernel System Renderer
nt os kernel
kernel错误的问题
Kernel 的问题
FreeDOS Kernel 2036
电脑里面的Kernel是什么意思??
什么是 Win32 Kernel core component
什么是 Win32 Kernel core component
关于winme的kernel.dll
kernel debugger是什么来的?
loading freedos fat kernel go!
failed to load kernel library!!
Microsoft Kernel Wave Audio Mixer
Linux ? ? ? ? ? ?
linux~~~
Linux???
linux???
linux~~~~~~~~~~~~~~~~~`