记录自己学习android系统启动以及 recovery过程(1)----------uboot

记录自己学习android系统启动以及 recovery过程(1)----------uboot

欢迎指出其中错误。

启动uboot bootm文件作为uboot->kernel的最后一个步骤,负责引导内核,并配置需要传递进内核的相关参数

在uboot启动后,会检查是否需要recovery,一般通过两个途径, 1.挂载boot device,并查看/cache/recovery文件,2.按键检测,当需要进行recovery时,会重新设置启动的环境变量。

system image和recovery的环境变量主要区别在于:

system :   bootm (kernel_addr)  (ramdisk_addr)

recovery:   bootm或者bootm (kernel_addr)   root=/dev/mmcblk0px

uboot阶段通过对bootm代码的执行,来设置传递进内核的参数,通知内核是挂载recovery 还是运行system。

相关代码分析:

1. do_bootm函数

int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    ulong        iflag;
    ulong        load_end = 0;
    int        ret;
    boot_os_fn    *boot_fn;

    /* relocate boot function table */   
    /*重定位 boot_os内部函数指针地址,启动包含do_bootm_linux。因为在uboot启动的最初阶段,会对uboot的text,data,bss..进行一次搬移*/
    if (!relocated) {
        int i;
        for (i = 0; i < ARRAY_SIZE(boot_os); i++)
            if (boot_os[i] != NULL)
                boot_os[i] += gd->reloc_off;
        relocated = 1;
    }

    /* determine if we have a sub command */
    /* 当传进来参数多于一个时,判断参数类型,并执行。在android正常启动模式下,参数模式是 bootm kernel_addr rd_addr,多于3个,但是参数endp是0,不会return*/
    if (argc > 1) {
        char *endp;

        simple_strtoul(argv[1], &endp, 16);
        /* endp pointing to NULL means that argv[1] was just a
         * valid number, pass it along to the normal bootm processing
         *
         * If endp is ':' or '#' assume a FIT identifier so pass
         * along for normal processing.
         *
         * Right now we assume the first arg should never be '-'
         */
        if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
            return do_bootm_subcommand(cmdtp, flag, argc, argv);
    }
    /* do_bootm重要函数,主要用来查看,验证 uImage, ramdisk,并初始化一个结构体images,类型为bootm_headers_t,后续会详细解析*/
    if (bootm_start(cmdtp, flag, argc, argv))
        return 1;

    /*
     * We have reached the point of no return: we are going to
     * overwrite all exception vector code, so we cannot easily
     * recover from any failures any more...
     */
    iflag = disable_interrupts();

#if defined(CONFIG_CMD_USB)
    /*
     * turn off USB to prevent the host controller from writing to the
     * SDRAM while Linux is booting. This could happen (at least for OHCI
     * controller), because the HCCA (Host Controller Communication Area)
     * lies within the SDRAM and the host controller writes continously to
     * this area (as busmaster!). The HccaFrameNumber is for example
     * updated every 1 ms within the HCCA structure in SDRAM! For more
     * details see the OpenHCI specification.
     */
    usb_stop();
#endif

#ifdef CONFIG_AMIGAONEG3SE
    /*
     * We've possible left the caches enabled during
     * bios emulation, so turn them off again
     */
    icache_disable();
    dcache_disable();
#endif
    /*下面函数,是用来将kernel的uImage 解压并拷贝到指定的运行地址*/
    ret = bootm_load_os(images.os, &load_end, 1);

    if (ret < 0) {
        if (ret == BOOTM_ERR_RESET)
            do_reset (cmdtp, flag, argc, argv);
        if (ret == BOOTM_ERR_OVERLAP) {
            if (images.legacy_hdr_valid) {
                if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
                    puts ("WARNING: legacy format multi component "
                        "image overwritten\n");
            } else {
                puts ("ERROR: new format image overwritten - "
                    "must RESET the board to recover\n");
                show_boot_progress (-113);
                do_reset (cmdtp, flag, argc, argv);
            }
        }
        if (ret == BOOTM_ERR_UNIMPLEMENTED) {
            if (iflag)
                enable_interrupts();
            show_boot_progress (-7);
            return 1;
        }
    }

    lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));

    if (images.os.type == IH_TYPE_STANDALONE) {
        if (iflag)
            enable_interrupts();
        /* This may return when 'autostart' is 'no' */
        bootm_start_standalone(iflag, argc, argv);
        return 0;
    }

    show_boot_progress (8);

#ifdef CONFIG_SILENT_CONSOLE
    if (images.os.os == IH_OS_LINUX)
        fixup_silent_linux();
#endif
    /*image.os.os在bootm_start函数中被初始化,此处,boot_fn就等于do_bootm_linux*/
    boot_fn = boot_os[images.os.os];

    if (boot_fn == NULL) {
        if (iflag)
            enable_interrupts();
        printf ("ERROR: booting os '%s' (%d) is not supported\n",
            genimg_get_os_name(images.os.os), images.os.os);
        show_boot_progress (-8);
        return 1;
    }
    /*调用do_bootm_linux引导内核并启动*/
    boot_fn(0, argc, argv
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值