`
carywei
  • 浏览: 191363 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

bootloader 引导进入recovery转载

 
阅读更多

昨天大家问recovery怎么工作的,差不多花了俩小时看了下
这个东西肯定是要bootloader支持的,因为bootloader要选择启动哪个kernel和ramdisk
所以是平台相关的。

这里可以从上往下看,也可以从下往上看。
我们先从上往下吧

多年不做,好在以前做bootloader和kernel的基础还在。
还比较容易找。

Setting里面我们可以选择恢复出厂设置,recovery
Power.reboot("recovery");

参数表示reboot的原因

然后会到JNI
static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
{
    sync();
#ifdef HAVE_ANDROID_OS
    if (reason == NULL) {
        reboot(RB_AUTOBOOT);
    } else {
        const char *chars = env->GetStringUTFChars(reason, NULL);
        __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                 LINUX_REBOOT_CMD_RESTART2, (char*) chars);
        env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
    }
    jniThrowIOException(env, errno);
#endif
}


这里会调用到c库里面的函数

__reboot:
    .save   {r4, r7}
    stmfd   sp!, {r4, r7}
    ldr     r7, =__NR_reboot
    swi     #0
    ldmfd   sp!, {r4, r7}
    movs    r0, r0
    bxpl    lr
    b       __set_syscall_errno
    .fnend


c库实际上到最底下就是系统调用的封装了,
一般都是sys_reboot的实现了,
不过Qualcomm这里用了宏来定义的。

调用了系统调用,kernel里面实现,我们就到了kernel里面

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
        void __user *, arg)



    switch (cmd) {
    case LINUX_REBOOT_CMD_RESTART:
        kernel_restart(NULL);
        break;

    case LINUX_REBOOT_CMD_CAD_ON:
        C_A_D = 1;
        break;

    case LINUX_REBOOT_CMD_CAD_OFF:
        C_A_D = 0;
        break;

    case LINUX_REBOOT_CMD_HALT:
        kernel_halt();
        unlock_kernel();
        do_exit(0);
        break;

    case LINUX_REBOOT_CMD_POWER_OFF:
        kernel_power_off();
        unlock_kernel();
        do_exit(0);
        break;

    case LINUX_REBOOT_CMD_RESTART2:
        if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
            unlock_kernel();
            return -EFAULT;
        }
        buffer[sizeof(buffer) - 1] = '/0';

        kernel_restart(buffer);


走到kernel_restart
void kernel_restart(char *cmd)
{
    kernel_restart_prepare(cmd);
    if (!cmd)
        printk(KERN_EMERG "Restarting system./n");
    else
        printk(KERN_EMERG "Restarting system with command '%s'./n", cmd);
    machine_restart(cmd);
}



void machine_restart(char * __unused)
{
    arm_pm_restart(reboot_mode);
}

    arm_pm_restart(reboot_mode);
这个函数是要每个target自己定义的,
以Qualcomm来说
static void msm_pm_restart(char str)
{
    msm_rpcrouter_close();
    msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);

    for (;;)
        ;
}

这里的restart reason是recovery

static int msm_reboot_call
    (struct notifier_block *this, unsigned long code, void *_cmd)
{
    if ((code == SYS_RESTART) && _cmd) {
        char *cmd = _cmd;
        if (!strcmp(cmd, "bootloader")) {
            restart_reason = 0x77665500;
        } else if (!strcmp(cmd, "recovery")) {
            restart_reason = 0x77665502;
        } else if (!strcmp(cmd, "eraseflash")) {
            restart_reason = 0x776655EF;
        } else if (!strncmp(cmd, "oem-", 4)) {
            unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
            restart_reason = 0x6f656d00 | code;
        } else {
            restart_reason = 0x77665501;
        }
    }
    return NOTIFY_DONE;
}

会把这个原因写到smem里面去

下次启动的时候怎么管用呢?

bootloader下次起来的时候会去读这个值

Qualcomm的bootloader是appsboot.mbn
void aboot_init(const struct app_descriptor *app)
{
    unsigned reboot_mode = 0;
    unsigned disp_init = 0;
    #if DISPLAY_SPLASH_SCREEN
    display_init();
    dprintf(INFO, "Diplay initialized/n");
    disp_init = 1;
    #endif
    page_size = flash_page_size();
    page_mask = page_size - 1;
    if (keys_get_state(KEY_HOME) != 0)
            boot_into_recovery = 1;
    if (keys_get_state(KEY_BACK) != 0)
        goto fastboot;
    if (keys_get_state(KEY_CLEAR) != 0)
        goto fastboot;
    if (keys_get_state(KEY_VOLUMEUP) != 0)
        goto fastboot;
    if (keys_get_state(KEY_CAMERA) != 0)
        goto fastboot;
    if (keys_get_state(KEY_VOLUMEDOWN) != 0)
            boot_into_recovery = 1;
        //goto fastboot;

    reboot_mode = check_reboot_mode();
        if (reboot_mode == RECOVERY_MODE){
            boot_into_recovery = 1;
        }else if(reboot_mode == FASTBOOT_MODE){
            goto fastboot;
        }
    recovery_init();
    boot_linux_from_flash();
    dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
        "to fastboot mode./n");

fastboot:
    if(!disp_init) {
        display_init();
    } else {
        fbcon_clear();
    }
    dprintf(INFO, "Diplay initialized/n");
    udc_init(&surf_udc_device);

    fastboot_register("boot", cmd_boot);
    fastboot_register("erase:", cmd_erase);
    fastboot_register("flash:", cmd_flash);
    fastboot_register("continue", cmd_continue);
    fastboot_register("reboot", cmd_reboot);
    fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
    fastboot_publish("product", "swordfish");
    fastboot_publish("kernel", "lk");

    fastboot_init(target_get_scratch_address(), 150 * 1024 * 1024);
    udc_start();
        target_battery_charging_enable(1, 0);
}

APP_START(aboot)
    .init = aboot_init,
APP_END


函数很简单,
有三种情况
1:如果按键就会进入recovery
2:如果check_boot_mode是recovery的时候就会做
3 : 如果recovery_init返回的是真的话就会进入recovery mode


第一种很好理解,标准就是
第二种会去读smem
unsigned check_reboot_mode(void)
{
    unsigned mode[2] = {0, 0};
    unsigned int mode_len = sizeof(mode);
    unsigned smem_status;

    smem_status = smem_read_alloc_entry(SMEM_APPS_BOOT_MODE,
                    &mode, mode_len );
    if(smem_status)
    {
      dprintf(CRITICAL, "ERROR: unable to read shared memory for reboot mode/n");
      return 0;
    }
    return mode[0];
}


unsigned smem_read_alloc_entry(smem_mem_type_t type, void *buf, int len)
{
    struct smem_alloc_info *ainfo;
    unsigned *dest = buf;
    unsigned src;
    unsigned size;

    if (((len & 0x3) != 0) || (((unsigned)buf & 0x3) != 0))
        return 1;

    if (type < SMEM_FIRST_VALID_TYPE || type > SMEM_LAST_VALID_TYPE)
        return 1;

    /* TODO: Use smem spinlocks */
    ainfo = &smem->alloc_info[type];
    if (readl(&ainfo->allocated) == 0)
        return 1;

    if ((size = readl(&ainfo->size)) != (unsigned)len)
        return 1;

    src = MSM_SHARED_BASE + readl(&ainfo->offset);
    for (; size > 0; src += 4, size -= 4)
        *(dest++) = readl(src);

    return 0;
}


第三种才是网络上普遍说的寻找misc分区
这个我就不说了,可以参考网上的文档。

http://blog.chinaunix.net/u/14459/showart_1911144.html

Qualcomm的机器有些没有misc分区的,我见过的好像都没有?
不过也都没太注意。

这个文章只解释如何进入recovery,至于进入recovery之后如何取cache,
就比较简单了,系统都起来了,后面的recovery的过程就是cache分区的东西了。

实际上所有的Android的bsp都不是完全开源的,
包括Qualcomm的全系列,nvidia的tegra,ti的,freescale的,
都有一些不能开源的部分,比如tegra 的bootloader是单独发布的。没开源。

我上面贴出来的代码都是Qualcomm开源部分的代码。
其他的部分都是合作伙伴才有的,包括Tegra 2也是一样的,大家能下载的
都只是开源的那个部分,私有的部分只有合作伙伴才有。等等厂家都一样。

不过大多数东西,应该说80%的东西都是开源的吧。

目前在做一些系统工程的东西,不过刚才又有其他项目的临时抽调任务。
疑难杂症性质的东西又来了。

关于Android双屏的事情还一直有customer在问,
大体分多种
1:两个屏幕是独立的,各自跑各自的东西,就是俺之前做的那个东西,典型的应用是
大小屏应用。比如游戏机等等
2:两个屏幕是分离的,但是内容要跨界显示,组合成一个屏幕,
也是可以做的了,KERNEL里面做就好了,电子书屏幕的确是太小,不能折叠还。
3:两个屏幕是分离的,显示东西是一样的,这个就更好做了,类似HDMI

但是如果要硬件加速的话,整个系统上的工作会多很多

分享到:
评论

相关推荐

    Bootloader引导程序下载

    该文档提供了Bootloader引导程序下载的详细步骤和操作截图说明,十分实用。

    如何使用Bootloader引导程序1

    本文将详细介绍如何在HY—SmartSTM32 Multi Media Development Board上使用STM32 USB Bootloader进行引导程序的操作。 首先,你需要下载STM32 USB Bootloader,这是一个专为STM32微控制器设计的引导程序,它允许...

    XC7K325T使用MIG怎样从bootloader引导(含教程和FPGA工程)|XC7K325T 使用 MIG 怎样从 bootloader 引导(含教程和FPGA工程).zip

    在本文中,我们将深入探讨如何在Xilinx的XC7K325T FPGA上使用Memory Interface Generator (MIG) 从bootloader引导系统。MIG是Xilinx提供的一种工具,用于设计高性能、低延迟的DDR和其他内存接口。通过遵循本教程,你...

    bootloader 引导程序源码

    引导程序,或者更具体地说,Bootloader,是计算机系统启动时执行的第一段代码,它负责初始化硬件设备,加载操作系统内核,并将控制权传递给内核。Bootloader在嵌入式系统和PC领域中都起着至关重要的作用,因为它是...

    最小的BootLoader 更新引导程序

    在嵌入式系统开发中,引导程序(Bootloader)扮演着至关重要的角色,它是系统启动时的第一段代码,负责加载操作系统或应用程序到内存并执行。本文将深入探讨一个专为STM32工业控制芯片设计的极小BootLoader更新程序...

    TMS320C6414的bootloader引导程序

    ### TMS320C6414的Bootloader引导程序 #### 概述 TMS320C6414是TI公司推出的一款高性能数字信号处理器(DSP),广泛应用于通信、图像处理等领域。Bootloader是启动时运行的第一段小程序,主要负责初始化硬件设备、...

    MSP430F系列单片机bootloader原理及实现方法附源码

    1. **中断向量重定向**:Bootloader首先要确保中断向量表指向Bootloader的入口地址,以便在启动时执行Bootloader代码。 2. **自举加载**:Bootloader会检查是否有新的应用程序待加载。这可以通过检测特定的引脚状态...

    USART_BootLoader_IAP.zip

    IAP实际上是将片上flash分为两个区,第一个区域放置BootLoader的引导程序,作用是接收已经编写好的应用程序(bin文件),同时将接收到的应用APP文件存储到flash第二个区域。存储完成后程序跳转到第二个flash运行APP...

    android recovery原理讲解

    - `command == 'boot-recovery'`: 启动`recovery.img`,即进入Recovery模式。 - `command == 'update-radio/hboot'`: 更新固件(Bootloader)。 - 其他命令: 启动`boot.img`,即正常的启动流程。 #### Recovery的...

    bootloader

    - **Android Bootloader**:对于Android设备,有fastboot和recovery模式,其中fastboot用于固件更新,recovery则提供备份和恢复功能。 5. **Bootloader的安全性** - **防止非法篡改**:Bootloader的安全性至关...

    一键Recovery

    使用方法: ...三、进入fastboot界面(音量下+电源,进入bootloader,然后再按一下电源进入fastboot) 四、将手机和电脑用数据线连接,一般情况下会安装驱动 五、运行一键刷入Recovery.EXE完成刷入recovery

    c6000dsp引导方式和bootloader

    在C6000 DSP的开发过程中,引导过程和bootloader的配置是至关重要的环节,它们直接影响到系统的启动速度、稳定性和可扩展性。本文将深入探讨C6000 DSP的引导方式以及如何编写二次引导程序,帮助开发者更好地理解和...

    一种新的BootLoader启动引导方式研究

    【BootLoader启动引导方式】 BootLoader,即“系统的引导加载程序”,是计算机系统启动时运行的第一个软件,负责初始化硬件设备,比如CPU、内存、外设等,并构建内存映射图,为操作系统内核的加载和运行创建合适的...

    手动进入进入Recovery模式方法.doc

    - Nexus One (G5):先按住轨迹球,然后按电源键,再通过音量键选择BOOTLOADER和RECOVERY。 - Legend (G6):返回键+开机键,然后在HBOOT界面用音量键选择Recovery。 - HTC Desire (G7)至Incredible S (G11)、...

    bootloader三种启动模式说明

    Recovery 模式是一种特殊的启动模式,在这个模式下,手机将引导一个简化的 recovery 程序。这个程序可以在没有电脑的情况下,直接用 SD 卡里的升级文件进行升级。Recovery 模式的功能要比 Fastboot 模式复杂一些,...

    Bootloader

    - **移动设备**:在智能手机和平板电脑上,Bootloader通常包括Fastboot和Recovery Mode,它们在设备维护和更新固件时发挥作用,比如Android设备中的Bootloader就支持fastboot模式进行系统刷机。 Bootloader的安全性...

    STM32F103系列Bootloader

    STM32F103系列Bootloader是针对意法半导体(STMicroelectronics)的STM32F103微控制器设计的一种引导加载程序。Bootloader是嵌入式系统中的一个重要组成部分,它在系统启动时运行,负责加载操作系统或应用程序到内存...

    华为手机工具箱只支持华为系列智能安卓机-可用于解锁bootloader及刷写recovery,重启到fastboot及重启

    华为手机工具箱是一款专为华为系列智能安卓手机设计的实用工具集合,主要功能集中在解锁bootloader、刷写recovery、安装USB驱动以及实现快速启动到fastboot或Recovery模式。这款工具箱对于喜欢自定义手机系统或者...

Global site tag (gtag.js) - Google Analytics