查看: 3635|回复: 0

uboot 完整源码追踪注释

[复制链接]
  • TA的每日心情
    开心
    2024-1-16 17:48
  • 签到天数: 592 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2018-8-15 09:04:13 | 显示全部楼层 |阅读模式
    分享到:
    uboot 完整的源码追踪注释,代码比较多,细节会有错误,程序走向没有问题,
    从第一行代码 :b  reset
    到最后一行:kernel_entry(0, machid, r2);
    完整源码追踪做了注释
    本文格式:缩进代表是上层函数的子函数,像 python 那样。括号中是文件全路径。
    u-boot.lds(arch/arm/lib/vectors.S)                                                                .globl         _start        b        reset        ldr        pc, _undefined_instruction        ldr        pc, _software_interrupt        ldr        pc, _prefetch_abort        ldr        pc, _data_abort        ldr        pc, _not_used        ldr        pc, _irq        ldr        pc, _fiq                                                                .globl        _undefined_instruction                                                                .globl        _software_interrupt                                                                .globl        _prefetch_abort                                                                .globl        _data_abort                                                                .globl        _not_used                                                                .globl        _irq                                                                .globl        _fiq                                                                                                                                _undefined_instruction:        .word undefined_instruction                                                                _software_interrupt:        .word software_interrupt                                                                _prefetch_abort:        .word prefetch_abort                                                                _data_abort:                .word data_abort                                                                _not_used:                .word not_used                                                                _irq:                        .word irq                                                                _fiq:                        .word fiq                                                                                                                                .globl IRQ_STACK_START_IN        IRQ_STACK_START_IN:                                                                .globl IRQ_STACK_START        IRQ_STACK_START:                                                                .globl FIQ_STACK_START        FIQ_STACK_START:                中断处理函数:                                寄存器压栈,处理结束,弹栈                do_undefined_instruction                do_software_interrupt                do_prefetch_abort                do_data_abort                do_not_used                do_irq                do_fiq                                        (arch/arm/lib/interrupts.c)        (arch/arm/cpu/armv7/start.S)        .reset        .save_boot_params_ret        reset:                                                                save_boot_params_ret:        关闭FIQ/IRQ, 设置SVC32,或者进HYP模式                                                                设置向量表_start(定义CONFIG_SPL_BUILD)                cpu_init_cp15:                        关mmu,关caches,开i-cache                cpu_init_crit:                        lowlevel_init:                设置sp指针=CONFIG_SYS_INIT_SP_ADDR,                                                                清零r9,=0(定义CONFIG_SPL_DM)                                                                设置r9,=gdata(定义CONFIG_SPL_BUILD)                                                                设置r9,放到 sp 空间上面                                 s_init:                设置PLL                _main:(arch/arm/lib/crt0.S_main        ldr        sp, =(CONFIG_SYS_INIT_SP_ADDR):                设置sp                #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)                #define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR                #define IRAM_BASE_ADDR 0x00900000                #define CONFIG_SYS_INIT_SP_OFFSET (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)                #define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE                #define IRAM_SIZE 0x00020000        board_init_f_alloc_reserve:                (common/init/board_init.c:                保留1k空间                                                                                        设置r9        board_init_f_init_reserve:                (common/init/board_init.c:                设置gd->malloc_base        board_init_f:                (common/board_f.c:                                清零gd空间,设置gd->flags=0,gd->have_console=0                initcall_run_list:                        init_sequence_fcommon/board_f.c)init_sequence_f:        setup_mon_len:                                                        设置gd->mon_len = (ulong)&__bss_end - (ulong)_start;        initf_malloc:                                                        设置gd->malloc_ptr = 0;设置gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;        initf_console_record:                                        空        arch_cpu_init:                                                        (arch/arm/cpu/armv7/mx6)                init_aips:                clear_mmdc_ch_mask:                init_src:        initf_dm:                dm_init_and_scan:                                                                                dm_init:                                                        gd->dm_root存在,返回。不存在初始化gd->uclass_root                                device_bind_by_name:                                device_probe:                        dm_scan_platdata:                        dm_scan_other:        arch_cpu_init_dm:                                                空        mark_bootstage:                                                        添加record记录(static struct bootstage_record record[BOOTSTAGE_ID_COUNT] = { {1} };)        board_early_init_f:                                                (board/myir/mys_imx6ull/mys_imx6ull.c)        //修改1                setup_iomux_uart:                                        设置串口        timer_init:                                                        (arch/arm/imx-common/syscounter.c)                                                                                        初始化启动syscounter,清零gd->arch.tbl,gd->arch.tbu        board_postclk_init:                set_ldo_voltage:        get_clocks:                                                        设置gd->arch.sdhc_clk        env_init:                                                                设置gd->env_addr=default_environment[]地址,(include/env_default.h)                                                                                        设置gd->env_valid=1        init_baud_rate:                                                        设置gd->baudrate        serial_init:                                                        设置gd->flags |= GD_FLG_SERIAL_READY;                get_current:                        default_serial_console:                                mxc_serial_drv:                                        struct serial_device mxc_serial_drv={                                                .name        = "mxc_serial",                                                .start        = mxc_serial_init,                                                .stop        = NULL,                                                .setbrg        = mxc_serial_setbrg,                                                .putc        = mxc_serial_putc,                                                .puts        = default_serial_puts,                                                .getc        = mxc_serial_getc,                                                .tstc        = mxc_serial_tstc,                                        }                get_current()->start():                                初始化串口,并使能。(drivers/serial/serial_mxc.c)        console_init_f:                                                        设置gd->have_console=1,初始化console        display_options:                                                [打印]u-boot第一次开始输出信息,输出版本信息                                                                                                                                display_text_info:        print_cpuinfo:                                                        [打印]cpu信息,reset cause:por 信息        show_board_info:                                                [打印]board信息,(board/myir/mys_imx6ull/mys_imx6ull.c)        announce_dram_init:                                        puts打印信息        dram_init:                get_ram_size:                                                获取实际ram size,赋值给gd->ram_size        setup_dest_addr:                                                重新设置内存分配内存                                                                                        设置gd->relocaddr = gd->ram_top        reserve_round_4k:                                                设置gd->relocaddr 4k对齐        reserve_mmu:                                                        设置gd->arch.tlb_size,gd->arch.tlb_addr        reserve_trace:                                                        空        reserve_uboot:                                                        预留gd->mon_len        reserve_malloc:                                                预留TOTAL_MALLOC_LEN        reserve_board:                                                        预留gd->bd,设置gd->bd        setup_machine:                                                        设置gd->bd->bi_arch_number        reserve_global_data:                                        预留gd->new_gd空间,设置gd->new_gd        reserve_fdt:                                                        预留gd->new_fdt,设置gd->new_fdt        arch_reserve_stacks:                                        预留gd->irq_sp,设置gd->irq_sp        dram_init_banksize:                                        设置gd->bd->bi_dram[0].start,                                                                                        设置gd->bd->bi_dram[0].size        show_dram_config:                                                [打印]dram信息        display_new_sp:                                                        [打印]gd->start_addr_sp信息(已设置gd->start_addr_sp)        setup_board_extra:                                                设置gd->bd->bi_s_version,                                                                                        设置gd->bd->bi_r_version,                                                                                        设置gd->bd->bi_procfreq = gd->cpu_clk                                                                                        设置gd->bd->bi_plb_busfreq = gd->bus_clk        reloc_fdt:                                                                复制memcpy(gd->new_fdt, gd->fdt_blob, gd->fdt_size);                                                                                        设置gd->fdt_blob = gd->new_fdt;        setup_reloc:                                                        复制memcpy(gd->new_gd, (char *)gd, sizeof(gd_t));        未完接下页
    (arch/arm/lib/crt0.S_main                sp = gd->start_addr_sp        r9 = new GD        设置返回寄存器        r0 = gd->relocaddr        b relocate_code(arch/arm/lib/relocate.Srelocate_code                复制 __image_copy_start 和 __image_copy_end 之间代码(arch/arm/lib/crt0.S_main                        bl        relocate_vectors(arch/arm/lib/relocate.Srelocate_vectors        r0 = gd->relocaddr        复制代码(arch/arm/lib/crt0.S_main        bl        c_runtime_cpu_setup:关闭I-cache        清空bss        bl coloured_LED_init        bl red_led_on        mov     r0, r9                                        /* gd_t */        ldr        r1, [r9, #GD_RELOCADDR]                /* dest_addr */        ldr        pc, =board_init_r(common/baord_r.cboard_init_r                initcall_run_list:                init_sequence_rinit_sequence_r:        initr_reloc:                                                        设置gd->flags                gd->flags |= GD_FLG_RELOC | GD_FLG_FULL_MALLOC_INIT;        initr_caches:                                                        使能D-cache        initr_reloc_global_data:                                设置monitor_flash_len                monitor_flash_len = _end - __image_copy_start;        initr_barrier:                                                        空        initr_malloc:                                                        设置malloc_start,并初始化                malloc_start = gd->relocaddr - TOTAL_MALLOC_LEN;        initr_console_record:                                        空        bootstage_relocate:                                        复制record        initr_dm:                gd->dm_root_f = gd->dm_root;                gd->dm_root = NULL;        dm_init:                device_bind_by_name:                                初始化gd->dm_root,(udevice)        initr_bootstage:                                                空        board_init:                                                                                //修改2                gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;        设置变量                imx_iomux_v3_setup_multiple_pads                                初始化pads(gpio5:7/8/10/11) SNVS_TAMPER7/8 和 bootmode                iox74lv_init                                                                        检查boot mode                setup_i2c                                                                                设置pad,设置复用,使能clk                setup_fec                setup_usb                board_qspi_init                setup_gpmi_nand        stdio_init_tables:                                                初始化struct stdio_dev的list变量        initr_serial,                serial_initialize                                        初始化所有串口        initr_announce,                                                        打印信息        power_init_board:                                                空        initr_nand                                                                空        initr_onenand                                                        空        initr_mmc                mmc_initialize                        INIT_LIST_HEAD (&mmc_devices);        初始化mmc_devices                        mmc_probe                                                probe                        do_preinit                                                初始化mmc卡                        initr_dataflash                                                        空        initr_env                env_relocate                                                设置env,从emmc分配空间                load_addr = getenv_ulong("loadaddr", 16, load_addr);                设置load_addr        initr_malloc_bootparams                                        空        initr_secondary_cpu                                                空        mac_read_from_eeprom                                        空        stdio_add_devices,                drv_video_init                        board_video_skip                                找到displays,配置lcdif pad.                        video_init                                mxs_lcd_init                                设置lcdc                        stdio_register(&console_dev)        注册console_dev设备                drv_system_init                                                注册"serial"设备                serial_stdio_init                                        注册serial_device设备                drv_jtag_console_init                                注册"jtag"设备        initr_jumptable,                                                给gd->jt分配堆空间        console_init_r                console_setfile                                                设置stdio_devices[file] = dev;初始化gd->jf->getc/putc                setenv(stdio_names, stdio_devices->name)                        设置stdio_devices名字        interrupt_init                                                        中断初始化,设置堆栈指针 (中断处理实现在arch/arm/lib/interrupts.c)                IRQ_STACK_START = gd->irq_sp - 4;                IRQ_STACK_START_IN = gd->irq_sp + 8;                FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;        initr_enable_interrupts                                        开中断        initr_ethaddr                                                        获取环境变量ip地址,验证有效性        board_late_init                                                        增加sd/qspi启动模式,//修改3                setenv("board_name", "MYS6ULL");        设置环境变量                setenv("board_rev", "14X14");                board_late_mmc_env_init                                检测mmc是否启动设备                        mmc_get_env_dev                                        获取mmc启动设备                        getenv("mmcautodetect");                获取mmcautodetect环境变量,并判断是否等于yes,决定是否mmc启动                        strcmp(autodetect_str, "yes")                                                                                        设置环境变量mmcdev/mmcroot                        run_command(cmd, 0);                        执行cmd启动                                sprintf(cmd, "mmc dev %d", dev_no);                set_wdog_reset                                                使能看门狗        initr_net                                                                初始化,或者reset eth控制器                                                                initr_check_fastboot                                        是否需要从 fastboot 启动                run_main_loop                                                        主循环                main_loop                                                        陷入死循环执行 main_loop 中(common/main.c:)main_loop        cli_init                                                                cli环境初始化        run_preboot_environment_command                        获取preboot 环境变量,并执行        s = bootdelay_process();                bootdelay_process                        s = getenv("bootdelay");                获取bootdelay环境变量,保存到stored_bootdelsy                        stored_bootdelsy = s                                                retrun s;s = getenv("bootcmd");        返回bootcmd指令        if (cli_process_fdt(&s))                                查找设备树是否有bootcmd,有的话覆盖环境变量bootcmd,并执行bootcmd,然后hang                cli_secure_boot_cmd(s);                                (如果fdt设置了secureboot,就从fdt,bootcmd启动。)        autoboot_command(s);                                        如果在bootdelay时间内按了按键,不执行bootcmd,不然直接启动                run_command_list(s, -1, 0);                        启动前后关闭恢复disable_ctrlc 功能        cli_loop();(common/cli.c:)run_command_list(s, -1, 0)        parse_string_outer(buff, FLAG_PARSE_SEMICOLON);                =parse_string_outer("bootcmd", (1<<1));(common/cli_hush.c:)parse_string_outer        parse_stream_outer                run_list                        run_list_real                                run_pipe_real                                        cmd_process                                                cmd_call                                                        (cmdtp->cmd)(cmdtp, flag, argc, argv);(cmd/bootm.c)do_bootz        bootz_start        do_bootm_states                bootm_start                bootm_find_os                bootm_find_other                bootm_disable_interrupts                bootm_load_os                lmb_reserve                bootm_os_get_boot_func                boot_selected_os                        arch_preboot_os                        boot_fn                                do_bootm_linux                                        boot_prep_linux                                        boot_jump_linux                                                kernel_entry(0, machid, r2);源码到 kernel_entery 结束了,下一页看几个相关的东西

    几个结构,结构体,宏,环境变量等:kernel_entry, cmd_tbl_s,U_BOOT_CMD,env 。
    /* kernel_entry */void (*kernel_entry)(int zero, int arch, uint params);/* cmd_tbl_s / cmd_tbl_t 结构体 */struct cmd_tbl_s {        char                *name;                /* Command Name                        */        int                maxargs;        /* maximum number of arguments        */        int                repeatable;        /* autorepeat allowed?                */                                        /* Implementation function        */        int                (*cmd)(struct cmd_tbl_s *, int, int, char * const []);        char                *usage;                /* Usage message        (short)        */#ifdef        CONFIG_SYS_LONGHELP        char                *help;                /* Help  message        (long)        */#endif#ifdef CONFIG_AUTO_COMPLETE        /* do auto completion on the arguments */        int                (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);#endif};/* U_BOOT_CMD 宏定义解析 */U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)ll_entry_declare(cmd_tbl_t, _name, cmd) =        U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,_usage, _help, _comp);ll_entry_declare(cmd_tbl_t, _name, cmd) =        { #_name, _maxargs, _rep, _cmd, _usage,_CMD_HELP(_help) _CMD_COMPLETE(_comp) }//U_BOOT_CMD 宏解析结果,两种情况ll_entry_declare(cmd_tbl_t, _name, cmd) =        { #_name, _maxargs, _rep, _cmd, _usage,_help  _comp}ll_entry_declare(cmd_tbl_t, _name, cmd) =        { #_name, _maxargs, _rep, _cmd, _usage, }/* env */         baudrate=115200board_name=MYS6ULLboard_rev=14X14boot_fdt=trybootargs=console=ttymxc0,115200 root=/dev/nfs ip=dhcp nfsroot=:,v3,tcpbootcmd=run findfdt;mmc dev ${mmcdev};mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fibootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};bootdelay=3bootscript=echo Running bootscript from mmc ...; sourceconsole=ttymxc0ethact=FEC0ethprime=FECfdt_addr=0x83000000fdt_file=mys-imx6ull-14x14.dtbfdt_high=0xfffffffffindfdt=if test $fdt_file = undefined; then if test $board_name = EVK && test $board_rev = 9X9; then setenv fdt_file imx6ull-9x9-evk.dtb; fi; if test $board_name = MYS6ULL && test $board_rev = 14X14; then setenv fdt_file mys-imx6ull-14x14.dtb; fi; if test $fdt_file = undefined; then echo WARNING: Could not determine dtb to use; fi; fi;get_cmd=dhcpimage=zImageinitrd_addr=0x83800000initrd_high=0xffffffffip_dyn=yesloadaddr=0x80800000loadbootscript=fatload mmc ${mmcdev}{mmcpart} ${loadaddr} ${script};loadfdt=fatload mmc ${mmcdev}{mmcpart} ${fdt_addr} ${fdt_file}loadimage=fatload mmc ${mmcdev}{mmcpart} ${loadaddr} ${image}mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" clk_ignore_unused mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}mmcautodetect=yesmmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;mmcdev=0mmcpart=1mmcroot=/dev/mmcblk0p2 rootwait rwnetargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}{nfsroot},v3,tcpnetboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;panel=LCD050_800x480_Robescript=boot.scr        /* bootcmd */                /* 先从bootscript启动,再mmc启动(加载zImage fdt,bootz启动),其次net启动 */bootcmd=run findfdt;mmc dev ${mmcdev};mmc dev ${mmcdev};if mmc rescan; then                if run loadbootscript; then        run bootscript;        else if run loadimage; then        run mmcboot;                 else run netboot;                fi;        fi; else run netboot;fi;/* findfdt */ findfdt=if test $fdt_file = undefined; then         if test $board_name = EVK && test $board_rev = 9X9; then setenv fdt_file imx6ull-9x9-evk.dtb;         fi;         if test $board_name = MYS6ULL && test $board_rev = 14X14; then setenv fdt_file mys-imx6ull-14x14.dtb;         fi;         if test $fdt_file = undefined; then echo WARNING: Could not determine dtb to use;         fi; fi;        上一篇文章,uboot 屏幕源码解析,入口就是本文第二页 70 行代码,stdio_add_devices  指针函数。能看出来 uboot 屏幕源码只占 uboot 整个项目中很小的一部分,仅仅是一个环节而已。
    代码注释有可能不对,以后单独看局部代码时候再修改增加完善注释,后续更新的话再另开一篇。本文可以看看 uboot 整个源码大概走向,这个是没有问题的,本文达成这个目标就好。
    <完>
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-25 07:18 , Processed in 0.114758 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.