1.总述
为了方便客户日后的固件升级,本周研究了一下android的recovery模式。网上有不少这类的资料,但都比较繁杂,没有一个系统的介绍与认识,在这里将网上所找到的和自己通过查阅代码所掌握的东西整理出来,给大家一个参考!
2.Android启动过程
在这里有必要理一下android的启动过程:
图1 android启动过程
系统上电之后,首先是完成一系列的初始化过程,如cpu、串口、中断、timer、DDR等等硬件设备,然后接着加载boot default environmet,为后面内核的加载作好准备。在一些系统启动必要的初始完成之后,将判断是否要进入recovery模式,从图1中可以看出,进入recovery模式有两种情况。一种是检测到有组合按键按下时;另一种是检测到cache/recovery目录下有command这个文件,这个文件有内容有它特定的格式,将在后面讲到。
3.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
"