Chinaunix首页 | 论坛 | 博客
  • 博客访问: 902113
  • 博文数量: 478
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4832
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-28 11:12
文章分类

全部博文(478)

文章存档

2019年(1)

2018年(27)

2017年(21)

2016年(171)

2015年(258)

我的朋友

分类: Android平台

2018-01-17 18:17:10

http://blog.csdn.net/shichaog/article/details/61917374
高通android bootloader
原创 2017年03月13日 16:03:54
标签:
android
/
  • boot little authenti
  • 高通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的哈希值,并将其编译生成的哈希值对比,如果相对,则成功授权。这一过程中涉及到的函数如下:

[plain] view plain copy
  1. 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.c)--platform_init()

c.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() {
[plain] view plain copy
  1.   
  1. boot_linux_from_mmc() {  
  2.    structboot_img_hdr*hdr=(void*)buf; // boot image header  
  3.   
  4.    /* Read boot image header from emmcpartition into buf*/  
  5.    if(mmc_read(ptn+offset,(unsignedint*)buf,page_size)){... }  
  6.    /* Read image without signature to the scratch address */  
  7.    if (mmc_read(ptn+ offset, (void *)image_addr, imagesize_actual)) { .... }  
  8.    /* Read signature to the scratch address */  
  9.    if(mmc_read(ptn+ offset, (void *)(image_addr+ offset), page_size))  
  10.    /* Kernel image authentication */  
  11.    verify_signed_bootimg(image_addr, imagesize_actual);  
  12.    /* Move kernel, ramdiskand device tree to correct address */  
  13.    memmove((void*) hdr->kernel_addr, (char *)(image_addr+ page_size), hdr->kernel_size);  
  14.    memmove((void*) hdr->ramdisk_addr, (char *)(image_addr+ page_size+kernel_actual), hdr->ramdisk_size);  
  15.    /* Find the DT table address */  
  16.    dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual +ramdisk_actual + second_actual);  
  17.    table = (struct dt_table*) dt_table_offset;  
  18.    /* Calculate the index of device tree within device tree table */  
  19.    if(dev_tree_get_entry_info(table, &dt_entry) != 0){ }  
  20.    /* boot_linux : update device tree and jump to kernel */  
  21.    boot_linux((void *)hdr->kernel_addr, (unsigned *) hdr->tags_addr, (const char *)cmdline, board_machtype(),  
  22.    (void *)hdr->ramdisk_addr, hdr->ramdisk_size);  
  • void boot_linux()
  1. update_device_tree((void *)tags, final_cmdline, ramdisk, ramdisk_size); /* 
  2. shown on the next slide */  
  3. .....  
  4. if (IS_ARM64(kptr))  
  5. scm_elexec_call((paddr_t)kernel, tags_phys); /* Jump to a 64bit kernel */  
  6. else  
  7. entry(0, machtype, (unsigned*)tags_phys); /* Jump to a 32 bitkernel */  
  8. }  
  • 跟新设备树
  1. Int update_device_tree(constvoid*fdt,char*cmdline,  
  2. void*ramdisk,unsignedramdisk_size)  
  3. { .........  
  4. uint32_t*memory_reg;  
  5. /*Checkthedevicetreeheader*/  
  6. offset=fdt_check_header(fdt);  
  7. ..........  
  8. /*Getoffsetofthe”memory”node*/  
  9. offset=fdt_path_offset(fdt,”/memory”);  
  10. /* Update “memory” node* / 
  11. ret=target_dev_tree_mem(fdt,offset); 
  12. /*Getoffsetofthe”chosen”node*/  
  13. ret=fdt_path_offset(fdt,”/chosen”);  
  14. /*Addingthecmdlinetothe”chosen”node*/  
  15. ret=fdt_setprop_string(fdt,offset,(constchar*)”bootargs”,(constvoid*)cmdlin  
  16. e);  
  17. /*Addingtheinitrd-start tothechosennode*/  
  18. ret=fdt_setprop_u32(fdt,offset,”linux,initrd-start”,(uint32_t)ramdisk);  
  19. /*Addingtheinitrd-end tothechosennode*/  
  20. ret=fdt_setprop_u32(fdt,offset,”linux,initrd-  
  21. end”,((uint32_t)ramdisk+ramdisk_size));  
  22. .... }  

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了,这出于安全考虑
[plain] view plain copy
  1. ifeq($(TARGET_BUILD_VARIANT),user)  
  2. CFLAGS += -DDISABLE_FASTBOOT_CMDS=1  
  3. endif  
  • 启动user版本的镜像,如果要支持特定命令,需要按如下做
[plain] view plain copy
  1. bootable/bootloader/lk/app/aboot/aboot.c  

  1. structfastboot_cmd_desccmd_list[] = {  
  2. /* By default the enabled list is empty. */  
  3. {““, NULL},  
  4. /* move commands enclosed within the below ifndefto here 
  5. * if they need to be enabled in user build. 
  6. */  
  7. #ifndefDISABLE_FASTBOOT_CMDS  
  8. /* Register the following commands only for non-user builds */  
  9. {“flash:”, cmd_flash},  
  10. {“erase:”, cmd_erase},  
  11. {“boot”, cmd_boot},  
  12. {“continue”, cmd_continue},  
  13. {“reboot”, cmd_reboot},  
  14. {“reboot-bootloader”, cmd_reboot_bootloader},  
  15. {“oemunlock”, cmd_oem_unlock},  
  16. {“oemlock”, cmd_oem_lock},  
  17. {“oemverified”, cmd_oem_verified},  
  18. {“oemdevice-info”, cmd_oem_devinfo},  
  19. {“oemenable-charger-screen”, cmd_oem_enable_charger_screen},  
  20. {“oemdisable-charger-screen”, cmd_oem_disable_charger_screen},  
  21. {“oem-select-display-panel”, cmd_oem_select_display_panel},  
  22. #endif  
  23. };  

LK recovery模式

  • aboot_init检查KEY_HOME or VOLUME UP是否被按压了
  • 检查重启的原因--check_reboot_mode(),如果是RECOVERY_MODE原因,则设置boot_into_recovery = 1.
  • boot_linux_from_mmc检查
  1. if (!boot_into_recovery) {  
  2. .........  
  3. ...  
  4. else {  
  5. index = partition_get_index(“recovery”);  
  6. ptn = partition_get_offset(index);  
  7. ...........  
  8. ......  
  9. }  
  • 从recovery分区获取镜像
[plain] view plain copy
  1. gned int target_freq, unsigned int relation); 
阅读(2182) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~