Android uboot

下面来看看uboot中lib_arm/board.c这个文件中的start_armboot这个函数,这个函数在start.s这个汇编文件中完成堆栈等一些基础动作之后被调用,进入到c的代码中,start_armboot部分代码如下:

void start_armboot (void)
{
       .
       .
       .
       for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
              if ((*init_fnc_ptr)() != 0) {
                     hang ();
              }
#ifdef CONFIG_ANDROID_RECOVERY
       check_recovery_mode();
#endif
       /* main_loop() can return to retry autoboot, if so just run it again. */
       for (;;) {
              main_loop ();
       }
}

init_sequence是一个函数结构体指针,里面存放的是一些必备的初始化函数,其代码如下:

init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
       arch_cpu_init,            /* basic arch cpu dependent setup */
#endif
       board_init,           /* basic board dependent setup */
#if defined(CONFIG_USE_IRQ)
       interrupt_init,             /* set up exceptions */
#endif
       timer_init,           /* initialize timer */
       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
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
       init_func_i2c,
#endif
       dram_init,            /* configure available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
       arm_pci_init,
#endif
       display_dram_config,
       NULL,
};

我们来看看env_init这个函数,其代码如下:

int env_init(void)
{
       /* use default */
       gd->env_addr = (ulong)&default_environment[0];
       gd->env_valid = 1;
#ifdef CONFIG_DYNAMIC_MMC_DEVNO
       extern int get_mmc_env_devno(void);
       mmc_env_devno = get_mmc_env_devno();
#else
       mmc_env_devno = CONFIG_SYS_MMC_ENV_DEV;
#endif
       return 0;
}

可以看出在这里将default_environment加载进入系统,default_environment对应的部分代码如下:

uchar default_environment[] = {
       .
       .
       .
#ifdef  CONFIG_EXTRA_ENV_SETTINGS
       CONFIG_EXTRA_ENV_SETTINGS
#endif
       "\0"
};

而CONFIG_EXTRA_ENV_SETTINGS则是在我们对应的BSP的头文件中定义了,如下:

#define  CONFIG_EXTRA_ENV_SETTINGS                                 \
              "netdev=eth0\0"                                    \
              "ethprime=FEC0\0"                                \
              "bootfile=uImage\0"  \
              "loadaddr=0x70800000\0"                            \
              "rd_loadaddr=0x70D00000\0"        \
              "bootargs=console=ttymxc0 init=/init " \
                     "androidboot.console=ttymxc0 video=mxcdi1fb:RGB666,XGA " \
                     "ldb=di1 di1_primary pmem=32M,64M fbmem=5M gpu_memory=64M\0" \
              "bootcmd_SD=mmc read 0 ${loadaddr} 0x800 0x2000;" \
                     "mmc read 0 ${rd_loadaddr} 0x3000 0x300\0" \
              "bootcmd=run bootcmd_SD; bootm ${loadaddr} ${rd_loadaddr}\0" \

再来看看check_recovery_mode这个函数中的代码,具体代码如下:

/* export to lib_arm/board.c */
void check_recovery_mode(void)
{
       if (check_key_pressing())
              setup_recovery_env();
       else if (check_recovery_cmd_file()) {
              puts("Recovery command file founded!\n");
              setup_recovery_env();
       }
}
可以看到在这里通过check_key_pressing这个函数来检测组合按键,当有对应的组合按键按下时,将会进入到recovery模式,这也正是各大android论坛里讲到刷机时都会提到的power+音量加键进入recovery模式的原因。那么check_recovery_cmd_file又是在什么情况下执行的呢?这个也正是这篇文章所要讲的内容之处。

       先来看看check_recovery_cmd_file这个函数中的如下这段代码:

int check_recovery_cmd_file(void)
{
       .
       .
       .
       switch (get_boot_device()) {
       case MMC_BOOT:
       case SD_BOOT:
              {
                     for (i = 0; i < 2; i++) {
                            block_dev_desc_t *dev_desc = NULL;
                            struct mmc *mmc = find_mmc_device(i);
                            dev_desc = get_dev("mmc", i);
                            if (NULL == dev_desc) {
                                   printf("** Block device MMC %d not supported\n", i);
                                   continue;
                            }
                            mmc_init(mmc);
                            if (get_partition_info(dev_desc, CONFIG_ANDROID_CACHE_PARTITION_MMC,
                                                 &info)) {
                                   printf("** Bad partition %d **\n",CONFIG_ANDROID_CACHE_PARTITION_MMC);
                                   continue;
                            }
                            part_length = ext2fs_set_blk_dev(dev_desc, CONFIG_ANDROID_CACHE_PARTITION_MMC);
                            if (part_length == 0) {
                                   printf("** Bad partition - mmc %d:%d **\n", i, CONFIG_ANDROID_CACHE_PARTITION_MMC);
                                   ext2fs_close();
                                   continue;
                            }
                            if (!ext2fs_mount(part_length)) {
                                   printf("** Bad ext2 partition or "
                                          "disk - mmc %d:%d **\n",
                                          i, CONFIG_ANDROID_CACHE_PARTITION_MMC);
                                   ext2fs_close();
                                   continue;
                            }
                            filelen = ext2fs_open(CONFIG_ANDROID_RECOVERY_CMD_FILE);
                            ext2fs_close();
                            break;
                     }
              }
              break;
       .
       .
       .
}

主要来看看下面这个ext2fs_open所打开的内容,CONFIG_ANDROID_RECOVERY_CMD_FILE,这个正是上面所提到的rocovery cmd file的宏定义,内容如下:

#define CONFIG_ANDROID_RECOVERY_CMD_FILE  "/recovery/command"

当检测到有这个文件存在时,将会进入到setup_recovery_env这个函数中,其相应的代码如下:

void setup_recovery_env(void)
{
       char *env, *boot_args, *boot_cmd;
       int bootdev = get_boot_device();
       boot_cmd = supported_reco_envs[bootdev].cmd;
       boot_args = supported_reco_envs[bootdev].args;
       if (boot_cmd == NULL) {
              printf("Unsupported bootup device for recovery\n");
              return;
       }
       printf("setup env for recovery..\n");
       env = getenv("bootargs_android_recovery");
       /* Set env to recovery mode */
       /* Only set recovery env when these env not exist, give user a
        * chance to change their recovery env */
       if (!env)
              setenv("bootargs_android_recovery", boot_args);
       env = getenv("bootcmd_android_recovery");
       if (!env)
              setenv("bootcmd_android_recovery", boot_cmd);
       setenv("bootcmd", "run bootcmd_android_recovery");
}

在这里主要是将bootcmd_android_recovery这个环境变量加到uboot启动的environment中,这样当系统启动加载完root fs之后将不会进入到android的system中,而是进入到了recovery这个轻量级的小UI系统中。

       下面我们来看看为什么在uboot的启动环境变量中加入bootcmd_android_recovery这些启动参数的时候,系统就会进入到recovery模式下而不是android system,先看看bootcmd_android_recovery相应的参数:

#define CONFIG_ANDROID_RECOVERY_BOOTARGS_MMC \
       "setenv bootargs ${bootargs} init=/init root=/dev/mmcblk1p4"     \
       "rootfs=ext4 video=mxcdi1fb:RGB666,XGA ldb=di1 di1_primary"
#define CONFIG_ANDROID_RECOVERY_BOOTCMD_MMC  \
       "run bootargs_android_recovery;"  \
       "mmc read 0 ${loadaddr} 0x800 0x2000;bootm"


可以看到在进入recovery模式的时候这里把root的分区设置成了/dev/mmcblk1p4,再来看看在系统烧录的时候对整个SD卡的分区如下:

sudo mkfs.vfat -F 32 ${NODE}${PART}1 -n sdcards
sudo mkfs.ext4 ${NODE}${PART}2 -O ^extent -L system
sudo mkfs.ext4 ${NODE}${PART}4 -O ^extent -L recovery
sudo mkfs.ext4 ${NODE}${PART}5 -O ^extent -L data
sudo mkfs.ext4 ${NODE}${PART}6 -O ^extent -L cache

这里NODE = /dev/mmcblk1为挂载点,PART = p或者为空,作为分区的检测。可以看出上面在给recovery分区的时候,用的是/dev/mmcblk1p4这个分区,所以当设置了recovery启动模式的时候,root根目录就被挂载到/dev/mmcblk1p4这个recovery分区中来,从而进入recovery模式。

作者:Xandy


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值