Linux 内核启动过程 (四、关于内核解压过程)

uboot结束后,就会去启动内核。如果内核属于压缩内核,那么就会进入:arch/mips/boot/compressed/head.S

先上源码:

#include <asm/asm.h>
#include <asm/regdef.h>

    .set noreorder        //默认汇编器处在reorder的模式下
    .cprestore
    LEAF(start)

start:
    /* Save boot rom start args */
    move    s0, a0
    move    s1, a1
    move    s2, a2
    move    s3, a3

    /* Clear BSS */
    PTR_LA    a0, _edata
    PTR_LA    a2, _end
1:    sw    zero, 0(a0)
    bne    a2, a0, 1b
     addiu    a0, a0, 4

    PTR_LA    a0, (.heap)          /* heap address */
    PTR_LA  sp, (.stack + 8192)  /* stack address */

    PTR_LA    ra, 2f
    PTR_LA    k0, decompress_kernel //解压函数 arch/mips/boot/compressed/decompress.c
    jr    k0
     nop
2:
    move    a0, s0
    move    a1, s1
    move    a2, s2
    move    a3, s3
    PTR_LI    k0, KERNEL_ENTRY   //进入arch/mips/kernel/head.S 
    jr    k0
     nop
3:
    b    3b
     nop
    END(start)

    .comm .heap,BOOT_HEAP_SIZE,4
    .comm .stack,4096*2,4

这里讲讲开始的: LEAF(start)

这里在arch/mips/kernel/head.S 中有个NESTED(kernel_entry, 16, sp) # kernel entry point

他们都在asm.h中定义:

#define    LEAF(symbol)                                    \
        .globl    symbol;                         \
        .align    2;                              \
        .type    symbol, @function;              \
        .ent    symbol, 0;                      \
symbol:        .frame    sp, 0, ra         //汇编伪指令  frame 用来声明堆栈布局。

/*
 * NESTED - declare nested routine entry point
 */
#define    NESTED(symbol, framesize, rpc)                  \
        .globl    symbol;                         \
        .align    2;                              \
        .type    symbol, @function;              \
        .ent    symbol, 0;                       \
symbol:        .frame    sp, framesize, rpc

 

LEAF不需要过多处理堆栈指针。

汇编伪指令  frame 用来声明堆栈布局。
它有三个参数:
    1)第一个参数  framereg:声明用于访问局部堆栈的寄存器,一般为  $sp。
    2)第二个参数  framesize:申明该函数已分配堆栈的大小,应该符合  $sp + framesize = 原来的  $sp。
    3)第三个参数  returnreg:这个寄存器用来保存返回地址。

 

void decompress_kernel(unsigned long boot_heap_start)  //arch/mips/boot/compressed/decompress.c

该函数的主要作用:

1 获取vmlinux.bin的开始和结束位置;

2 准备解压的内存地址和长度;

3 decompress((char *)zimage_start, zimage_size, 0, 0,(void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error);

就此,将内核解压到指定地址。

讲得不是很详细,后期再加...

posted @ 2015-03-24 22:45  JustRelax  阅读(836)  评论(0)    收藏  举报