android kernel启动学习笔记

1.wiki百科上的booting关于移动设备的描述

Some modern CPUs and microcontrollers (for example, TI OMAP) or sometimes even DSPs may have boot ROM with boot code integrated directly into their silicon, so such a processor could perform quite a sophisticated boot sequence on its own and load boot programs from various sources like NAND flash, SD or MMC card and so on. It is hard to hardwire all the required logic for handling such devices, so an integrated boot ROM is used instead in such scenarios. Boot ROM usage enables more flexible boot sequences than hardwired logic could provide. For example, the boot ROM could try to perform boot from multiple boot sources. Also, a boot ROM is often able to load a boot loader or diagnostic program via serial interfaces like UARTSPIUSB and so on. This feature is often used for system recovery purposes when for some reasons usual boot software in non-volatile memory got erased, and it could also be used for initial non-volatile memory programming when there is clean non-volatile memory installed and hence no software available in the system yet.

Some embedded system designs may also include an intermediary boot sequence step in form of additional code that gets loaded into system RAM by the integrated boot ROM. Additional code loaded that way usually serves as a way for overcoming platform limitations, such as small amounts of RAM, so a dedicated primary boot loader, such asDas U-Boot, can be loaded as the next step in system's boot sequence. The additional code and boot sequence step are usually referred to as secondary program loader(SPL).

再看一下MT6253的启动顺序(摘自6253 datasheet)

2.UBOOT在启动第一阶段把自己拷贝到RAM运行,跳转到start_armboot,进入启动的第二个阶段。

start_armboot是启动流程的核心。里面有个重要的初始化数组

init_fnc_t *init_sequence[] = {
	cpu_init,		/* basic cpu dependent setup */
	dram_init,              /* configure available RAM banks */ /*  change the original init order */
	board_init,		/* basic board dependent setup */
	interrupt_init,		/* set up exceptions */
	env_init,		/* initialize environment */
	init_baudrate,		/* initialze baudrate settings */
	serial_init,		/* serial communications setup */
	console_init_f,		/* stage 1 init of console */
	display_banner,		/* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
	print_cpuinfo,		/* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
	checkboard,		/* display board info */
#endif
	display_dram_config,
	NULL,
};

 .......

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) 
    {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }    

在它们执行完之后。

3.调用env_relocate ();初始化UBOOT环境变量,这个非常关键。调用函数进行默认环境变量初始化set_default_env();利用数组:

uchar default_environment[] = {
#ifdef    CONFIG_BOOTARGS
    "bootargs="    CONFIG_BOOTARGS            ""
#endif
#ifdef    CONFIG_BOOTCOMMAND
    "bootcmd="    CONFIG_BOOTCOMMAND        ""
#endif
#ifdef    CONFIG_RAMBOOTCOMMAND
    "ramboot="    CONFIG_RAMBOOTCOMMAND        ""
#endif
#ifdef    CONFIG_NFSBOOTCOMMAND
    "nfsboot="    CONFIG_NFSBOOTCOMMAND        ""
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
    "bootdelay="    MK_STR(CONFIG_BOOTDELAY)    ""
#endif
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
    "baudrate="    MK_STR(CONFIG_BAUDRATE)        ""
#endif
#ifdef    CONFIG_LOADS_ECHO
    "loads_echo="    MK_STR(CONFIG_LOADS_ECHO)    ""
#endif
#ifdef    CONFIG_ETHADDR
    "ethaddr="    MK_STR(CONFIG_ETHADDR)        ""
#endif
#ifdef    CONFIG_ETH1ADDR
    "eth1addr="    MK_STR(CONFIG_ETH1ADDR)        ""
#endif
#ifdef    CONFIG_ETH2ADDR
    "eth2addr="    MK_STR(CONFIG_ETH2ADDR)        ""
#endif
#ifdef    CONFIG_ETH3ADDR
    "eth3addr="    MK_STR(CONFIG_ETH3ADDR)        ""
#endif
#ifdef    CONFIG_ETH4ADDR
    "eth4addr="    MK_STR(CONFIG_ETH4ADDR)        ""
#endif
#ifdef    CONFIG_ETH5ADDR
    "eth5addr="    MK_STR(CONFIG_ETH5ADDR)        ""
#endif
#ifdef    CONFIG_IPADDR
    "ipaddr="    MK_STR(CONFIG_IPADDR)        ""
#endif
#ifdef    CONFIG_SERVERIP
    "serverip="    MK_STR(CONFIG_SERVERIP)        ""
#endif
#ifdef    CONFIG_SYS_AUTOLOAD
    "autoload="    CONFIG_SYS_AUTOLOAD            ""
#endif
#ifdef    CONFIG_PREBOOT
    "preboot="    CONFIG_PREBOOT            ""
#endif
#ifdef    CONFIG_ROOTPATH
    "rootpath="    MK_STR(CONFIG_ROOTPATH)        ""
#endif
#ifdef    CONFIG_GATEWAYIP
    "gatewayip="    MK_STR(CONFIG_GATEWAYIP)    ""
#endif
#ifdef    CONFIG_NETMASK
    "netmask="    MK_STR(CONFIG_NETMASK)        ""
#endif
#ifdef    CONFIG_HOSTNAME
    "hostname="    MK_STR(CONFIG_HOSTNAME)        ""
#endif
#ifdef    CONFIG_BOOTFILE
    "bootfile="    MK_STR(CONFIG_BOOTFILE)        ""
#endif
#ifdef    CONFIG_LOADADDR
    "loadaddr="    MK_STR(CONFIG_LOADADDR)        ""
#endif
#ifdef  CONFIG_CLOCKS_IN_MHZ
    "clocks_in_mhz=1"
#endif
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
    "pcidelay="    MK_STR(CONFIG_PCI_BOOTDELAY)    ""
#endif
#ifdef  CONFIG_EXTRA_ENV_SETTINGS
    CONFIG_EXTRA_ENV_SETTINGS
#endif
    ""
};

比如 "bootcmd="    CONFIG_BOOTCOMMAND        ""。这个环境变量,最终会通过它来启动系统。CONFIG_BOOTCOMMAND定义类似

#define CONFIG_BOOTCOMMAND   "msdc_boot;nand_boot" /* autoboot command */

4.start_armboot在初始化完环境变量之后会调用

    /* main_loop() can return to retry autoboot, if so just run it again */
    for (;;) {
        main_loop ();
    }

5.main_loop会获取刚才环境变量配置里的UBOOT启动内核命令,并执行。

  s = getenv ("bootcmd");

 ....
  run_command (s, 0);

 比如执行nand_boot。

6.会调用do_nand_boot()函数。它会根据g_boot_mode决定启动方式。

    switch(g_boot_mode)
    {
        
        case NORMAL_BOOT:
          ....
  ret = mboot_android_load_bootimg(PART_BOOTIMG, CFG_BOOTIMG_LOAD_ADDR);  
          ....
case META_BOOT: 。。。 case ADVMETA_BOOT: 。。。 case RECOVERY_BOOT: 。。。 case FACTORY_BOOT: 。。。 case ATE_FACTORY_BOOT: 。。。 case SW_REBOOT: 。。。 case ALARM_BOOT: 。。。 }

 正常启动时  ret = mboot_android_load_bootimg(PART_BOOTIMG, CFG_BOOTIMG_LOAD_ADDR);  这个函数会把给定的映象分区拷贝到CFG_BOOTIMG_LOAD_ADDR所指定的RAM区域执行。

原文地址:https://www.cnblogs.com/chyl411/p/3224505.html