ARM linux解析之压缩内核zImage的启动过程
,言归正传,再往下看,代码如下:
.macrodebug_reloc_start
#ifdef DEBUG
kputc#\n
kphexr6, 8
kputc#:
kphexr7, 8
#ifdef CONFIG_CPU_CP15
kputc#:
mrcp15, 0, r0, c1, c0
kphexr0, 8
#endif
kputc#\n
kphexr5, 8
kputc#-
kphexr9, 8
kputc#>
kphexr4, 8
kputc#\n
#endif
.endm
.macrodebug_reloc_end
#ifdef DEBUG
kphexr5, 8
kputc#\n
movr0, r4
blmemdump
#endif
.endm
debug_reloc_start
用来打印出一些代码重定位后的信息,关于重定位,后面会说,debug_reloc_end
用来把解压后的内核的256字节的数据dump出来,查看是否正确。很不幸的是,这个不是必须调用的,调试的时候,这些都是要自己把这些调试函数加上去的。好debug部分到这里就完了。
2.head.s的.start部分,进入或保持在svc模式,并关中断
继续向下分析,下面是定义.start段,这段在链接时被链接到代码的最开头,那么zImage启动时,最先执行的代码也就是下面这段代码start开始的,如下:
.section".start", #alloc, #execinstr
.align
.arm@ Always enter in ARM state
start:
.typestart,#function
.rept7
movr0, r0
.endr
ARM(movr0, r0)
ARM(b1f)
THUMB(adr r12, BSYM(1f))
THUMB(bxr12)
.word0x016f2818@ Magic numbers to help the loader
.wordstart@ absolute load/run zImage address
.word_edata@ zImage end address
THUMB(.thumb)
1:movr7, r1@ save architecture ID
movr8, r2@ save atags pointer
#ifndef __ARM_ARCH_2__
mrsr2, cpsr@ get current mode
tstr2, #3@ not user?
bne not_angel
movr0, #0x17@ angel_SWIreason_EnterSVC
ARM(swi 0x123456)@ angel_SWI_ARM
THUMB(svc 0xab)@ angel_SWI_THUMB
not_angel:
mrsr2, cpsr@ turn off interrupts to
orr r2, r2, #0xc0@ prevent angel from running
msrcpsr_c, r2
#else
teqppc, #0x0c003@ turn off interrupts
#endif
为何这个会先执行呢?问的好。那么来个中断吧:这个是由arch/arm/boot/compressed/vmlinux.lds的链接脚本决定的,如下:
.text : {
_start = .;
*(.start)
*(.text)
*(.text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.piggydata)
. = ALIGN(4);
}
怎么样,看到没,.text段最开始的一部分就是.start段,所以这就注定了它就是最先执行的代码。
好了,中断结束,再回到先前面的代码,这段代码的最开始是会被编译器编译成8个nop,这个是为了留给ARM的中断向量表的,但是整个head.s都没有用到中断啊,谁知道告诉我一下,谢了。
然后呢,把u-boot传过来的放在r1,r2的值,存在r7,r8中,r1存是的evb板的ID号,而r2存的是内核要用的参数地址,这两个参数在解压内核的时候不要用到,所以暂时保存一下,解压内枋完了,再传给linux内核。
再然后是几个宏定义的解释,ARM(),BSYM(),THUMB(),再加上W()吧,这几个个宏定义都是在arch/arm/include/asm/unified.h里面定义的,好了,这里也算个中断吧,如下:
#ifdefCONFIG_THUMB2_KERNEL
......
#defineARM(x...)
#defineTHUMB(x...)x
#ifdef __ASSEMBLY__
#defineW(instr)instr.w
#endif
#defineBSYM(sym)sym + 1
#else
......
#defineARM(x...)x
#defineTHUMB(x...)
#ifdef __ASSEMBLY__
#defineW(instr)instr
#endif
#defineBSYM(sym)sym
#endif
好的看到上面的定义你就会明白了,这里是为了兼容THUMB2指令的内核。
关于#defineARM(x...)里面的“...”,没有见过吧,这个是C语言的C99的新标准,变参宏,就是在x里,你可以随便你输入多少个参数。别急还没有完,因为没有看见文件里有什么方包含这个头文件。是的文件中确实没有包含,它的定义是在:arch/arm/makefile中加上的:
KBUILD_AFLAGS+= -include asm/unified.h
行,这些宏解释到此,下面再出现,我就无视它了。
好了,再回来,读取cpsr并判断是否处理器处于supervisor模式——从u-boot进入kernel,系统已经处于SVC32模式;而利用angel进入则处于user模式,还需要额外两条指令。之后是再次确认中断关闭,并完成cpsr写入。
注:Angel是ARM公司的一种调试方法,它本身就是一个调试监控程序,是一组运行在目标机上的程序,可以接收主机上调试器发送的命令,执行诸如设置断点、单步执行目标程序、观察或修改寄存器、存储器内容之类的操作。与基于jtag的调试代理不同,Angel调试监控程序需要占用一定的系统资源,如内存、串行端口等。使用angel调试监控程序可以调试在目标系统运行的arm程序或thumb程序。
好了,里面有一句:teqppc, #0x0c003@ turn off interrupts
是否很奇怪,不过
ARMlinux解析压缩内核zImage启动过 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)