Linux 启动流程之自解压(一)
首先,我们要知道在zImage的生成过程中,是把arch/arm/boot/compressed/head.s 和解压代码misc.c,decompress.c加在压缩内核的最前面最终生成zImage的,那么它的启动过程就是从这个head.s开始的,并且如果代码从RAM运行的话,是与位置无关的,可以加载到内存的任何地方。
下面以linux-4.15.09 版本arch/arm/boot/compressed/head.s为主线进行启动过程解析。
1 head.s DEBUG宏定义部分
/*
* Debugging stuff
*
* Note that these macros must not contain any code which is not
* 100% relocatable. Any attempt to do so will result in a crash.
* Please select one of the following when turning on debugging.
*/
#ifdef DEBUG
//开启DEBUG,该功能可有两种方式实现。
//第一种方式:CONFIG_DEBUG_ICEDCC使用ARMv6以上架构支持的ICEDCC技术实现,
//DCC(Debug Communication Channel)是ARM的调试通信通道,在串口无法使用的时候可
//使用改通道进行通信。
//第二种方式:使用串口进行调试,通过配置CONFIG_DEBUG_LL_INCLUDE,
//包含相关平台操作串口的方法,其所用的串口配置参数依赖前一级
//BootLoader所配置好的串口。
#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
mcr p14, 0, \ch, c0, c5, 0
.endm
#elif defined(CONFIG_CPU_XSCALE)
.macro loadsp, rb, tmp
.endm
.macro writeb, ch, rb
mcr p14, 0, \ch, c8, c0, 0
.endm
#else
.macro loadsp, rb, tmp
.endm
.macro writeb, ch, rb
mcr p14, 0, \ch, c1, c0, 0
.endm
#endif
#else
#include CONFIG_DEBUG_LL_INCLUDE
//添加平台操作串口的汇编代码,该部分汇编代码主要实现以下几个功能:
//1. 添加UART:addruart
//2. 发送数据:senduart
//3. 忙等待:busyuart
//4. 等待完成:waituart
.macro writeb, ch, rb
senduart \ch, \rb
.endm
#if defined(CONFIG_ARCH_SA1100)
.macro loadsp, rb, tmp
mov \rb, #0x80000000 @ physical base address
#ifdef CONFIG_DEBUG_LL_SER3
add \rb, \rb, #0x00050000 @ Ser3
#else
add \rb, \rb, #0x00010000 @ Ser1
#endif
.endm
#else
.macro loadsp, rb, tmp
addruart \rb, \tmp
.endm
#endif
#endif
#endif
早期调试信息的实现方式:
//定义宏,输出字符
.macro kputc,val
mov r0, \val
bl putc
.endm
.macro kphex,val,len
mov r0, \val
mov r1, #\len
bl phex
.endm
//定义宏,用于输出cpu_id,arch_id等信息
.macro debug_reloc_start
#ifdef DEBUG
kputc #'\n'
kphex r6, 8 /* processor id */
kputc #':'
kphex r7, 8 /* architecture id */
#ifdef CONFIG_CPU_CP15
kputc #':'
mrc p15, 0, r0, c1, c0
kphex r0, 8 /* control reg */
#endif
kputc #'\n'
kphex r5, 8 /* decompressed kernel start */
kputc #'-'
kphex r9, 8 /* decompressed kernel end */
kputc #'>'
kphex r4, 8 /* kernel execution address */
kputc #'\n'
#endif
.endm
.macro debug_reloc_end
#ifdef DEBUG
kphex r5, 8 /* end of kernel */
kputc #'\n'
mov r0, r4
bl memdump /* dump 256 bytes at start of kernel */
#endif
.endm