微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM linux解析之压缩内核zImage的启动过程

ARM linux解析之压缩内核zImage的启动过程

时间:11-10 来源:互联网 点击:
首先,我们要知道在zImage的生成过程中,是把arch/arm/boot/compressed/head.s和解压代码misc.c,decompress.c加在压缩内核的最前面最终生成zImage的,那么它的启动过程就是从这个head.s开始的,并且如果代码从RAM运行的话,是与位置无关的,可以加载到内存的任何地方。

下面以arch/arm/boot/compressed/head.s为主线进行启动过程解析。

1.head.s的debug宏定义部分

最开始的一段都是head.s的debug宏定义部分,这部分可以方便我们调试时使用。

如下:

#ifdefDEBUG

#if defined(CONFIG_DEBUG_ICEDCC)

#if defined(CONFIG_CPU_V6) defined(CONFIG_CPU_V6K) defined(CONFIG_CPU_V7)

.macro loadsp, rb, tmp

.endm

.macro writeb, ch, rb

mcrp14, 0, \ch, c0, c5, 0

.endm

#elif defined(CONFIG_CPU_XSCALE)

.macro loadsp, rb, tmp

.endm

.macro writeb, ch, rb

mcrp14, 0, \ch, c8, c0, 0

.endm

#else

.macro loadsp, rb, tmp

.endm

.macro writeb, ch, rb

mcrp14, 0, \ch, c1, c0, 0

.endm

#endif

#else

#include

.macro writeb, ch, rb

senduart \ch, \rb

.endm

#if defined(CONFIG_ARCH_SA1100)

.macro loadsp, rb, tmp

mov\rb, #0x80@ physical base address

#ifdef CONFIG_DEBUG_LL_SER3

add \rb, \rb, #0x50 @ Ser3

#else

add \rb, \rb, #0x10 @ Ser1

#endif

.endm

#elif defined(CONFIG_ARCH_S3C2410)

.macro loadsp, rb, tmp

mov\rb, #0x50

add \rb, \rb, #0x4 * CONFIG_S3C_LOWLEVEL_UART_PORT

.endm

#else

.macro loadsp, rb, tmp

addruart \rb, \tmp

.endm

#endif

#endif

#endif

如果开启DEBUGging宏的话,这部分代码分两段CONFIG_DEBUG_ICEDCC是用ARMv6以上的加构支持的ICEDCC技术进行调试,DCC(Debug Communications Channel)是ARM的一个调试通信通道,在串口无法使用的时候可以使用这个通道进行数据的通信,具体的技术参前ARM公司文档《ARM Architecture Reference Manual》。

第二部分首先#include ,这个文件定义位于arch/arm/mach-xxxx/include/mach/debug-macro.S里面,所以这个是和平台相关的,里面定义了每个平台的相关的串口操作,因这个时候系统还没有起来,所以它所用的串口配置参数是依赖于前一级bootloader所设置好的,如我们使用的u-boot设置好所有的参数。如我们的EVB板ARM的实现如下:

#include

#include

.macroaddruart, rp, rv

ldr \rp, =ARM_EVB_UART0_BASE@ System peripherals (phys address)

ldr \rv, =(IO_BASE+ ARM_EVB _UART0_BASE)@ System peripherals (virt address)

.endm

.macrosenduart,rd,rx

strb\rd, [\rx, #(0x00)]@ Write to Transmitter Holding Register

.endm

.macrowaituart,rd,rx

1001:ldr \rd, [\rx, #(0x18)]@ Read Status Register

tst \rd, #0x20@when TX FIFOFull, then wait

bne 1001b

.endm

.macrobusyuart,rd,rx

1001:ldr \rd, [\rx, #(0x18)]@ Read Status Register

tst \rd, #0x08@ when uart is busy then wait

bne 1001b

.endm

主要实现addruart,senduart,waituart,busyuart这四个函数的具体实施。这个是调试函数打印的基础。

下面是调试打印用到的kputc和kphex

.macrokputc,val

movr0, \val

blputc

.endm

.macrokphex,val,len

movr0, \val

movr1, #\len

blphex

.endm

它所调用的putc和phex是在head.s最后的一段定义的,如下

#ifdef DEBUG

.align2

.typephexbuf,#object

phexbuf:.space12

.sizephexbuf, . - phexbuf

上面是分配打印hex的buffer,下面是具体的实现:

@ phex corrupts {r0, r1, r2, r3}

phex:adr r3, phexbuf

movr2, #0

strbr2, [r3, r1]

1:subsr1, r1, #1

movmi r0, r3

bmiputs

and r2, r0, #15

movr0, r0, lsr #4

cmpr2, #10

addger2, r2, #7

add r2, r2, #0

strbr2, [r3, r1]

b1b

@ puts corrupts {r0, r1, r2, r3}

puts:loadspr3, r1

1:ldrbr2, [r0], #1

teq r2, #0

moveqpc, lr

2:writebr2, r3

movr1, #0x20

3:subsr1, r1, #1

bne 3b

teq r2, #\n

moveqr2, #\r

beq 2b

teq r0, #0

bne 1b

movpc, lr

@ putc corrupts {r0, r1, r2, r3}

putc:

movr2, r0

movr0, #0

loadspr3, r1

b2b

@ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}

memdump:movr12, r0

movr10, lr

movr11, #0

2:movr0, r11, lsl #2

add r0, r0, r12

movr1, #8

blphex

movr0, #:

blputc

1:movr0, #

blputc

ldrr0, [r12, r11, lsl #2]

movr1, #8

blphex

and r0, r11, #7

teq r0, #3

moveqr0, #

bleqputc

and r0, r11, #7

add r11, r11, #1

teq r0, #7

bne 1b

movr0, #\n

blputc

cmpr11, #64

blt2b

movpc, r10

#endif

嘿嘿,还有memdump这个函数可以用,不错。

好了

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top