浅析开发板相关函数bootloader传入的寄存器r2对应开发板tags参数地址浅析blob到kernel传递tags参数和cmdline处理流程
r0 = 0
r1=mach_type_id
r2=BOOT_PARAMS
arch/arm/kernel/vmlinux.lds
arch/arm/kernel/head.S
为入口位置
.section ".text.head", "ax"
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id // r9 = 0x41129200
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)? // r5 = __proc_info_begin虚拟地址值,所以r10等于__proc_info_begin虚拟地址值
beq __error_p @ yes, error 'p' // 如果r5等于0,那么beq成立,跳转到__error_p执行,halt在那里[luther.gliethttp]
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
bl __vet_atags
bl __create_page_tables
arch/arm/kernel/head-common.S
.long __proc_info_begin
.long __proc_info_end
3: .long .
.long __arch_info_begin
.long __arch_info_end
__lookup_machine_type:
adr r3, 3b
ldmia r3, {r4, r5, r6} // r4 = 3b的虚拟地址值,r5 = __arch_info_begin虚拟地址值[luther.gliethttp]
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type // MACHINFO_TYPE为0,所以ldr r3, [r5, #0],对于EDB9312开发板r3 = 451
teq r3, r1 @ matches loader number? // r1为bootloader,比如vivi,redboot或者blob等传入的nr值,即函数的第2个参数值
beq 2f @ found // 如果bootloader确实启动该zImage内核,那么跳到2f成功返回
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
cmp r5, r6
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
ENDPROC(__lookup_machine_type)
反汇编可以得到machine_desc的.nr
c0008344: c001ba18 andgt fp, r1, r8, lsl sl
c0008348: c0008348 andgt r8, r0, r8, asr #6
c000834c: c001ba18 andgt fp, r1, r8, lsl sl
c0008350: c001ba4c andgt fp, r1, ip, asr #20
c0008354 <__lookup_machine_type>:
c0008354: e24f3014 sub r3, pc, #20 ; 0x14 // 从当前pc回数20个字节,即
c0008358: e8930070 ldmia r3, {r4, r5, r6} // r4 = c0008348, r5 = c001ba18, r6 = c001ba4c
c000835c: e0433004 sub r3, r3, r4
c0008360: e0855003 add r5, r5, r3
c0008364: e0866003 add r6, r6, r3
c0008368: e5953000 ldr r3, [r5] // 所以取出虚拟地址c001ba18数据
c001ba18 <__arch_info_begin>:
c001ba18: 000001c3 andeq r0, r0, r3, asr #3 // 0x1c3 = 451,所以等于MACH_TYPE_EDB9312
c001ba1c: 80800000 addhi r0, r0, r0
c001ba20: 00003fb4 streqh r3, [r0], -r4
c001ba24: c02d6cd0 ldrgtd r6, [sp], -r0
c001ba28: 00000100 andeq r0, r0, r0, lsl #2
下面该宏MACHINE_START用来在__arch_info_begin空间生成一个machine结构体struct machine_desc,
该machine_desc结构体用来描述该款SoC,比如ep9312,的基础配置信息.[luther.gliethttp]
从这里来看宏默认只是定义.nr,即该SoC对应的索引值.[luther.gliethttp]
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
#define MACH_TYPE_EDB9312 451
所以下面的.nr = 451,[luther.gliethttp]
arch/arm/mach-ep93xx/edb9312.c
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
/* Maintainer: Toufeeq Hussain
*/
.phys_io = EP93XX_APB_PHYS_BASE,
.io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
.init_machine = edb9312_init_machine,
MACHINE_END
再比如:
#define MACH_TYPE_AT91RM9200DK 262
所以下面的.nr = 262,[luther.gliethttp]
arch/arm/mach-at91/board-dk.c
MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
/* Maintainer: SAN People/Atmel */
.phys_io = AT91_BASE_SYS,
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = dk_map_io,
.init_irq = dk_init_irq,
.init_machine = dk_board_init,
MACHINE_END