[rk3288] uboot启动kernel流程

本文详细解析了U-Boot在RK3288平台上的启动过程,包括从链接脚本开始的代码流程,全局数据结构初始化,内存区域的分配,重定位过程以及后续的系统初始化。主要内容涉及CPU初始化,串口设置,DDR初始化,环境变量管理,以及最终的内核加载。通过对启动代码的分析,展示了如何从裸机环境逐步过渡到运行Linux内核的阶段。
摘要由CSDN通过智能技术生成

环境:

cpu:3288

system:7.1

uboot启动kernel代码流程:

1.根据.lds链接脚本文件,是从__start开始,里面定义了各个段
start.S---->  //进行reset,disable interrupt 设置向量表进cp15  etc
    bl	_main
crts0.S---->
    初始化c运行时环境,初始化sp,global data结构体
    bl	board_init_f
    
    {
        gd->mon_len = (ulong)&__bss_end - (ulong)_start;
        gd->env_addr    = (ulong)&default_environment[0];   //保存cmdline
        gd->arch.chiptype   //保存cpu信息
        gd->ram_size   //ddr大小
        gd->relocaddr  //128M
        gd->bd->bi_dram[0].size   //128M
        gd->bd->bi_dram[0].start  //0

        serial_init  //初始化串口,主要是写寄存器
        display_options,   //显示Uboot信息---U-Boot 2014.10-RK3288-06 (Sep 22 2023 -                         00:33:05)
        display_text_info   //设置bss段的开始和结束地址,text从0x00开始
        print_cpuinfo   //输出cpu信号,并获取到pll的rate
        show_board_info  //如果 dts中由model输出队  --- model = "Rockchip RK3126 bnd-d708 board";
        dram_init  //初始化dram
        setup_dest_addr   //设置ram_top为ram_size relocaddr 0x8000000(128M)
        reserve_mmu,      //TLB table设置rel地址
        reserve_lcd,      //fb base rel addr
        reserve_global_buffers, //rk bootbuf fastboot log buf
        reserve_uboot   //保留了mon_size的大小,留给重定位后的uboot,对齐后的地址也是开始stack地址
        reserve_malloc,
	    reserve_board,   //保留board info结构体

	    reserve_global_data, //创建新的gd结构体,并将原来的复制过来
	    reserve_stacks,
	    setup_dram_config, 
	    show_dram_config,

	    display_new_sp,
	    setup_reloc,        //计算出reloc_off
    }
    
    /****此时执行完,reloc_addr=reloc_off(因为链接sys_text=0),此时的地址在uboot地址,sp在最后***/
    

 开始uboot重定位:

回到crt0.S
    
    ldr	sp, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */
	bic	sp, sp, #7	/* 8-byte alignment for ABI compliance */
	ldr	r9, [r9, #GD_BD]		/* r9 = gd->bd */
	sub	r9, r9, #GD_SIZE		/* new GD is below bd */

    /***通过上述操作,会找到global data新的结构体位置之前有分析过,他在board info地址下面****/

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
	adr	lr, here               //lr通常作为返回寄存器,执行完relocate_code返回here
	
    ldr	r0, [r9, #GD_RELOC_OFF]		/* r0 = gd->reloc_off 将上述分配的uboot地址空间和链接地址结算出的偏移量复制给r0,[r9, #GD_RELOC_OFF]的含义就是gd结构体,GD_RELOC_OFF的偏移量,也就是reloc_off在gd中的位置*/
	add	lr, lr, r0      //计算出重定位之后here的地址            
	ldr	r0, [r9, #GD_RELOCADDR]		/* r0 = gd->relocaddr 调用relocate_code传递的参数*/
	b	relocate_code
#endif
    
    /******************/
here:

    ....
    ldr	pc, =board_init_r  //返回之后就是调用此函数正式进入c代码初始化

relocate.S------->

    00000000 T __image_copy_start
    00000000 T _start
    //可以看到,其实这个也就是Uboot代码的最开始的位值
ldr	r1, =__image_copy_start	/* r1 <- SRC &__image_copy_start */
    
    //r0就是上面传下来的参数,新uboot地址.r4就是新老uboot开头的地址偏移
	subs	r4, r0, r1		/* r4 <- relocation offset */
    
    //如果地址相同就跳过,显然是不相同的
	beq	relocate_done		/* skip relocation */
    
    //r2保存__image_copy_end地址
	ldr	r2, =__image_copy_end	/* r2 <- SRC &__image_copy_end */

copy_loop:
    //开始进行copy,老地址到新地址
	ldmia	r1!, {r10-r11}		/* copy from source address [r1]    */
(1)	stmia	r0!, {r10-r11}		/* copy to   target address [r0]    */
	cmp	r1, r2			/* until source end address [r2]    */
	blo	copy_loop
    
	/*
	 * fix .rel.dyn relocations
	 */
    //在__image_copy_end段下面的段
	ldr	r2, =__rel_dyn_start	/* r2 <- SRC &__rel_dyn_start */
	ldr	r3, =__rel_dyn_end	/* r3 <- SRC &__rel_dyn_end */
fixloop:
    //经过上述(1)操作,r0也到了新uboot的rel.syn段,开始复制rel.syn段
	ldmia	r2!, {r0-r1}		/* (r0,r1) <- (SRC location,fixup) */
	and	r1, r1, #0xff
	cmp	r1, #23			/* relative fixup? */
	bne	fixnext

	/* relative fix: increase location by offset */
	add	r0, r0, r4
	ldr	r1, [r0]
	add	r1, r1, r4
	str	r1, [r0]
fixnext:
	cmp	r2, r3
	blo	fixloop

relocate_done:
board/rockchip/rk32xx/rk32xx.c
board_late_init------>          //进行一些初始化
{
    board_late_init--->
	board_init_adjust_env();  //检查一些env,比如bootdelay
	load_disk_partitions();   //解析分区表
	rkimage_prepare_fdt();   //从boot,resource recovery里面获取fdt
	key_init();   			//初始化adc按键 RockusbKeyadc :0~30    FastbootKey adc:160~180   RecoveryKey adc:0~30  
							//	power key从dts中获取
	fixed_regulator_init();	//在dts中找到regulator-fixed的device,然后使能 
	pmic_init(0);           //初始化pmic,传入参数为i2c bus
	pwm_regulator_init();   //pwm初始化
}

load_disk_partitions----->     //rk解析parameter
board_fbt_preboot----->
board_fbt_key_pressed----->
    board_fbt_low_power_check----->
        is_power_extreme_low----->
            get_power_bat_status----->
rkloader_run_misc_cmd------->

main_loop---->
	1.获取"bootrk" cmd,并启动  autoboot_command("bootrk");=>run_command_list(s, -1, 0);
	2.cmd_bootrk.c ==>
	{
		U_BOOT_CMD(
		bootrk,	2,	1,	do_bootrk,      //执行do_bootrk函数
		"boot rockchip android bootimg",
	}
do_bootrk(NULL, 0, ARRAY_SIZE(boot_cmd), boot_cmd);           

rk_load_image_from_storage/ram()------>   //这里会去保存加载kernel内存地址
  rkimage_load_image(hdr, ptn, get_disk_partition(KERNEL_NAME)----->  
    rkimg_load_image(kernel_ptn->start, (unsigned char *)(unsigned long)hdr->kernel_addr,  &image_size)------->
       rkloader_CopyFlash2Memory((uint32)(unsigned long) load_addr + RK_BLK_SIZE - head_offset, offset + 1, blocks - 1)----->//kernel加载到内存中

do_bootm_linux(0, 0, NULL, &images);------>   //Image中保存这logo,,kernel,ramdisk等信息的加载地址
boot_jump_linux----->
 kernel_entry(r0, 0, r2);    //跳到kernel

rk是通过加载parameter文件来进行信息获取。在load_disk_partitions步骤中,代码会去读取解析parameter文件,经过些处理将所有信息存储在结构体中。

rk的parameter都保存在  PBootInfo  指针里面    cmd_mtd就是保存分区大小信息的字符串   
typedef struct tagBootInfo {
        uint32 magic_code;
        uint16 machine_type;
        uint16 boot_index; /* 0 - normal boot, 1 - recovery */
        uint32 atag_addr;
        uint32 misc_offset;
        uint32 kernel_load_addr;
        uint32 boot_offset; /* ÒÔSectorΪµ¥Î» */
        uint32 recovery_offset; /* ÒÔSectorΪµ¥Î» */
        uint32 ramdisk_offset; /* ÒÔSectorΪµ¥Î» */
        uint32 ramdisk_size; /* ÒÔByteΪµ¥Î» */
        uint32 ramdisk_load_addr;
        uint32 is_kernel_in_boot;

        uint32 check_mask; /* 00 - ²»Ð£Ñ飬 01 - check kernel, 10 - check ramdisk, 11 - both check */
        char cmd_line[MAX_LINE_CHAR];
        cmdline_mtd_partition cmd_mtd;

        int index_misc;
        int index_kernel;
        int index_boot;
        int index_recovery;
        int index_system;
        int index_backup;
        int index_snapshot;
        char fw_version[MAX_LINE_CHAR];
        char fdt_name[MAX_LINE_CHAR];
} BootInfo, *PBootInfo;

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值