bootloader recovery

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lf12345678910/article/details/72845494

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);//处理当前动作

猜你喜欢

转载自blog.csdn.net/lf12345678910/article/details/72845494