基于Linux2.6.38.8内核zImage文件的自解压详解(3)

那么内核是从什么地方开始运行的呢?这个要看lds文件。其实zImage的生成经历了两次链接过程:一是顶层vmlinux的生成,在arch/arm/boot/vmlinux.lds(这个lds文件是由arch/arm/kernel/vmlinux.lds.S生成的)中;另一次是arch/arm/boot/compressed/vmlinux的生成,在arch/arm/boot/compressed/vmlinux.lds.in中。zImage的入口点应该由arch/arm/boot/compressed/vmlinux.lds.in决定。从中可以看出入口点为‘_start’

[plain]

/*    *  linux/arch/arm/boot/compressed/vmlinux.lds.in    *    *  Copyright (C) 2000 Russell King    *    * This program is free software; you can Redistribute it and/or modify    * it under the terms of the GNU General Public License version 2 as    * published by the Free Software Foundation.    */   OUTPUT_ARCH(arm)   ENTRY(_start)   SECTIONS   {     /DISCARD/ : {       *(.ARM.exidx*)       *(.ARM.extab*)       /*        * Discard any r/w data - this produces a link error if we have any,        * which is required for PIC decompression.  Local data generates        * GOTOFF relocations, which prevents it being relocated independently        * of the text/got segments.        */       *(.data)     }        . = TEXT_START;     _text = .;        .text : {       _start = .;       *(.start)       *(.text)       *(.text.*)       *(.fixup)       *(.gnu.warning)       *(.rodata)       *(.rodata.*)       *(.glue_7)       *(.glue_7t)       *(.piggydata)       . = ALIGN(4);     }        _etext = .;        /* Assume size of decompressed image is 4x the compressed image */     _image_size = (_etext - _text) * 4;        _got_start = .;     .got          : { *(.got) }     _got_end = .;     .got.plt      : { *(.got.plt) }     _edata = .;        . = BSS_START;     __bss_start = .;     .bss          : { *(.bss) }     _end = .;        . = ALIGN(8);     /* the stack must be 64-bit aligned */     .stack        : { *(.stack) }        .stab 0       : { *(.stab) }     .stabstr 0        : { *(.stabstr) }     .stab.excl 0      : { *(.stab.excl) }     .stab.exclstr 0   : { *(.stab.exclstr) }     .stab.index 0     : { *(.stab.index) }     .stab.indexstr 0  : { *(.stab.indexstr) }     .comment 0        : { *(.comment) }   }  

在arch/arm/boot/compressed/head.S中找到入口点。
看看head.S会做些什么样的工作:[下面是从网络上摘录]
1: 对于各种Arm CPU的DEBUG输出设定,通过定义宏来统一操作;
2: 设置kernel开始和结束地址,保存architecture ID;
3: 如果在ARM2以上的CPU中,用的是普通用户模式,则升到超级用户模式,然后关中断
4: 分析LC0结构delta offset,判断是否需要重载内核地址(r0存入偏移量,判断r0是否为零)。
5: 需要重载内核地址,将r0的偏移量加到BSS region和GOT table中的每一项。
   对于位置无关的代码,程序是通过GOT表访问全局数据目标的,也就是说GOT表中中记录的是全局数据目标的绝对地址,所以其中的每一项也需要重载。
6: 清空bss堆栈空间r2-r3
7: 建立C程序运行需要的缓存
8: 这时r2是缓存的结束地址,r4是kernel的最后执行地址,r5是kernel境象文件的开始地址
9: 用文件misc.c的函数decompress_kernel(),解压内核于缓存结束的地方(r2地址之后)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/22525.html