uboot code review
术语
术语 | 描述 |
---|---|
fdt | flattened device tree |
流程
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_f
和board_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 }
日志
提示:如下日志//
注释部分表示对应代码位置,->
之前的第一个标签同如上流程图一一对应。
//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
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
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->
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
还不快抢沙发