高通LK(little kernel)。

little kernel是bootloader,其作用是硬件初始化,读取linux 内核和ramdisk到RAM里,设置初始寄存器以及内核命令行参数,并跳转到内核运行。

作用

  • 硬件初始化:设置向量表,MMU,cache,初始化外设
  • 从存储器加载boot.img
  • 支持flash和recovery

即使在64bit架构,LK依然运行在32bit模式

kernel授权

  • 签名的boot.img生成

a.使用用户的私有key生成加签名的boot镜像

b.计算原始boot.img的SHA256的哈希值,并使用用户的私有key(定义于device/qcom/common/common.mk)对哈希值镜像加签。将最终的哈希值和签名添加到原始的boot.img的末尾。

c.用户必须用PRODUCT_PRIVATE_KEY设置自己的私有key文件,当前该宏定义于device/qcom/common/qcom.key,目前使用的是一个测试key。

d.校验签名启动目前用于kernel和recovery镜像。

  • LK授权kernel(boot.img)

a.如果在目标平台的BoardConfig.mk中设置了TARGET_BOOTIMG_SIGNED= true,LK先校验boot.img,然后在启动kernel。

b.在启动过程中,LK提取原始的boot.img镜像并计算其SHA26的哈希值,并将其编译生成的哈希值对比,如果相对,则成功授权。这一过程中涉及到的函数如下:

verify_signed_bootimg()→image_verify()

c.如果成功授权,则LK传递给kernel的命令行中有”androidboot.authorized_kernel=true“

d.用户需要用公钥放到bootable/bootloader/lk/platform/msm_shared/certificate.cfile,LK将会使用该公钥解密boot.img最后的签名哈希值。

LK调用流程

  • 启动序列起始于arch/arm/crt0.S: _start:

a.设置cpu

b.如果需要调用__cpu_early_init(),

c.如果需要代码重定位

d.设置栈

e.调用kmain()

  • kmain的调用流程如下:

  • bootstrap2()的调用流程

a.arch/arm/arch.c –arch_init()

b.platform/<platform>/(platform.c)--platform_init()

c.target/<target>/(init.c) –target_init()

初始化SPMI

初始化keypad

设置驱动能力以及配置SDCpin脚功能

初始化SD主机控制器;确认MMC卡,设置时钟。

mmc_init()初始化

从emmc读取分区表

partition_read_table()

  • app/init.c –apps_init()

初始化APP_START 和 APP_END两个宏定义的apps,aboot_init()被调用;

如果有.entry字段,则app运行在在一个独立的线程中。

  • app/aboot/aboot.c –aboot_init()

根据设置和环境启动

  • 常规启动
  • fastboot模式接收镜像
  • recovery模式恢复固件

LK常规启动

  • recovery和fastboot标志没有设置
  • 将boot.img从emmc中读取到内存中,读取地址由target/msmXXX/rules.mk的base address指定。
  • 将kernel加载到KERNEL_ADDR(该地址源于boot image头)
  • 类似kernel,加载RAM disk到RAMDISK_ADDR
  • 找到正确的设备树,加载到TAGS_ADDR
  • 跟新设备树

a.获得/memory和/chosen的偏移

b.添加HLOS内存范围

c.将cmdline添加到/chosen节点

d.禁止cache,中断,跳转到kernel

代码片段

  • boot_linux_from_mmc() {
boot_linux_from_mmc() {structboot_img_hdr*hdr=(void*)buf; // boot image header
/* Read boot image header from emmcpartition into buf*/if(mmc_read(ptn+offset,(unsignedint*)buf,page_size)){... }/* Read image without signature to the scratch address */if (mmc_read(ptn+ offset, (void *)image_addr, imagesize_actual)) { .... }/* Read signature to the scratch address */if(mmc_read(ptn+ offset, (void *)(image_addr+ offset), page_size))/* Kernel image authentication */verify_signed_bootimg(image_addr, imagesize_actual);/* Move kernel, ramdiskand device tree to correct address */memmove((void*) hdr->kernel_addr, (char *)(image_addr+ page_size), hdr->kernel_size);memmove((void*) hdr->ramdisk_addr, (char *)(image_addr+ page_size+kernel_actual), hdr->ramdisk_size);/* Find the DT table address */dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual +ramdisk_actual + second_actual);table = (struct dt_table*) dt_table_offset;/* Calculate the index of device tree within device tree table */if(dev_tree_get_entry_info(table, &dt_entry) != 0){ }/* boot_linux : update device tree and jump to kernel */boot_linux((void *)hdr->kernel_addr, (unsigned *) hdr->tags_addr, (const char *)cmdline, board_machtype(),(void *)hdr->ramdisk_addr, hdr->ramdisk_size);


  • void boot_linux()

update_device_tree((void *)tags, final_cmdline, ramdisk, ramdisk_size); /*
shown on the next slide */
.....
if (IS_ARM64(kptr))
scm_elexec_call((paddr_t)kernel, tags_phys); /* Jump to a 64bit kernel */
else
entry(0, machtype, (unsigned*)tags_phys); /* Jump to a 32 bitkernel */
}

  • 跟新设备树

Int update_device_tree(constvoid*fdt,char*cmdline,
void*ramdisk,unsignedramdisk_size)
{ .........
uint32_t*memory_reg;
/*Checkthedevicetreeheader*/
offset=fdt_check_header(fdt);
..........
/*Getoffsetofthe”memory”node*/
offset=fdt_path_offset(fdt,”/memory”);
/* Update “memory” node* /
ret=target_dev_tree_mem(fdt,offset);
/*Getoffsetofthe”chosen”node*/
ret=fdt_path_offset(fdt,”/chosen”);
/*Addingthecmdlinetothe”chosen”node*/
ret=fdt_setprop_string(fdt,offset,(constchar*)”bootargs”,(constvoid*)cmdlin
e);
/*Addingtheinitrd-start tothechosennode*/
ret=fdt_setprop_u32(fdt,offset,”linux,initrd-start”,(uint32_t)ramdisk);
/*Addingtheinitrd-end tothechosennode*/
ret=fdt_setprop_u32(fdt,offset,”linux,initrd-
end”,((uint32_t)ramdisk+ramdisk_size));
.... }

LK fastboot模式


  • aboot_init检查boot.img是否存在,音量减键是否被按住
  • 检查reboot的原因--check_reboot_mode
  • 注册fastboot模式的函数方法--fastboot_register(cmd_list[i].name,cmd_list[i].cb);
  • 初始化fastboot
fastboot_init(void *base, unsigned size)
为 fastboot_handler()创建线程
线程等待USB事件
  • 设置USB--udc_start()

fastboot命令


  • 在用户模式fastboot命令被disable了,这出于安全考虑

ifeq($(TARGET_BUILD_VARIANT),user)
CFLAGS += -DDISABLE_FASTBOOT_CMDS=1
endif

  • 启动user版本的镜像,如果要支持特定命令,需要按如下做

bootable/bootloader/lk/app/aboot/aboot.c

structfastboot_cmd_desccmd_list[] = {
/* By default the enabled list is empty. */
{““, NULL},
/* move commands enclosed within the below ifndefto here
* if they need to be enabled in user build.
*/
#ifndefDISABLE_FASTBOOT_CMDS
/* Register the following commands only for non-user builds */
{“flash:”, cmd_flash},
{“erase:”, cmd_erase},
{“boot”, cmd_boot},
{“continue”, cmd_continue},
{“reboot”, cmd_reboot},
{“reboot-bootloader”, cmd_reboot_bootloader},
{“oemunlock”, cmd_oem_unlock},
{“oemlock”, cmd_oem_lock},
{“oemverified”, cmd_oem_verified},
{“oemdevice-info”, cmd_oem_devinfo},
{“oemenable-charger-screen”, cmd_oem_enable_charger_screen},
{“oemdisable-charger-screen”, cmd_oem_disable_charger_screen},
{“oem-select-display-panel”, cmd_oem_select_display_panel},
#endif
};

LK recovery模式


  • aboot_init检查KEY_HOME or VOLUME UP是否被按压了
  • 检查重启的原因--check_reboot_mode(),如果是RECOVERY_MODE原因,则设置boot_into_recovery = 1.
  • boot_linux_from_mmc检查

if (!boot_into_recovery) {
.........
...
else {
index = partition_get_index(“recovery”);
ptn = partition_get_offset(index);
...........
......
}

  • 从recovery分区获取镜像

gned int target_freq, unsigned int relation);
												

高通android bootloader相关推荐

  1. android加载efi分区,高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

  2. 高通Android平台开发

    问题描述:          对于有过开发高通android系统的人来说,获取代码构建开发环境并不是难事,但对于刚刚接触这一块内容的人,如果没有详细的说明很容易走弯路,本文档就是根据本人的实践总结的一 ...

  3. 高通Android智能平台环境搭建_编译流程分析

    高通Android智能平台环境搭建_编译流程分析 高通平台环境搭建,编译,系统引导流程分析 TOC \o \h \z \u 1. 高通平台android开发总结. 7 1.1 搭建高通平台环境开发环境 ...

  4. 高通Android智能平台开发总结

    高通Android智能平台开发总结 1. 高通平台android开发总结. 7 1.1 搭建高通平台环境开发环境. 7 1.2 搭建高通平台环境开发环境. 7 1.2.1 高通android智能平台概 ...

  5. 高通Android display架构分析

    目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...

  6. 高通android平台修改开机小企鹅logo

    高通平台修改开机画面 小企鹅LOGO 高通android平台修改开机小企鹅logo 方法一 方法二 高通android平台修改开机小企鹅logo 高通android平台开机lk阶段默认使用小企鹅log ...

  7. 高通linux内核目录,高通 android 源代码以及目标系统目录结构

    下面为高通android源代码结构 build/ – Build 环境建立和makefiles生成4 bionic/ – Android C 库 dalvik/ – Android Java 虚拟机 ...

  8. 高通android开源代码下载

    高通android开源代码下载 开源网站https://www.codeaurora.org/projects/all-active-projects/android-msm,选择wiki,在Wiki ...

  9. 高通 MSM8K bootloader : SBL1 .

    一. MSM8K Boot Flow 图1: 高通MSM8K平台bootloader启动流程基本类似,但具体各平台,比如MSM8974.MSM8916.MSM8994等,会有微小区别. 从上图,可以看 ...

最新文章

  1. hexo绑定个人域名
  2. 高效程序猿之(四)VS2010其他技巧
  3. 2018年东北农业大学春季校赛 E 阶乘后的0【数论】
  4. 什么是RosBE及其安装使用、第一次生成ReactOS的VS工程失败
  5. web 埋点实现原理了解一下
  6. Altium designer快捷键汇总
  7. 【poj2114】点分治(离线)
  8. Unity3D 与 objective-c 之间数据交互。iOS SDK接口封装Unity3D接口
  9. python调用系统命令_linux里面python调用系统命令问题
  10. 【洛谷 P3304】[SDOI2013]直径(树的直径)
  11. 运维工程师必备之负载均衡集群及LVS详解
  12. keil uVision4 创建项目
  13. BroadcastReceiver广播
  14. 联想服务器虚拟化解决方案,联想虚拟化解决方案
  15. Python库安装注意事项
  16. linux查看已安装的软件
  17. Inception-V3论文翻译——中文版
  18. 麦克劳林级数与麦克劳林公式(泰勒公式)
  19. 识破面试官的套路:十个典型的面试问题剖析
  20. 基本的信号——冲激信号与冲激序列

热门文章

  1. 通过例子学TLA+(十一)--命题逻辑与实例
  2. android 开发工程师 高级面试题
  3. 骁龙660是32位还是64位_高通骁龙660、653、652、650、626、625手机处理器区别是什么?...
  4. 解决高度塌陷4种方法
  5. 程序员是不是青春饭?
  6. 如何将Simulink应用于ISO 26262项目
  7. 六级词汇天天练(11.11)
  8. Elasticsearch高级搜索排序( 中文+拼音+首字母+简繁转换+特殊符号过滤)(示例代码)
  9. SSM文件上传封装工具类
  10. [转帖]一个关于国密SM4的故事