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);
就此,将内核解压到指定地址。
讲得不是很详细,后期再加...

浙公网安备 33010602011771号