Android培训班(98)内核解压过程11

从前面那段代码,就可以看到调用decompress_kernel函数来把内核压缩的代码解压出来,那么你也许问传给解压函数decompress_kernel的四个参数是什么呢?由于ARM里编译时就决定这四个参数是使用四个寄存器来传送,分别为r0,r1,r2,r3等四个寄存器。因此,只需要搞清楚这四个寄存器是什么样的内容,就知道传送给函数什么值了。从代码上看到r0的值与r2r5的值一样,都是指向栈后面64K的位置。r1是指向栈的开始位置。r3是等于r7的值,由于r7里保存着内核的架构ID,因此r3就是CPU的架构ID。这样这四个参数就传送给下面的函数调用:

ulg

decompress_kernel(ulgoutput_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,

int arch_id)

{

output_data =(uch *)output_start; /* Points to kernel start */

free_mem_ptr =free_mem_ptr_p;

free_mem_end_ptr =free_mem_ptr_end_p;

__machine_arch_type =arch_id;

arch_decomp_setup();

makecrc();

putstr("UncompressingLinux...");

gunzip();

putstr("done, booting the kernel.\n");

returnoutput_ptr;

}


在函数decompress_kernel里,就获取得解压后数据输出位置,以及临时的内存开始位置和结束位置,同时得到CPU的架构ID。再把输出位置给全局变量output_data,以便解压函数把数据写到里面。

arch_decomp_setup函数在这里没有任何需要初始化的代码。

makecrc函数是计算内核压缩代码的CRC码表,达到检验代码是否正确的目的。

gunzip函数是进行所有数据解压的操作。

最后在函数返回解压后代码数据结束位置,以便后面的代码进行重定位的操作。


在整个函数没有看到压缩的代码数据从那里输入,以及需要解压数据的长度,到底在那里呢?其实这需要从编译内核时就需要了解,如果还不懂赶紧看看前面的文章了。会在下面函数fill_inbuf里获取解压的数据:

intfill_inbuf(void)

{

if(insize != 0)

error("ranout of input data");

inbuf= input_data;

insize= &input_data_end[0] - &input_data[0];

inptr= 1;

returninbuf[0];

}

看到函数里的input_datainput_data_end,应很眼熟吧,其实它们就是编译时在文件piggy.S汇编文件里,通过这两个指针,就可以得到数据的开始位置和结束位置,从而计算出来要压缩后的数据长度。

通过在gunzip函数解压代码,就可以把压缩的内核变换为可执行的代码,这时代码就全部解压到内存里,能否立即跳到那里执行吗?这个要看输入的解压的地址,如果是内核实际执行位置,就可以直接运行,如果不是,又需要重定位了。


posted @ 2012-04-13 21:49  ajuanabc  阅读(350)  评论(0编辑  收藏  举报