a64 uboot 代码走读

默认分类,linux,a64,debian 2019-09-17 3739 次浏览 次点赞


uboot code review

I. 术语

术语描述
fdtflattened device tree

II. 流程

st=>start: main
op0=>operation: board_init_f
op1=>operation: init_sequence_r
op2=>operation: main_loop
op3=>operation: do_sunxi_flash
op4=>operation: do_boota
e=>end:do_boota

st->op0->op1->op2->op3->op4->

已经完整梳理主要程序流,对于每个主程序流会按章节阻逐个细化分解。

  • uboot 入口main

    main完成一些状态初始化和标记,之后通过board_init_fboard_init_r 完成早期、中期初始化工作;

    //file."arch/sandbox/cpu/start.c" funciton."main" line."239
    //Do pre- and post-relocation init
    board_init_f(0);
    board_init_r(gd->new_gd, 0);
  • 对于如上初始化board_init_f主要通过预定义并且初始化的函数指针列表init_sequence_f[]依次执行完成;

    //file."common/board_f.c" funciton."board_init_f" line."834"
    static init_fnc_t init_sequence_f[] = {
    #ifdef CONFIG_SANDBOX
        setup_ram_buf,
    #endif
        setup_mon_len,
        setup_fdt,
        trace_early_init,
    }

    同样地,对于board_init_r 通过预先定义好的init_sequence_r 数组依次完成函数调用;

    //file."common/board_r.c" funciton."init_sequence_r" line."411"
    init_fnc_t init_sequence_r[] = {
        initr_trace,
        initr_reloc,
        run_main_loop,
    }
  • 之后程序进入main_loop 通过解析预定义环境变量bootcmd=x执行后续操作。

    //file."common/main.c" funciton."main_loop" line."56"
    void main_loop(void) {
    s = bootdelay_process();
    if (cli_process_fdt(&s))
        cli_secure_boot_cmd(s);
    
    autoboot_command(s);
    }

    bootcmd的函数实体通过预先定义好命令序列。

    //file."common/cmd_sunxi_flash.c" funciton.U_BOOT_CMD line.176
    U_BOOT_CMD(
        sunxi_flash, CONFIG_SYS_MAXARGS, 1, do_sunxi_flash,

    完成boot image的查找查找android 引导分区,为kernel 跳转查找基地址;

    //file.common/cmd_sunxi_flash.c function.sunxi_flash_read_all line.30
    static int sunxi_flash_read_all(u32 start, ulong buf, const char *part_name)
    {
        int ret;
        u32 rbytes, rblock;
        u32 start_block = start;
        void *addr;
        struct andr_img_hdr *fb_hdr;
    
        addr = (void *)buf;
        ret = sunxi_flash_read(start_block, SUNXI_FLASH_READ_FIRST_SIZE/512, addr);
    //file."common/cmd_boota.c" funciton.U_BOOT_CMD line.284
    U_BOOT_CMD(
        boota,    3,    1,    do_boota,

    在这里完成boot到kernel 基地址跳转;

    //file."common/cmd_boota.c" funciton.do_boota_linux line.147
    int do_boota_linux (struct andr_img_hdr *hdr,void * dtb_base)
    {
        int fake = 0;
        Kernel_Entry kernel_entry = NULL;
        //通过预先解析过的boot image 获取kernel的基地址;
        kernel_entry = (Kernel_Entry)(ulong)(hdr->kernel_addr);
        
        debug("## Transferring control to Linux (at address %lx)...\n",
            (ulong) kernel_entry);
    
        
        //while(*(uint*)(0x4a000000) != 9);
    #ifdef CONFIG_ARM64
        do_nonsec_virt_switch();
        announce_and_cleanup(fake);
        //直接绝对地址跳转;
        kernel_entry(dtb_base);
    #else
    }

III. 日志

提示:如下日志// 注释部分表示对应代码位置,->之前的第一个标签同如上流程图一一对应。
//board_init_f->display_text_info(file line.944)
U-Boot 2014.07 (Sep 16 2015 - 18:08:34) Allwinner Technology 

uboot commit : ad5f4db37d600c2566902ed7e243eaa9b670a563
 
rsb: secure monitor exist
//board_init_f->init_func_pmubus(line.978)
[      0.366]pmbus:   ready
[      0.368][ARISC] :arisc initialize
[      0.697][ARISC] :arisc_dvfs_cfg_vf_table: support only one vf_table
[SCP] :sunxi-arisc driver begin startup 2
[SCP] :arisc_para size:1a8
[SCP] :arisc version: [v0.1.76]
[SCP] :sunxi-arisc driver v1.10 is starting
[      0.824][ARISC] :sunxi-arisc driver startup succeeded

//
[      0.857]PMU: AXP81X
[      0.859]PMU: read AXP81X 84H=0xf2
[      0.862]PMU: write AXP81X 84H=0xf6
[      0.866]PMU: AXP81X found
bat_vol=0, ratio=100
[      0.872]PMU: dcdc2 1100
[      0.875]PMU: cpux 1008 Mhz,AXI=336 Mhz
PLL6=600 Mhz,AHB1=200 Mhz, APB1=100Mhz AHB2=300Mhz MBus=400Mhz
device_type = 3253, onoff=1
dcdc1_vol = 3000, onoff=1
dcdc2_vol = 1100, onoff=1
dcdc5_vol = 1350, onoff=1
dcdc6_vol = 1100, onoff=1
aldo1_vol = 2800, onoff=0
aldo2_vol = 3300, onoff=1
aldo3_vol = 3000, onoff=1
dldo1_vol = 3300, onoff=0
dldo2_vol = 3300, onoff=0
dldo3_vol = 2800, onoff=0
dldo4_vol = 3300, onoff=1
eldo1_vol = 1800, onoff=1
eldo2_vol = 1800, onoff=0
eldo3_vol = 1800, onoff=0
fldo2_vol = 1100, onoff=1
gpio0_vol = 3100, onoff=0
vbus not exist
no battery, limit to dc
//board_init_f->init_func_pmubus(line.980)
run key detect
no key found
no uart input
//board_init_f->announce_dram_init(line.982)
DRAM:  1008 MiB
//board_init_f->reloc_fdt(line.1058)
fdt addr: 0x76eb8420
//board_init_f->setup_reloc(line.1060)
Relocation Offset is: 35f0a000
In:    serial
Out:   serial
Err:   serial
gic: sec monitor mode
//board_init_r->initr_sunxi_display(line.443)
[      1.185]start
drv_disp_init
init_clocks: finish init_clocks.
fdt_get_one_gpio lcd0.lcd_gpio_0 fail
fdt_get_one_gpio lcd0.lcd_gpio_1 fail
fdt_get_one_gpio lcd0.lcd_gpio_2 fail
fdt_get_one_gpio lcd0.lcd_gpio_3 fail
fdt_get_one_gpio lcd0.lcd_gpio_scl fail
fdt_get_one_gpio lcd0.lcd_gpio_sda fail
enable power vcc-hdmi-33, ret=0
drv_disp_init finish
boot_disp.output_disp=0
boot_disp.output_type=1
boot_disp.output_type=4
fetch script data boot_disp.auto_hpd fail
disp0 device type(1) enable
enable power vcc-dsi-33, ret=0
disp 0, clk: pll(180000000),clk(180000000),dclk(30000000) dsi_rate(180000000)
     clk real:pll(178200000),clk(178200000),dclk(29700000) dsi_rate(0)
enable power vcc-mipi, ret=0
enable power vcc-pd, ret=0
FDT ERROR:format gpio lcdd2
[      1.751]end
//init_sequence_r->initr_sunxi_flash(line.445)->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
workmode = 0,storage type = 2
//init_sequence_r->initr_sunxi_flash(line.445)
//->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
//->sunxi_flash_boot_handle(file.sunxi_flash.c line.230)
//->sdmmc_init_for_boot(sdmmc.c line.163)
[      1.755]MMC:        2
[mmc]: mmc driver ver 2015-07-29 14:10:00
[mmc]: get sdc_ex_dly_used 2, use auto tuning sdly
SUNXI SD/MMC: 2
[mmc]: start mmc_calibrate_delay_unit, don't access device...
[mmc]: delay chain cal done, sample: 192(ps)
[mmc]: delay chain cal done, ds: 200(ps)
[mmc]: media type 0x8000000
[mmc]: ************Try MMC card 2************
[mmc]: host caps: 0x6f
[mmc]: MID 000015 PSN 3991bcc7
[mmc]: PNM 8WMB3R -- 0x38-57-4d-42-33
[mmc]: PRV 0.1
[mmc]: MDT m-6 y-2014
[mmc]: MMC v5.0
[mmc]: speed mode     : HSSDR52/SDR25 
[mmc]: clock          : 50000000 Hz
[mmc]: bus_width      : 8 bit
[mmc]: user capacity  : 7456 MB
[mmc]: boot capacity  : 4096 KB
[mmc]: rpmb capacity  : 512 KB
[mmc]: ************SD/MMC 2 init OK!!!************
[mmc]: erase_grp_size      : 0x400WrBlk*0x200=0x80000 Byte
[mmc]: secure_feature      : 0x55
[mmc]: secure_removal_type : 0x9
[mmc]: EOL Info(Rev blks): Normal
[mmc]: Wear out(type A): 0%-10% life time used
[mmc]: Wear out(type B): 0%-10% life time used
[      2.090]sunxi flash init ok
//init_sequence_r->initr_sunxi_base (line.445)->board_late_init->board_late_init->sunxi_fastboot_init
--------fastboot partitions--------
-total partitions:6-
-name-        -start-       -size-      
boot-res    : 1000000       1000000     
env         : 2000000       1000000     
boot        : 3000000       2000000     
rootfs      : 5000000       0           
klog        : 5000000       1000000     
UDISK       : 6000000       0           
-----------------------------------
base bootcmd=run setargs_nand boot_normal
bootcmd set setargs_mmc
key 0
recovery key high 12, low 10
fastboot key high 6, low 4
no misc partition is found
to be run cmd=run setargs_mmc boot_normal
update dtb dram start
update dtb dram  end
serial is: 441050374818280c070f
//init_sequence_r->PowerCheck line.450
no battery exist
//init_sequence_r->PowerCheck line.450->EnterNormalBootMode file.powerchek.c line.252
sunxi_bmp_logo_display
reading bootlogo.bmp
668628 bytes read in 22 ms (29 MiB/s)
bmp file buffer: 0x41000000, bmp_info.buffer: 47400000
fetch script data boot_disp.output_full fail
screen_id =0, screen_width =480, screen_height =800
frame buffer address 47400036
//init_sequence_r->run_main_loop line.452
[      2.642]inter uboot shell
//mainloop->file.autoboot.c function.autoboot_command line.280 
Hit any key to stop autoboot:  0 
//do_sunxi_flash->file.cmd_sunxi_flash.c function.do_sunxi_flash line.71
read partition: boot or recovery
[      4.161]sunxi flash read :offset 3000000, 16816300 bytes OK
Android's image name: sun50i
Kernel load addr 0x41080000 size 12722 KiB
RAM disk load addr 0x42000000 size 2677 KiB
[      4.389]ready to boot
//do_boota-> file.cmd_boota.c line.147 function.do_boota_linux
prepare for kernel
[mmc]: mmc exit start
[mmc]: start mmc_calibrate_delay_unit, don't access device...
[mmc]: delay chain cal done, sample: 200(ps)
[mmc]: delay chain cal done, ds: 200(ps)
[mmc]: mmc 2 exit ok

Starting kernel ...

mmc

详细分析mmc初始化流程。

//init_sequence_r->initr_sunxi_flash(line.445)
//->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
//->sunxi_flash_boot_handle(file.sunxi_flash.c line.230)
//->sdmmc_init_for_boot(sdmmc.c line.163)
[      1.755]MMC:        2
[mmc]: mmc driver ver 2015-07-29 14:10:00
[mmc]: get sdc_ex_dly_used 2, use auto tuning sdly
SUNXI SD/MMC: 2
[mmc]: start mmc_calibrate_delay_unit, don't access device...
[mmc]: delay chain cal done, sample: 192(ps)
[mmc]: delay chain cal done, ds: 200(ps)
//init_sequence_r->initr_sunxi_flash(line.445)
//->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
//->sunxi_flash_boot_handle(file.sunxi_flash.c line.230)
//->sdmmc_init_for_boot(sdmmc.c line.163)
//->mmc_init(drivers/mmc.c line.2722)
//->mmc_init_boot(drivers/mmc.c line.2568)
//->mmc_start_init(drivers/mmc.c line.2121)
[mmc]: media type 0x8000000
[mmc]: ************Try MMC card 2************
//init_sequence_r->initr_sunxi_flash(line.445)
//->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
//->sunxi_flash_boot_handle(file.sunxi_flash.c line.230)
//->sdmmc_init_for_boot(sdmmc.c line.163)
//->mmc_init(drivers/mmc.c line.2722)
//->mmc_init_boot(drivers/mmc.c line.2568)
//->mmc_complete_init(drivers/mmc.c line.2253)
//->mmc_startup(drivers/mmc.c line.1489)
[mmc]: host caps: 0x6f
[mmc]: MID 000015 PSN 3991bcc7
[mmc]: PNM 8WMB3R -- 0x38-57-4d-42-33
[mmc]: PRV 0.1
[mmc]: MDT m-6 y-2014
[mmc]: MMC v5.0
[mmc]: speed mode     : HSSDR52/SDR25 
[mmc]: clock          : 50000000 Hz
[mmc]: bus_width      : 8 bit
[mmc]: user capacity  : 7456 MB
[mmc]: boot capacity  : 4096 KB
[mmc]: rpmb capacity  : 512 KB
[mmc]: ************SD/MMC 2 init OK!!!************
//init_sequence_r->initr_sunxi_flash(line.445)
//->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
//->sunxi_flash_boot_handle(file.sunxi_flash.c line.230)
//->sdmmc_init_for_boot(sdmmc.c line.163)
//->mmc_init_boot (drivers/mmc.c line.2596)
[mmc]: erase_grp_size      : 0x400WrBlk*0x200=0x80000 Byte
[mmc]: secure_feature      : 0x55
[mmc]: secure_removal_type : 0x9
//init_sequence_r->initr_sunxi_flash(line.445)
//->sunxi_flash_handle_init(file.sunxi_flash.c line.309)
//->sunxi_flash_boot_handle(file.sunxi_flash.c line.230)
//->sdmmc_init_for_boot(sdmmc.c line.163)
//->mmc_init_boot (drivers/mmc.c line.2596)
//->mmc_mmc_parse_health_report  (drivers/mmc.c line.2499)
[mmc]: EOL Info(Rev blks): Normal
[mmc]: Wear out(type A): 0%-10% life time used
[mmc]: Wear out(type B): 0%-10% life time used
[      2.090]sunxi flash init ok

IV. lcd

uboot中disp init流程

allwinner a64支持uboot阶段显示静态图片,这里梳理程序结构,确定gac-350未什么未生效,同时确定从boot->rootfs 整个过程显示蓝屏的根本原因。

//board_init_r->initr_sunxi_display(line.443)
[      1.185]start
//board_init_r->initr_sunxi_display(line.443)->drv_disp_init(dev_disp.c line274)
drv_disp_init
//board_init_r->initr_sunxi_display(line.443)
//->drv_disp_init(dev_disp.c line274)
//->init_clocks(clk_sun50iw1.c line.655) 
init_clocks: finish init_clocks.
//board_init_r->initr_sunxi_display(board_r.c line.443)
//->drv_disp_init(dev_disp.c line274)
//->bsp_disp_init(disp_display.c line.5)
//->disp_init_lcd(disp_lcd.c line.2042)
//->disp_lcd_init(disp_lcd.c line.1966)
//->lcd_get_sys_config(disp_lcd.c line.601)
fdt_get_one_gpio lcd0.lcd_gpio_0 fail
fdt_get_one_gpio lcd0.lcd_gpio_1 fail
fdt_get_one_gpio lcd0.lcd_gpio_2 fail
fdt_get_one_gpio lcd0.lcd_gpio_3 fail
fdt_get_one_gpio lcd0.lcd_gpio_scl fail
fdt_get_one_gpio lcd0.lcd_gpio_sda fail
enable power vcc-hdmi-33, ret=0
drv_disp_init finish
//board_init_r->initr_sunxi_display(line.443)
//->drv_disp_init(dev_disp.c line274)
//->init_clocks(clk_sun50iw1.c line.655) 
boot_disp.output_disp=0
boot_disp.output_type=1
boot_disp.output_type=4
fetch script data boot_disp.auto_hpd fail
disp0 device type(1) enable
enable power vcc-dsi-33, ret=0
disp 0, clk: pll(180000000),clk(180000000),dclk(30000000) dsi_rate(180000000)
     clk real:pll(178200000),clk(178200000),dclk(29700000) dsi_rate(0)
enable power vcc-mipi, ret=0
enable power vcc-pd, ret=0
FDT ERROR:format gpio lcdd2
[      1.751]end

从如上代码走的来看,lcd完整驱动区分如下层次关系;

提示: 在/u-boot-2014.07/drivers/video/sunxi/disp2/disp/u-boot-2014.07/drivers/video/sunxi/sunxi_v3 同时保存了a64的显示驱动,从打印日志来看使用了前者。
st=>start: board_r.c
op0=>operation: dev_disp.c
op1=>operation: disp_display.c
e=>end: disp_lcd.c

st->op0->op1->e

kernel中disp init流程

此uboot中的disp模块同内核/linux-3.10/drivers/video/sunxi/disp2/disp中的一一对应。

[DISP]disp_module_init
[DISP] boot_disp:0x104
[DISP] disp_sys_script_get_item,line:193:of_find_compatible_node allwinner,sunxi-lcd1 fail
[DISP] disp_sys_script_get_item,line:193:of_find_compatible_node allwinner,sunxi-lcd1 fail
[DISP] disp_sys_script_get_item,line:193:of_find_compatible_node allwinner,sunxi-lcd1 fail
[DISP] fb_base:0x47400000
[DISP] lcd_clk_config,line:808:disp 0, clk: pll(180000000),clk(180000000),dclk(30000000) dsi_rate(180000000)
     clk real:pll(178200000),clk(178200000),dclk(29700000) dsi_rate(0)
[DISP]disp_module_init finish

不同的是,内核中的显示驱动通过内核模块的方式加载。也就是,在uboot通过的boardc_r.c 直接通过调用initr_sunxi_display 完成液晶初始化,但是内核模块中的驱动通过disp_module_init开始显示驱动的初始化。

st=>start: disp_module_init(dev_disp.c)
op0=>operation: dev_disp(dev_disp.c)
op1=>operation: disp_display.c
e=>end: disp_lcd.c

st->op0->op1->e

V. emmc

boot0

uboot

  • 预初始化

    ->drivers/mmc/sun50iw1p1

  • 程序流

    ->common/board_r.c

    ->drivers/sunxi_flash/sunxi_flash.c

    ->drivers/sunxi_flash/sdmmc.c

    ->drivers/mmc/mmc.c

    ->arch/arm/cpu/armv7/sun50iw1p1/mmc/mmc.c

    st=>start: board_r.c
    op0=>operation: sunxi_flash.c
    op1=>operation: sdmmc.c
    op2=>operation: mmc.c
    e=>end: mmc.c
    
    st->op0->op1->op2->e

kernel

SD/MMC/SDIO Host Controller Driver(v0.63 2016-10-13 13:39-patch201611081726) Compiled in Aug  1 2018 at 12:55:32
regulator prop vmmc,str vcc-emmc
regulator prop vqmmc,str vcc-lpddr
regulator prop vdmmc,str none
No vqmmc regulator found
No vdmmc regulator found
sdc set ios: clk 0Hz bm PP pm UP vdd 22 width 1 timing LEGACY(SDR12) dt B
sdc set ios: clk 400000Hz bm PP pm ON vdd 22 width 1 timing LEGACY(SDR12) dt B
base:0xffffff80000c2000 irq:94

dts->proble->

VI. Troubleshooting

./arm-trusted-firmware-1.0/Makefile-431-        @echo
./arm-trusted-firmware-1.0/Makefile-432-ifeq (bl31.bin,$(notdir ${BIN}))
./arm-trusted-firmware-1.0/Makefile:433:        $${Q}git show HEAD --pretty=format:"%H" | head -n 1 > cur.log
./arm-trusted-firmware-1.0/Makefile-434-        $${Q}./tools/add_hash_bl31.sh -f $$@ -m bl31
./arm-trusted-firmware-1.0/Makefile-435-endif
--
./u-boot-2014.07/Makefile-837-  $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
./u-boot-2014.07/Makefile-838-  $(BOARD_SIZE_CHECK)
./u-boot-2014.07/Makefile:839:  @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log
./u-boot-2014.07/Makefile-840-  ./tools/add_hash_uboot.sh -f u-boot.bin -m uboot
./u-boot-2014.07/Makefile-841-

sd 启动并且成功挂载emmc

  • 修改u-boot makefile 确保没有.git 目录能够正确填入hash值;
  • 修改u-boot初始化逻辑,去掉通过sd卡启动,禁止dts的逻辑;

    fdt_set_node_status(dtb_base,nodeoffset_emmc,FDT_STATUS_DISABLED,0);
  • 修改ramdisk默认从/dev/mmcblk1p7 加载rootfs;
  • 修改env.cfg 分区默认root分区为/dev/mmcblk1


本文由 Jay 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处,点赞2

还不快抢沙发

添加新评论