高通bootloader

news/2024/11/22 18:06:47/

====================基本知识=======================
LK是(L)ittle (K)ernel的缩写。
高通平台android普遍采用LK作为其bootloader,LK是一个开源项目。但是,LK只是整个系统的引导部分,所以它不是独立存在。LK是一个功能及其强大的bootloader,但现在只支持arm和x86平台。
LK的一个显著的特点就是它实现了一个简单的线程机制(thread),和对高通处理器的深度定制和使用。

====================源码架构=======================
app               //主函数启动app执行的目录,第一个app在app/aboot/aboot.c中
arch              //体系代码包含x86和arm
dev               //设备目录,包含显示器,键盘,net,usb等设备的初始化代码
include        //头文件
kernel          //kernel/main.c主函数以及kernel/thread.c线程函数
lib                //库文件
make          //编译规则
platform     //不同平台代码mdmxxx,msmxxx,apqxxx,qsdxxx,还有共享的目录msm_shared
project        //整个工程的编译规则
target          //通用init.c,具体目标板的初始化(主要为板子设备资源init.c代码中),编译规则代码(一级s810.mk二级hdc8094.mk)

====================程序执行流程============================
主函数lk/kernel/main.c
/* called from crt0.S */
void kmain(void) __NO_RETURN __EXTERNALLY_VISIBLE;
void kmain(void)     //从kmain函数开始执行
{
thread_init_early();      // 线程初始化
            arch_early_init();           //平台体系x86或者arm初始化,类似uboot的第一阶段汇编,在arch/arm下面实现
实现功能:关闭cache,设置异常向量,mmu初始化,打开cache
// do any super early platform initialization
platform_early_init();---->                                    //开始涉及到具体平台
void platform_early_init(void)
{
board_init();                  //目标平台板的初始化
platform_clock_init();  //平台时钟初始化msm8994_clock
qgic_init();                  //通用IO通道初始化
qtimer_init();              //时钟初始化
scm_init();                   //单片机初始化
}
                    
// do any super early target initialization
target_early_init();    //只初始化串口为了打印信息,与后面的target_init对应
以上采用层层递进的关系进行初始化

   dprintf(INFO, "welcome to lk\n\n");  //开始进入LK,INFO级别在console打印

// initialize the threading system
dprintf(SPEW, "initializing threads\n");     //SPEW级别在console口不打印
thread_init();

// initialize the dpc system
dprintf(SPEW, "initializing dpc\n");
dpc_init();

// initialize kernel timers
dprintf(SPEW, "initializing timers\n");
timer_init();

// create a thread to complete system initialization    -->创建线程完成系统初始化,跳转到第二阶段
dprintf(SPEW, "creating bootstrap completion thread\n");
/*jump to bootstrap2*/
thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

// become the idle thread    //变成空闲线程
thread_become_idle();
}

static int bootstrap2(void *arg)
{
platform_init();              ---> void platform_init(void)      //msm8994
{
dprintf(INFO, "platform_init()\n");
#if ENABLE_XPU_VIOLATION
scm_xpu_err_fatal_init();
#endif
}
target_init();  //各种板子资源初始化,mmc,sdc,usb,volumn等---->
              //里面最重要的是mmc的初始化    target_sdc_init();
              //还有RPM                                   rpm_smd_init();

             dprintf(SPEW, "calling apps_init()\n");//app初始化以及启动app
apps_init();//开始执行app/aboot.c中的aboot_init函数
}

接下来开始执行app/aboot/aboot.c
在amboot.c的源码最底端:
APP_START(aboot)     //可以看出上述的app启动的第一个就是aboot_init
.init = aboot_init,
APP_END

/* each app needs to define one of these to define its startup conditions */每个app需要的定义
struct app_descriptor {
const char *name;
app_init  init;
app_entry entry;
unsigned int flags;
};
开始研究aboot_init函数:
void aboot_init(const struct app_descriptor *app)
{
    /* Setup page size information for nv storage */首先判断从哪启动emmc还是flash
if (target_is_emmc_boot())
{
page_size = mmc_page_size();
page_mask = page_size - 1;
}
else
{
page_size = flash_page_size();
page_mask = page_size - 1;
}
    read_device_info(&device);      //读取设备信息

/* Display splash screen if enabled */
#if DISPLAY_SPLASH_SCREEN                           //初始化显示屏
dprintf(SPEW, "Display Init: Start\n");
target_display_init(device.display_panel);
dprintf(SPEW, "Display Init: Done\n");
#endif


target_serialno((unsigned char *) sn_buf);   //获取串口号
dprintf(SPEW,"serial number: %s\n",sn_buf);

memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);
    /*如果用户强制重启是进入正常模式的,不会进入fastboot模式,然而在实现中该函数返回0,不执行
     * Check power off reason if user force reset,
     * if yes phone will do normal boot.
     */
    if (is_user_force_reset())
        goto normal_boot;

接下来就做一些除了boot up之外的一些事情, 这里面主要判断组合按键,其中可以进入dload(livesuit)模式和recovery模式
      其中recovery模式 进入Linux内核,启动recovery映像,通过界面选择烧写的软 件包update.zip
注:android镜像烧写总共有三种:fastboot(调试用),livesuit(下载整个镜像),recovery(启动recovery镜像)

然后判断是正常启动还是非正常启动,如果正常启动就recovery_init然后直接启动内核(包括传参)
两种情况:emmc和flash启动
        if (target_is_emmc_boot())
{
if(emmc_recovery_init())
dprintf(ALWAYS,"error in emmc_recovery_init\n");
if(target_use_signed_kernel())
{
if((device.is_unlocked) || (device.is_tampered))
{
#ifdef TZ_TAMPER_FUSE
set_tamper_fuse_cmd();
#endif
#if USE_PCOM_SECBOOT
set_tamper_flag(device.is_tampered);
#endif
}
}

 boot_linux_from_mmc();    ---->lk的启动画面也在里面,其实就是完成启动前的最后准备工作
}
else
{
recovery_init();
#if USE_PCOM_SECBOOT
if((device.is_unlocked) || (device.is_tampered))
set_tamper_flag(device.is_tampered);
#endif
 boot_linux_from_flash();
}

如果是非正常启动就进入fastboot模式,之前进行fastboot命令的注册以及启动fastboot
/* register aboot specific fastboot commands */注册fastboot命令
  aboot_fastboot_register_commands();

/* dump partition table for debug info */
partition_dump();

/* initialize and start fastboot */初始化fastboot以及启动
fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
}
现在分析fastboot_init函数做些什么工作:
int fastboot_init(void *base, unsigned size)
{
/* target specific initialization before going into fastboot. */进入fastboot前的目标板初始化
    target_fastboot_init();

    /* setup serialno */创建串口号
target_serialno((unsigned char *) sn_buf);
dprintf(SPEW,"serial number: %s\n",sn_buf);
surf_udc_device.serialno = sn_buf;

/* initialize udc functions to use dwc controller */初始化usb控制器, 因为fastboot和板子通过usb进行通信
/* register udc device */注册usb  controller设备

/* register gadget */注册gadget

thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);//创建线程
----> static int fastboot_handler(void *arg)
{
for (;;) {
event_wait(&usb_online);//等待usb连接
fastboot_command_loop();//循环处理fastboot命令
}
return 0;
}
}
大多数fastboot命令cmd_xxx是在aboot.c中实现的,然后进行注册

现在分析 boot_linux_from_mmc函数做些什么工作:
常用结构体:
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];

unsigned kernel_size;  /* size in bytes */
unsigned kernel_addr;  /* physical load addr */

unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */

unsigned second_size;  /* size in bytes */
unsigned second_addr;  /* physical load addr */

unsigned tags_addr;    /* physical addr for kernel tags */
unsigned page_size;    /* flash page size we assume */
unsigned dt_size;      /* device_tree in bytes */
unsigned unused;    /* future expansion: should be 0 */

unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */

unsigned char cmdline[BOOT_ARGS_SIZE];     //串口的传参在这里

unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};

现在研究串口cmdline在哪打印的:
void boot_linux(void *kernel, unsigned *tags,
const char *cmdline, unsigned machtype,
void *ramdisk, unsigned ramdisk_size)
{
final_cmdline = update_cmdline((const char*)cmdline);

}

void aboot_init(const struct app_descriptor *app)
{
    bool boot_into_fastboot = false;    //判断是否进入fastboot模式
#if UART_INPUT_INTO_FASTBOOT
char getc_value;
#endif

#if UART_INPUT_INTO_FASTBOOT    // 经测验,按键f要一直按住,否则很难检测到,后续可以考虑延迟一段时间
if(dgetc(&getc_value, 0) >= 0) {
if(getc_value == 'f') {
boot_into_fastboot = true;
dprintf(INFO,"keyboard is pressed, goto fastboot mode!\n");
}
}
#endif

}
后续待完善!

http://www.ppmy.cn/news/422327.html

相关文章

麒麟810处理器_华为携7nm麒麟810处理器,再攻高通

近日,任正非与两位美国思想家的对谈,确认了海外手机业务至少下滑40%的事实。 在国际市场上遭遇了市场以外的阻力后,华为打算把更多的精力放到国内市场,这或许也是当下为数不多可选的路子。 迫在眉睫的华为 为了抵消海外市场下滑的…

麒麟810处理器_华为携7nm麒麟810处理器 剑指高通

尽管目前遭到美国限制,但华为的新品迭代并未停止。伴随本周华为nova5的即将发布,华为麒麟第二款自研7nm SoC也将正式面世,据悉这款新品将被命名为麒麟810,这也是华为首款8系列芯片。 日前,华为终端手机产品线总裁何刚表…

高通810高热该谁背锅?那就是Apple!!

扯扯骁龙810吧 骁龙810最早是高通公司与2014年进行的产品规格公开,CPU构架采用ARM公司的公版构架ARMCortex A57A53,并且通过Big.Little 技术实现异构8核心,GPU部分采用Adreno 430 GPU,支援LPDDR4内存,支援LTE C6 300Mb…

天玑810和骁龙695哪个好 天玑810和骁龙695差别

骁龙695,采用台积电6nm工艺制作,八核心CPU设计,具体由2个A78核心6个A55小核心组成,其中A78核心频率2.2GHz,A55小核心频率1.8GHz,GPU是Adreno 619。 存储部分,支持16位双通道的LPDDR4X内存和UFS …

8年测试总结,App测试要点常见bug分类,从功能到性能测试...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 而针对手机应用软…

2023ciscn初赛 Unzip

参考&#xff1a; 奇安信攻防社区-2021深育杯线上初赛官方WriteUp-Web篇 1.打开环境 2.上传一个文件&#xff0c;得到以下源码&#xff0c;分析一下8 <?php error_reporting(0); highlight_file(__FILE__);$finfo finfo_open(FILEINFO_MIME_TYPE); //使用 PHP 内置函数…

Python 代码实现用于对股票进行量化交易,2023博客之星候选

import yfinance as yf import pandas as pd# 下载股票数据 stock_data yf.download("AAPL", start"2010-01-01", end"2021-06-11")# 计算移动平均线 stock_data["SMA10"] stock_data["Close"].rolling(window10).mean() …

视觉SLAM十四讲——ch10实践(后端2)

视觉SLAM十四讲——ch10的实践操作及避坑 0. 实践前小知识介绍1. 实践操作前的准备工作2. 实践过程2.1 g2o原生位姿图2.2 李代数上的位姿图优化 3. 遇到的问题及解决办法3.1 在运行pose_graph_g2o_lie时出现错误 0. 实践前小知识介绍 视觉SLAM&#xff08;Simultaneous Locali…