http://huaqianlee.github.io/2015/07/25/Android/Android%E6%BA%90%E7%A0%81bootable%E8%A7%A3%E6%9E%90%E4%B9%8BLK-bootloader-little-kernel/
Android Recovery 源码解析和界面定制
http://blog.csdn.net/austindev/article/details/55213444
adb reboot edl 刷机模式
adb reboot recovery recovery模式
#define ANDROID_RB_PROPERTY "sys.powerctl" // 控制启动状态
property_set(ANDROID_RB_PROPERTY, "shutdown,");
property_set(ANDROID_RB_PROPERTY, "reboot,bootloader");
property_set(ANDROID_RB_PROPERTY, "reboot,");
property_set(ANDROID_RB_PROPERTY, "reboot,edl");
case Device::SHUTDOWN:
ui->Print("Shutting down...\n");
property_set(ANDROID_RB_PROPERTY, "shutdown,");
break;
case Device::REBOOT_BOOTLOADER:
ui->Print("Rebooting to bootloader...\n");
property_set(ANDROID_RB_PROPERTY, "reboot,bootloader");
break;
default:
ui->Print("Rebooting...\n");
property_set(ANDROID_RB_PROPERTY, "reboot,");
break;
手机开机后,硬件系统上电,完成一系列的初始化工作:CPU、串口、终端、timer、DDR等硬件设备,然后加载bootloader,为后面内核加载做准备工作。在系统启动初始化完成后系统检测进入哪一种工作模式,这一部分代码的源文件在\bootable\bootloader\lk\app\aboot\aboot.c文件的aboot_init()函数中:
检测用户关机方式,如果是强制关机,则进入normal_boot模式
bootable\bootloader\lk\arch\arm\crt0.S
bl kmain
bootable\bootloader\lk\kernel\main.c
apps_init
bootable\bootloader\lk\app\app.c
app->init(app);
aboot.c
APP_START(aboot)
.init = aboot_init,
APP_END
aboot_init //判断进入正常开机、fastboot、recovery模式
bootable\bootloader\lk\app\aboot\recovery.c
boot_linux_from_mmc(){
index = partition_get_index("recovery");
ptn = partition_get_offset(index);
}
当开机以后,在lk阶段会判断这个地址的值,如果是recovery,会设置boot_into_recovery=1,然后读取recovery.img镜像,把recovery.img的地址和ramdisk等信息作为参数启动kernel,从而进入recovery模式
我们知道,当我们通过按键或者应用进入recovery模式,实质是kernel后加载recovery.img,kernel起来后执行的第一个进程就 是init,此进程会读入init.rc启动相应的服务。在recovery模式中,启动的服务是执行recovery可执行文件,此文件是
bootable/recovery/recovery.cpp文件生成,我们就从recovery.cpp文件开始分析。
recovery.cpp
main()
ScreenRecoveryUI::SetLocale()
2 boottable/recovery/minui下的resources.cpp,graphics.cpp
其中resources.cpp提供的api主要用于图片资源的读取和加载,graphics.cpp负责具体完成各类ui的绘制
总体而言,recovery中上层通过调用minui库实现了图形的描绘以及固定大小的文字显示,minui库调用了png库来实现最后的渲染。
Android N恢复出厂设置进入Recovery
http://blog.csdn.net/ly890700/article/details/54586413
在RecoverySysterm.Java的setupOrClearBcb中,根据输入参数,一开始会执行 SystemProperties.set("ctl.start", "setup-bcb") ,这就会通知init进程启动setup-bcb服务,init进程在启动setup-bcb服务的同时创建出/dev/socket/uncrypt这个socket,之后uncrypt就会通过这个socket来和RecoverySystemService通信。
因此接下来就会执行/system/bin/uncrypt --setup-bcb
bootable/recovery/uncrypt/uncrypt.rc
service uncrypt /system/bin/uncrypt
class main
socket uncrypt stream 600 system system
disabled
oneshot
service setup-bcb /system/bin/uncrypt --setup-bcb
class main
socket uncrypt stream 600 system system
disabled
oneshot
service clear-bcb /system/bin/uncrypt --clear-bcb
class main
socket uncrypt stream 600 system system
disabled
oneshot
/system/bin/uncrypt ---> uncrypt.cpp
bootable/recovery/uncrypt/uncrypt.cpp
setup_bcb():
1 setup_bcb中先从/dev/socket/uncrypt中取出4个字节的数据,传递给int型的变量length,然后再将length的值继续作为长度,再从socket中取出length个字节的数据,作为要向bcb写入的数据传递给content。 这完全符合之前在RecoverySystemService中向/dev/socket/uncrypt的写入顺序。
2 在uncrypt调用write_bootloader_message来完成写入bcb的操作后,还会判断这个操作是否成功。如果成功,通过socket向RecoverySystemService返回100,如果失败则返回-1,这恰好验证了我们之前在5.2小节中发现的,恢复出厂设置失败的情况下输出的log中:
03-04 11:03:30.780 1434 6527 E RecoverySystemService: uncrypt failed with status: -1
bootloader_message.cpp
write_bootloader_message()
// The fstab path is always "/fstab.${ro.hardware}".
fs_mgr_get_entry_for_mount_point()
最后在write_bootloader_message中,会调用fs_mgr来判断是否存在misc分区,如果不存在就返回,同时将错误原因保存到err中,传递给uncrypt的setup_bcb,setup_bcb中会打印出我们在log中看到的出错原因:
failed to set bootloader message:failed to find /misc partition
A1属于高通机型,因此fs_mgr将从fstab.qcom中查找misc分区,这个问题真正的根源就是fstab.qcom中没有添加misc分区导致。
读取控制参数
recovery 和 bootloader 必须通过内存的一个特定分区,才能进行相互的通信,这个分区一般是/misc;
对应的信息数据结构体为bootloader_message;
参照源码中bootloader_message 的注释
struct bootloader_message {
char command[32];//bootloader 启动时读取改数据,决定是否进入recovery模式
char status[32];//由bootloader进行更新,标识升级的结果;
char recovery[768];//由Android系统进行写入,recovery从中读取信息;
char stage[32];
char reserved[224];
};
char command[32];//bootloader 启动时读取改数据,决定是否进入recovery模式
char status[32];//由bootloader进行更新,标识升级的结果;
char recovery[768];//由Android系统进行写入,recovery从中读取信息;
char stage[32];
char reserved[224];
};
1.2 系统的启动模式
由下图可知Android系统启动后可能进入的模式有以下几种:
3. 正常模式:
若启动过程中用户没有按下任何组合键,bootloader会读取位于MISC分区的启动控制信息块BCB(Bootloader Control Block)。它是一个结构体,存放着启动命令command。根据不同的命令,系统又可以进入三种不同的启动模式:MainSystem、Recovery、Bootloader。
Bootloader:除了正常的加载启动系统之外,还会通过读取MISC分区(BCB)获得来至Main system和Recovery的消息。
default_device.cpp/default_device.cpp
Device* make_device() {
return new Device(new ScreenRecoveryUI);
}
bootable/recovery/device.cpp
static const char* MENU_ITEMS[] = {
"Reboot system now",
"Reboot to bootloader",
"Apply update from ADB",
"Apply update from SD card",
"Wipe data/factory reset",
#ifndef AB_OTA_UPDATER
"Wipe cache partition",
#endif // !AB_OTA_UPDATER
"Mount /system",
"View recovery logs",
"Run graphics test",
"Power off",
NULL,
};
const char* const* Device::GetMenuItems() {
return MENU_ITEMS;
}
bootable/recovery/recovery.cpp
Device::BuiltinAction temp = prompt_and_wait(device, status);//循环检测当前的动作,准备接收用户按键
int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), 0, 0, device);//进入循环等待用户按键,得到当前的动作
int action = device->HandleMenuKey(key, visible);//处理当前动作