高通 MSM8K bootloader 之二: SBL1

续:高通 MSM8K bootloader 之一: SBL1

上篇将我重点关注SBL1的内容1和2基本说明完,本篇继续内容3和4。
1、    CDT : Platform ID和DDR参数 
2、 debug log :
3、 download : msm8K 新平台软件download支持两种协议,sahara和firehose
4、 ramdump :死机异常信息dump

四、SW download

1、软件升级模式

  高通8K以后平台支持如下两种,说到下载模式,忍不住又得骂高通。 
  以前6K, 7K平台不支持紧急下载模式,工厂生产软件要down到手机里,非常复杂。
  要嘛先用烧录器烧一段sbl image,然后剩下的image自己开发升级软件用usb多路升级。
  要嘛全部image用烧录器一次性烧完。
  坑人的高通啊!么得办法,就害苦咱苦命的民工。 好了,介绍一下现在支持的两种下载模式吧! 
  紧急下载模式:pbl负责与PC交互,实现软件下载
  自动进入紧急下载模式:主板刚生产emmc是裸片时,或者sbl运行异常时,系统自动进入紧急下载模式。
            这种情况就不多说了,主要是用于工厂生产,及sbl异常处理。

  手动进入紧急下载模式:通过硬件一个gpio下拉,pbl检测到该gpio后强制进入紧急下载模式。这种主要
             以防不测情况。
   另外一种就是软件通过设置magic number,然后由热重启,pbl检测到magic number后,强制进入下载模式。

  软件切换接口,参考如下boot_dload.c代码:
[cpp]  view plain  copy
 print ?
  1. /*============================================================================= 
  2.  
  3. **  Function :  boot_dload_transition_pbl_forced_dload 
  4.  
  5. ** ========================================================================== 
  6. */  
  7. /*! 
  8.  
  9. * @brief 
  10. *   This function sets the magic numbers for PBL to detect and enter forced 
  11. *   download mode.  It then calls the target specific function to trigger a 
  12. *   system reset. 
  13.  
  14. * @par Dependencies 
  15. *   None 
  16. *    
  17. * @retval 
  18. *   None 
  19.  
  20. * @par Side Effects 
  21. *   Set's PBL magic numbers to enter forced download, resets target, never to 
  22. *   return. 
  23.  
  24. */  
  25. void <strong>boot_dload_transition_pbl_forced_dload</strong>( void )  
  26. {  
  27.   /* PBL uses the last four bits of BOOT_MISC_DETECT to trigger forced download. 
  28.      Preserve the other bits of the register. */  
  29.   
  30.   uint32 register_value =   
  31.     HWIO_TCSR_BOOT_MISC_DETECT_INM(HWIO_TCSR_BOOT_MISC_DETECT_RMSK);  
  32.   
  33.   /* Clear the PBL masked area and then apply HS_USB value */  
  34.   register_value &= ~(FORCE_DLOAD_MASK);  
  35.   register_value |= FORCE_DLOAD_HS_USB_MAGIC_NUM;  
  36.   
  37.   /* Write the new value back out to the register */  
  38.   HWIO_TCSR_BOOT_MISC_DETECT_OUTM(FORCE_DLOAD_MASK,  
  39.                                   register_value);  
  40.   
  41.   boot_hw_reset(BOOT_WARM_RESET_TYPE);  
  42. /* boot_dload_transition_pbl_forced_dload() */  
 普通下载模式:sbl负责与PC交互,实现软件下载
 手机第一次下载完软件以后,普通情况下,可不进入pbl紧急下载模式,可由sbl进行软件升级。
 sbl是如何进入普通下载模式的呢?看如下函数boot_dload_check()。
 boot_dload_check()检测到USB D+ 接地或者sbl发生异常时调用boot_dload_set_cookie()设置了cookie,进自  动进入普通的下载模式。
[cpp]  view plain  copy
 print ?
  1. <pre name="code" class="cpp">  
  2. /*=========================================================================== 
  3.  
  4. **  Function :  boot_dload_check 
  5.  
  6. ** ========================================================================== 
  7. */  
  8. /*! 
  9.  
  10. * @brief 
  11. *   This function will check to see if the downloader should be entered 
  12. *   for QPST download, and enter the downloader if directed to. 
  13. *   
  14. * @param[in] bl_shared_data Pointer to the shared data  
  15. * 
  16. * @par Dependencies 
  17. *   Download ID must be present in IRAM if downloader is to be entered. 
  18.  
  19. * @retval 
  20. *   None 
  21.  
  22. * @par Side Effects 
  23. *   Boot may be halted and QPST downloader entered. 
  24.  
  25. */  
  26. void boot_dload_check  
  27. (   
  28.   bl_shared_data_type *bl_shared_data   
  29. )  
  30. {  
  31.   /* Check whether USB D+ line is grounded. If it is, then enter 
  32.      PBL Download mode */  
  33. <strong><span style="color:#cc0000;">  if(boot_qhsusb_al_check_for_pbl_dload(0))  
  34.   {  
  35.     boot_dload_transition_pbl_forced_dload();  
  36.   }</span></strong>  
  37.   
  38.   /* Determine if the downloader should be entered at this time, 
  39.      instead of continuing with the normal boot process. */  
  40.   if ( boot_dload_entry( ) == TRUE )  
  41.   {  
  42.     /* Check the UEFI ram dump cookie, we enter download mode 
  43.        only if UEFI ram dump cookie is NOT set*/  
  44.     if ( !( boot_shared_imem_cookie_ptr != NULL &&  
  45.             boot_shared_imem_cookie_ptr->uefi_ram_dump_magic ==   
  46.             UEFI_CRASH_DUMP_MAGIC_NUM ) )  
  47.     {  
  48.       /* Before entering downloader clear RESET_DEBUG[BLOCK_RESIN] so 
  49.          the next resin_n is not blocked.  This is part of the abnormal 
  50.          reset logic in Bear family */  
  51.       HWIO_GCC_RESET_DEBUG_OUTM(HWIO_GCC_RESET_DEBUG_BLOCK_RESIN_BMSK,  
  52.                                 0);  
  53.   
  54.       /* Enter downloader for QPST */    
  55.       sbl_dload_entry();  
  56.     }  
  57.   }  
  58. /* boot_dload_check() */  
 
 
[cpp]  view plain  copy
 print ?
  1. /*=========================================================================== 
  2. **  Function :  boot_dload_set_cookie 
  3. ** ========================================================================== 
  4. */  
  5. /*! 
  6.  
  7. * @brief 
  8. *   Set the SBL dload mode cookie 
  9. **         
  10. * @par Dependencies 
  11. *  None 
  12. *    
  13. */  
  14. void boot_dload_set_cookie()  
  15. {  
  16.   HWIO_TCSR_BOOT_MISC_DETECT_OUTM(SBL_DLOAD_MODE_BIT_MASK,  
  17.                                   SBL_DLOAD_MODE_BIT_MASK);  
  18. }  
再看看下面的代码!!! 我们又有新的发现!
sbl1_target.c
[cpp]  view plain  copy
 print ?
  1. <pre name="code" class="cpp">/*=========================================================================== 
  2.  
  3. **  Function :  sbl_dload_entry 
  4.  
  5. ** ========================================================================== 
  6. */  
  7. /*! 
  8.  
  9. * @brief 
  10. *   This function pointer is defined in each SBL* Bootloader to handle SBL-specific 
  11. *   requirements to enter a download routine. It is initialized to  
  12. *   boot_dload_transition_pbl_forced_dload by default. 
  13. *   
  14. * @par Dependencies 
  15. *   None 
  16. *    
  17. * @retval 
  18. *   None 
  19.  
  20. * @par Side Effects 
  21. *   None 
  22.  
  23. */  
  24. void (*sbl_dload_entry)(void) = boot_dload_transition_pbl_forced_dload;   
函数指针sbl_dload_entry默认指向紧急下载模式的入口:boot_dload_transition_pbl_forced_dload ,
该下载方式会切换到pbl,由pbl通过firehose协议实现download。
 
 
[cpp]  view plain  copy
 print ?
  1. void sbl1_dload_entry ()  
  2. {  
  3.   static uint32 dload_entry_count = 0;  
  4.   
  5.   dload_entry_count++;   
  6.   
  7.   /* Only execute the pre-dload procedures the first time we try to enter 
  8.    * dload in case there is an error within these procedures. */  
  9.   if( dload_entry_count == 1 && &bl_shared_data != NULL )  
  10.   {  
  11.     /* Entering dload routine for the first time */  
  12.     <strong>boot_do_procedures</strong>( &bl_shared_data, sbl1_pre_dload_procs );  
  13.   }  
  14.   
  15.   pm_device_config_in_dloadmode();  
  16.     
  17.   /* Enter boot Sahara */  
  18.   <strong>boot_dload_transition_enter_sahara</strong>();  
  19.     
  20. }/* sbl1_dload_entry() */  
而sbl1定义了另一个下载模式的入口:sbl1_dload_entry,它支持直接在sbl1中通过sahara协议download,
还支持crash ram dump 功能。包括dump to raw partition ,and dump to sdcard 。
见:boot_do_procedures( &bl_shared_data, sbl1_pre_dload_procs ); 
crash ramdump章节再详细看看。

sbl1_mc.c

[cpp]  view plain  copy
 print ?
  1. <pre name="code" class="cpp">/*DLOAD flag for SBL1 to enter PBL error handler*/  
  2. #ifdef BOOT_ENTER_PBL_DLOAD_ON_SBL_ERROR  
  3.   static boot_boolean edload_flag = TRUE;  
  4. #else  
  5.   static boot_boolean edload_flag = FALSE;  
  6. #endif  
 
  
[cpp]  view plain  copy
 print ?
  1. </pre><pre name="code" class="cpp">void sbl1_post_ddr_init(bl_shared_data_type *bl_shared_data)  
  2. {  
  3.    ..........  
  4.     
  5.   if (edload_flag != TRUE)  
  6.   {  
  7.     /* Update the dload entry to sbl1 sahara dload entry function */  
  8.     sbl_dload_entry = sbl1_dload_entry;  
  9.   }   
  10. }  
好,既然在sbl1有两个download入口,如何选则呢? 
sbl1_mc.c 中通过宏BOOT_ENTER_PBL_DLOAD_ON_SBL_ERROR控制。
如果定义该宏,则dload处理会转交给PBL帮忙处理了。

2、进入升级模式的方法

  上节描述的高通默认进入下载模式的方法,都是自动的,显然无法满足开发、生产、售后等需求。
  因此如下两种方法,实用于开发、生产、售后。

   sbl1扫描按键组合:
  关机状态下,sbl1扫描按键组合,比如,扫描到power & vol+ 两个按键同时按下,则进入pbl紧急下模模式。
  当然,有些结构设计可能导致power & vol+ 两个按键开机容易误触,则可以采用别的硬件组合方式。比如,
  vol+ & usb 等等!

  关机状态,进入下载模式,没有ram dump的需求,因此当扫描到相应的硬件组合,
  直接调用:boot_dload_transition_pbl_forced_dload

   adb reboot + edl / dload :
       手机正常开机,能连接usb上的状态下,可以使用 adb reboot edl 或者 adb reboot dload 命令,
  使手机进入pbl紧急下载模式,或者进入sbl1普通下载模式。 

  MSM8916平台参考如下代码,
  kernel/drivers/power/reset/msm-poweroff.c ,相关代码由宏CONFIG_MSM_DLOAD_MODE控制。
[cpp]  view plain  copy
 print ?
  1. static int msm_restart_probe(struct platform_device *pdev)  
  2. {  
  3.     struct device *dev = &pdev->dev;  
  4.     struct resource *mem;  
  5.     struct device_node *np;  
  6.     int ret = 0;  
  7.   
  8. #ifdef CONFIG_MSM_DLOAD_MODE  
  9.     if (scm_is_call_available(SCM_SVC_BOOT, SCM_DLOAD_CMD) > 0)  
  10.         scm_dload_supported = true;  
  11.   
  12.     atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);  
  13.     np = of_find_compatible_node(NULL, NULL, DL_MODE_PROP);  
  14.     if (!np) {  
  15.         pr_err("unable to find DT imem DLOAD mode node\n");  
  16.     } else {  
  17.         dload_mode_addr = of_iomap(np, 0);  
  18.         if (!dload_mode_addr)  
  19.             pr_err("unable to map imem DLOAD offset\n");  
  20.     }  
  21.   
  22.     np = of_find_compatible_node(NULL, NULL, EDL_MODE_PROP);  
  23.     if (!np) {  
  24.         pr_err("unable to find DT imem EDLOAD mode node\n");  
  25.     } else {  
  26.         emergency_dload_mode_addr = of_iomap(np, 0);  
  27.         if (!emergency_dload_mode_addr)  
  28.             pr_err("unable to map imem EDLOAD mode offset\n");  
  29.     }  
  30.   
  31.     set_dload_mode(download_mode);  
  32. #endif  
  33.     np = of_find_compatible_node(NULL, NULL,  
  34.                 "qcom,msm-imem-restart_reason");  
  35.     if (!np) {  
  36.         pr_err("unable to find DT imem restart reason node\n");  
  37.     } else {  
  38.         restart_reason = of_iomap(np, 0);  
  39.         if (!restart_reason) {  
  40.             pr_err("unable to map imem restart reason offset\n");  
  41.             ret = -ENOMEM;  
  42.             goto err_restart_reason;  
  43.         }  
  44.     }  
  45.   
  46.     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  47.     msm_ps_hold = devm_ioremap_resource(dev, mem);  
  48.     if (IS_ERR(msm_ps_hold))  
  49.         return PTR_ERR(msm_ps_hold);  
  50.   
  51.     pm_power_off = do_msm_poweroff;  
  52.     arm_pm_restart = do_msm_restart;  
  53.   
  54.     if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER) > 0)  
  55.         scm_pmic_arbiter_disable_supported = true;  
  56.   
  57.     return 0;  
  58.   
  59. err_restart_reason:  
  60. #ifdef CONFIG_MSM_DLOAD_MODE  
  61.     iounmap(emergency_dload_mode_addr);  
  62.     iounmap(dload_mode_addr);  
  63. #endif  
  64.     return ret;  
  65. }  
msm_restart_probe函数在执行过程中打印出如下log,说明dts中没有设置emergency_dload_mode_addr,及dload_mode_addr的地址。
<3>[    6.627538] unable to find DT imem DLOAD mode node
<3>[    6.628075] unable to find DT imem EDLOAD mode node
但添加scm_dload_supported的打印信息,可以看到如下log,
<3>[    6.626976]  scm_dload_supported=1 ,
说明,scm dload是支持的。因此,接下来的两个函数,都是通过scm dload实现download模式切换。
[cpp]  view plain  copy
 print ?
  1. static void enable_emergency_dload_mode(void)  
  2. {  
  3.     int ret;  
  4.   
  5.     if (emergency_dload_mode_addr) {  
  6.         __raw_writel(EMERGENCY_DLOAD_MAGIC1,  
  7.                 emergency_dload_mode_addr);  
  8.         __raw_writel(EMERGENCY_DLOAD_MAGIC2,  
  9.                 emergency_dload_mode_addr +  
  10.                 sizeof(unsigned int));  
  11.         __raw_writel(EMERGENCY_DLOAD_MAGIC3,  
  12.                 emergency_dload_mode_addr +  
  13.                 (2 * sizeof(unsigned int)));  
  14.   
  15.         /* Need disable the pmic wdt, then the emergency dload mode 
  16.          * will not auto reset. */  
  17.         qpnp_pon_wd_config(0);  
  18.         mb();  
  19.     }  
  20.   
  21.     if (scm_dload_supported) {  
  22.         ret = scm_call_atomic2(SCM_SVC_BOOT,  
  23.                 SCM_DLOAD_CMD, SCM_EDLOAD_MODE, 0);  
  24.         if (ret)  
  25.             pr_err("Failed to set EDLOAD mode: %d\n", ret);  
  26.     }  
  27. }  
使能紧急下载模式。
[cpp]  view plain  copy
 print ?
  1. static void set_dload_mode(int on)  
  2. {  
  3.     int ret;  
  4.   
  5.     if (dload_mode_addr) {  
  6.         __raw_writel(on ? 0xE47B337D : 0, dload_mode_addr);  
  7.         __raw_writel(on ? 0xCE14091A : 0,  
  8.                dload_mode_addr + sizeof(unsigned int));  
  9.         mb();  
  10.     }  
  11.   
  12.     if (scm_dload_supported) {  
  13.         ret = scm_call_atomic2(SCM_SVC_BOOT,  
  14.                 SCM_DLOAD_CMD, on ? SCM_DLOAD_MODE : 0, 0);  
  15.         if (ret)  
  16.             pr_err("Failed to set DLOAD mode: %d\n", ret);  
  17.     }  
  18.   
  19.     dload_mode_enabled = on;  
  20. }  
使能普通下载模式。
这样adb reboot edl 或者 adb reboot dload 命令就可以使手机进入下载模式了。

3、软件升级工具及协议

高通平台,从MSM6K 、7K 到8K, download的方法和协议,一直在更新。
协议经历了从stream dload到sahara,再到现在firehose 。
每一种协议的具体描述参考如下文档: 
80-V5348-1_J_Streaming_DLoad_Protocol.pdf

80-N1008-1_H_SaharaProtocolSpecification.pdf

80-NG319-1_A_Firehose Protocol V1.0_Def_Doc.pdf

参见本人的另一篇介绍《qualcomm 8K平台Sahara Protocol相对7K, 6K 平台Software Download优点》。


根据使用不同协议,相应的,高通提供两个下载工具:eMMC Software Download  和 QFIL (Qualcomm Flash Image Loader ) 

如下俩图 :

高通 MSM8K bootloader 之二: SBL1_第1张图片


通过这种普通下载模式,进入下载模后,windows设备管理器可以看到PC端枚举出一个9006的USB端口,

同时枚举出一个mass storage。

高通这种mass storage模式下载速率是非常的快。可是我也它有如下一些缺点:

pc端枚举mass storage速度很慢,根据测试也非常耗cpu。

pc端枚举mass storage容易出错,特别是多台手机同时枚举时。

纠错不易,按文件方式写入,目前我还没想到什么方法进行纠错?


好,下面贴相关代码所在的路径,及调用到的重要函数贴出来!

boot_images/core/storage/tools/emmcbld


boot_images/core/boot/secboot3/hw/msm8916/sbl1/

sbl1_mc.c

sbl1_target.c

sbl1_sahara.c


boot_images/core/boot/secboot3/src/

boot_sahara.c

boot_extern_hsusb_interface.c


boot_images/core/wiredconnectivity/qhsusb/src/al/qhsusb_al_bulk.c


boot_images/core/wiredconnectivity/qhsusb/src/func/

qhsusb_fd_hdlc.c

qhsusb_fd_ms.c

qhsusb_scsi.c

[cpp]  view plain  copy
 print ?
  1. void sbl1_dload_entry ()  
  2. {  
  3.   static uint32 dload_entry_count = 0;  
  4.   
  5.   dload_entry_count++;   
  6.   
  7.   /* Only execute the pre-dload procedures the first time we try to enter 
  8.    * dload in case there is an error within these procedures. */  
  9.   if( dload_entry_count == 1 && &bl_shared_data != NULL )  
  10.   {  
  11.     /* Entering dload routine for the first time */  
  12.     boot_do_procedures( &bl_shared_data, sbl1_pre_dload_procs );  
  13.   }  
  14.   
  15.   pm_device_config_in_dloadmode();  
  16.     
  17.   /* Enter boot Sahara */  
  18.   boot_dload_transition_enter_sahara();  
  19.     
  20. }/* sbl1_dload_entry() */  

[cpp]  view plain  copy
 print ?
  1. /*=========================================================================== 
  2.  
  3. **  Function :  boot_dload_transition_enter_sahara 
  4.  
  5. ** ========================================================================== 
  6. */  
  7. /*! 
  8.  
  9. * @brief 
  10. *   This function is implemented in each SBL to enter sahara dload mode 
  11. * 
  12. * @par Dependencies 
  13. *   None 
  14. *    
  15. * @retval 
  16. *   None 
  17.  
  18. * @par Side Effects 
  19. *   None 
  20.  
  21. */  
  22. void boot_dload_transition_enter_sahara(void)  
  23. {  
  24.   /* Get Sahara interface */  
  25.   struct boot_sahara_interface* sbl_sahara_interface = sbl_sahara_get_interface();  
  26.   BL_VERIFY(sbl_sahara_interface != NULL, BL_ERR_NULL_PTR);  
  27.     
  28.   /* Set Sahara mode to memory debug */  
  29.   sbl_sahara_interface->sahara_mode = SAHARA_MODE_MEMORY_DEBUG;  
  30.     
  31.   /* Flush the cache before calling into sahara so that all data is flushed to memory */    
  32.   mmu_flush_cache();  
  33.     
  34.   /* Enter Sahara */  
  35.   boot_sahara_entry(sbl_sahara_interface);  
  36. }  

调用sbl_sahara_get_interface获取sahara如下函数接口:sbl_sahara_interface

调用boot_sahara_entry。

[cpp]  view plain  copy
 print ?
  1. /* SBL Sahara dispatch table */  
  2. static struct boot_sahara_dispatch_tbl sbl_sahara_dispatch_tbl =   
  3. {  
  4.   SAHARA_INTERFACE_DISPATCH_VERSION,  
  5.   sbl_sahara_bulk_init,  
  6.   boot_qhsusb_al_bulk_shutdown,  
  7.   boot_qhsusb_al_bulk_poll,  
  8.   (sahara_rx_bulk_type) sbl_sahara_rx_bulk,  
  9.   (sahara_tx_bulk_type) boot_qhsusb_al_bulk_transmit,  
  10.   boot_qhsusb_al_bulk_get_max_packet_size,  
  11.   sbl_sahara_reset,  
  12.   boot_clobber_check_global_whitelist_range,  
  13.   sbl_sahara_exec_cmd,  
  14.   boot_qhsusb_al_bulk_get_max_raw_data_size,  
  15.   sbl_sahara_is_auth_enabled,  
  16.   qmemcpy,  
  17.   qmemset,  
  18.   sbl_sahara_get_bin_header_size,  
  19.   sbl_sahara_get_bin_image_id,  
  20.   sbl_sahara_get_bin_image_dest,  
  21.   sbl_sahara_get_bin_image_size,  
  22.   sbl_sahara_get_bin_code_size,  
  23.   sbl_sahara_get_bin_cert_chain_size,  
  24.   sbl_sahara_get_bin_signature_size,  
  25.   sbl_sahara_get_bin_image_src,  
  26.   sbl_sahara_unrecoverable_error_handler,  
  27.   sbl_sahara_image_load_post_proc,  
  28.   sbl_sahara_skip_image_load,    
  29.   boot_get_hash_segment_buffer,  
  30.   sbl_elf_optimized_segment_load,  
  31.   NULL,  
  32.   NULL,  
  33. };  
[cpp]  view plain  copy
 print ?
  1. /* ============================================================================ 
  2. **  Function : boot_sahara_entry 
  3. ** ============================================================================ 
  4. */  
  5. /*! 
  6. *   @brief 
  7. *   This function provides an entry into the Sahara protocol and jumps into 
  8. *   the protocol. 
  9. *    
  10. *   @details 
  11. *   This function initializes the Sahara protocol followed by sending a HELLO 
  12. *   packet to the host. After that, the target will proceed to wait for 
  13. *   incoming packets and handle them appropriately. 
  14. *    
  15. *   @param sahara_interface      -  [IN/OUT] Interface to be used by protocol 
  16. *    
  17. *   @par Dependencies 
  18. *   None 
  19. *    
  20. *   @par Side Effects 
  21. *   boot_sahara_init() will be called which calls the dispatch table's init() 
  22. *   routine - this is intended to initialize any hardware that is required 
  23. *   for the protocol to execute. 
  24. *    
  25. *   @retval  Boolean 
  26. *    
  27. *   @sa None 
  28. */  
  29. boolean boot_sahara_entry  
  30. (  
  31.   struct boot_sahara_interface* sahara_interface  
  32. )  
  33. {  
  34.   boolean status = TRUE;  
  35.   
  36.   sahara_if = sahara_interface;  
  37.   
  38.   // Validate interface and initialize Sahara protocol if not previously executed  
  39.   status = boot_sahara_init();  
  40.   
  41.   if (status)  
  42.   {  
  43.     // Send hello packet  
  44.     boot_sahara_handle_hello();  
  45.       
  46.     // Enter Sahara packet handler  
  47.     boot_sahara_process_packets();  
  48.       
  49.     // Reset authentication information  
  50.     sahara_auth_tbl = NULL;  
  51.     sahara_auth_elf = FALSE;  
  52.     sahara_auth_bin = FALSE;  
  53.   }  
  54.     
  55.   return status;  
  56. }  

调用函数boot_sahara_init初始化sahara协议,枚举usb com口及mass storage。

调用函数boot_sahara_handle_hello主动发送hello packet, 

调用函数boot_sahara_process_packets处理其它cmd packets。

[cpp]  view plain  copy
 print ?
  1. /* ============================================================================ 
  2. **  Function : boot_sahara_init 
  3. ** ============================================================================ 
  4. */  
  5. /*! 
  6. *   @brief 
  7. *   This function initializes the state for the Sahara protocol 
  8. *    
  9. *   @details 
  10. *   This function performs basic initialization in order to transfer an image. 
  11. *   Based on the image type, the current image in shared data will be updated. 
  12. *   This function also initializes the internal state machine and hardware 
  13. *   driver. 
  14. *    
  15. *   @param  None 
  16. *    
  17. *   @par Dependencies 
  18. *   None 
  19. *    
  20. *   @par Side Effects 
  21. *   None 
  22. *    
  23. *   @retval  TRUE if initialization was successful; FALSE otherwise 
  24. *    
  25. *   @sa None 
  26. */  
  27. static boolean boot_sahara_init ( void )  
  28. {  
  29.   boolean status = TRUE;  
  30.   
  31.   do  
  32.   {  
  33.     // Check parameters  
  34.     if (sahara_if == NULL)  
  35.     {  
  36.       status = FALSE;  
  37.       break;  
  38.     }  
  39.     if ((sahara_if->sahara_shared_data == NULL) ||  
  40.         (sahara_if->dispatch_tbl == NULL))  
  41.     {  
  42.       status = FALSE;  
  43.       break;  
  44.     }  
  45.   
  46.     sahara_shared_data = sahara_if->sahara_shared_data;  
  47.     sahara_dispatch_tbl = sahara_if->dispatch_tbl;  
  48.   
  49.     if (sahara_if->sahara_shared_data->cur_image == NULL)  
  50.     {  
  51.       status = FALSE;  
  52.       break;  
  53.     }  
  54.   
  55.     // Verify dispatch table  
  56.     if ((sahara_dispatch_tbl->init == NULL) ||  
  57.         (sahara_dispatch_tbl->shutdown == NULL) ||  
  58.         (sahara_dispatch_tbl->poll == NULL) ||  
  59.         (sahara_dispatch_tbl->rx_bulk == NULL) ||  
  60.         (sahara_dispatch_tbl->tx_bulk == NULL) ||  
  61.         (sahara_dispatch_tbl->shutdown == NULL) ||  
  62.         (sahara_dispatch_tbl->get_max_packet_size == NULL) ||  
  63.         (sahara_dispatch_tbl->reset == NULL) ||  
  64.         (sahara_dispatch_tbl->valid_address_range == NULL) ||  
  65.         (sahara_dispatch_tbl->exec_cmd == NULL) ||  
  66.         (sahara_dispatch_tbl->get_max_raw_data_size == NULL) ||  
  67.         (sahara_dispatch_tbl->auth_enabled == NULL) ||  
  68.         (sahara_dispatch_tbl->memcpy == NULL) ||  
  69.         (sahara_dispatch_tbl->memset == NULL) ||  
  70.         (sahara_dispatch_tbl->get_bin_header_size == NULL) ||  
  71.         (sahara_dispatch_tbl->get_bin_image_id == NULL) ||  
  72.         (sahara_dispatch_tbl->get_bin_image_dest == NULL) ||  
  73.         (sahara_dispatch_tbl->get_bin_image_size == NULL) ||  
  74.         (sahara_dispatch_tbl->get_bin_code_size == NULL) ||  
  75.         (sahara_dispatch_tbl->get_bin_cert_chain_size == NULL) ||  
  76.         (sahara_dispatch_tbl->get_bin_signature_size == NULL) ||  
  77.         (sahara_dispatch_tbl->get_hash_segment_buffer == NULL))  
  78.     {  
  79.       status = FALSE;  
  80.       break;  
  81.     }  
  82.   
  83.     // Determine if image should be authenticated  
  84.     sahara_shared_data->is_secure = sahara_dispatch_tbl->auth_enabled();  
  85.     sahara_auth_tbl = sahara_if->auth_tbl;  
  86.    if (((sahara_auth_tbl == NULL) ||  
  87.         (sahara_auth_tbl->authenticate == NULL)) &&   
  88.         (sahara_if->sahara_mode != SAHARA_MODE_MEMORY_DEBUG))  
  89.   
  90.     {  
  91.       status = FALSE;  
  92.       break;  
  93.     }  
  94.     else if (sahara_shared_data->is_secure &&  
  95.         (sahara_shared_data->expected_image_type == SAHARA_IMAGE_TYPE_ELF))  
  96.     {  
  97.         sahara_auth_elf = TRUE;  
  98.     }  
  99.     else if (sahara_shared_data->is_secure &&  
  100.             (sahara_shared_data->expected_image_type == SAHARA_IMAGE_TYPE_BINARY))  
  101.     {  
  102.         sahara_auth_bin = TRUE;  
  103.     }  
  104.   
  105.     sahara_mem_debug_tbl = sahara_if->mem_debug_tbl;  
  106.     if (sahara_mem_debug_tbl == NULL)  
  107.     {  
  108.       sahara_mem_debug_enabled = FALSE;  
  109.     }  
  110.     else  
  111.     {  
  112.       if ((sahara_mem_debug_tbl->mem_debug_supported == NULL) ||  
  113.           (sahara_mem_debug_tbl->mem_debug_init == NULL) ||  
  114.           (sahara_mem_debug_tbl->mem_debug_verify_addr == NULL) ||  
  115.           (sahara_mem_debug_tbl->mem_debug_table_addr == NULL) ||  
  116.           (sahara_mem_debug_tbl->mem_debug_table_len == NULL) ||  
  117.           (sahara_mem_debug_tbl->mem_debug_is_restricted_addr == NULL) ||  
  118.           (sahara_mem_debug_tbl->mem_debug_copy_restricted == NULL))  
  119.       {  
  120.         status = FALSE;  
  121.         break;  
  122.       }  
  123.       else  
  124.       {  
  125.         sahara_mem_debug_enabled = TRUE;  
  126.       }  
  127.     }  
  128.   
  129.     if (sahara_shared_data->expected_image_type == SAHARA_IMAGE_TYPE_BINARY)  
  130.     {  
  131.       sahara_binary_image_info =   
  132.         (struct boot_sahara_binary_image_info*)sahara_shared_data->cur_image;  
  133.   
  134.       // Initialize binary image info  
  135.       sahara_binary_image_info->image_id = 0;  
  136.       // Check the binary image header has been initialized to a valid address  
  137.       if (sahara_binary_image_info->header == NULL)  
  138.       {  
  139.         status = FALSE;  
  140.         break;  
  141.       }  
  142.       sahara_dispatch_tbl->memset(sahara_binary_image_info->header,   
  143.                                   0,   
  144.                                   sahara_dispatch_tbl->get_bin_header_size());  
  145.     }  
  146.     else if (sahara_shared_data->expected_image_type == SAHARA_IMAGE_TYPE_ELF)  
  147.     {  
  148.       sahara_elf_image_info =   
  149.         (struct boot_sahara_elf_image_info*)sahara_shared_data->cur_image;  
  150.       // Check program headers buffer has been initialized to a valid address  
  151.       if (sahara_elf_image_info->prog_headers == NULL)  
  152.       {  
  153.         status = FALSE;  
  154.         break;  
  155.       }  
  156.   
  157.       // Initialize ELF image info  
  158.       sahara_elf_image_info->image_id = 0;  
  159.       sahara_dispatch_tbl->memset(&(sahara_elf_image_info->elf_header),   
  160.                                   0,  
  161.                                   sizeof(Elf32_Ehdr));  
  162.       sahara_elf_image_info->hash_table = NULL;  
  163.       sahara_dispatch_tbl->memset(&(sahara_elf_image_info->shared_seg_index),   
  164.                                   0,  
  165.                                   sizeof(uint32));  
  166.       sahara_dispatch_tbl->memset(&(sahara_elf_image_info->entry_address),   
  167.                                   0,  
  168.                                   sizeof(uint32));  
  169.       /* zero initialize progressive_boot_block up to max possible  
  170.          prog-header entries */   
  171.       sahara_dispatch_tbl->memset((sahara_elf_image_info->prog_headers),  
  172.                                   0,  
  173.                                   sizeof(struct progressive_boot_block));  
  174.     }  
  175.     else if (sahara_if->sahara_mode != SAHARA_MODE_MEMORY_DEBUG)  
  176.     {  
  177.       // Image type not supported and not in memory debug mode  
  178.       status = FALSE;  
  179.       break;  
  180.     }  
  181.   
  182.     // Initialize Sahara state information  
  183.     sahara_if->sahara_shared_data->image_rx_complete = FALSE;  
  184.     sahara_mode = (enum boot_sahara_mode) sahara_if->sahara_mode;  
  185.     sahara_state = SAHARA_STATE_ENTRY;  
  186.     sahara_done = FALSE;  
  187.     
  188.     // Initialize hardware driver interface  
  189.     if(BULK_SUCCESS != sahara_dispatch_tbl->init())  
  190.     {  
  191.       status = FALSE;  
  192.         break;  
  193.     }  
  194.   } while (0);  
  195.   
  196.   if(NULL != sahara_if)  
  197.   {  
  198.     if (status == FALSE)  
  199.     {  
  200.       // Report error in initialize to Sahara client  
  201.       sahara_if->sahara_status = SAHARA_NAK_TARGET_INIT_FAILURE;  
  202.     }  
  203.     else  
  204.     {  
  205.       // Initialize sahara status  
  206.       sahara_if->sahara_status = SAHARA_STATUS_SUCCESS;  
  207.     }  
  208.   }  
  209.   
  210.   return status;  
  211. }  

调用sahara_dispatch_tbl->init函数指针, 即sbl1_sahara.c文件中的sbl_sahara_bulk_init()。

[cpp]  view plain  copy
 print ?
  1. struct qhsusb_dcd_dsc_device* qhsusb_fd_hdlc_init(void (*rx_callback)(struct qhsusb_urb* urb),  
  2.                                                   uint8* str_product,  
  3.                                                   void (*tx_callback)(struct qhsusb_urb* urb),  
  4.                                                   void (*enum_complete)(void),  
  5.                                                   void (*error_handler)(void),  
  6.                                                   qhsusb_transfer_mode transfer_mode)  
  7. #else  
  8. struct qhsusb_dcd_dsc_device* qhsusb_fd_hdlc_init(void (*rx_callback)(struct qhsusb_urb* urb),  
  9.                                                   uint8* str_product,  
  10.                                                   void (*tx_callback)(struct qhsusb_urb* urb),  
  11.                                                   void (*enum_complete)(void),  
  12.                                                   qhsusb_transfer_mode transfer_mode)  
  13. #endif  
  14. {  
  15.    boolean hdlc_enum_already_exists = FALSE;  
  16.   
  17.    struct qhsusb_urb* urb;  
  18.   
  19.    qhsusb_transfer_mode_g = transfer_mode;     
  20.    qhsusb_log(QHSUSB_FD_HDLC_INIT_LOG,0,0);  
  21. #ifndef FEATURE_SKIP_SERIAL_STR_UPDATE  
  22.    qhsusb_fd_hdlc_update_pid_and_serial_number_string();  
  23. #endif   
  24.    if ( NULL != str_product ) {  
  25.       sw_device.strings[2].descriptor = (struct usb_desc_header*)(void*)str_product;  
  26.    }  
  27.    /* set up sw -> hw links */  
  28. #if defined(FEATURE_QHSUSB_HDLC_CDCACM)  
  29.    hdlc_shutdown_in_progress = 0;  
  30.    if ( 0 != hdlc_use_cdcacm ) {  
  31.       sw_data_eps[0].descriptor = &hdlc_usb_config_cdcacm.ep_in;  
  32.       sw_data_eps[1].descriptor = &hdlc_usb_config_cdcacm.ep_out;  
  33.       sw_data_ifc.descriptor = &hdlc_usb_config_cdcacm.ifc_data;  
  34.       sw_config.descriptor = &hdlc_usb_config_cdcacm.conf1;  
  35.       sw_device.descriptor = &hdlc_usb_device_cdcacm;  
  36.       sw_config.interfaces = &sw_cdc_control_ifc;  
  37.    } else   
  38. #endif /* defined(FEATURE_QHSUSB_HDLC_CDCACM) */  
  39.    {  
  40.     if(QHSUSB_MODE__SER_MS == qhsusb_bulk_mode_g)  
  41.     {  
  42.       sw_data_eps[0].descriptor = &hdlc_usb_config_obex.ep_in;  
  43.       sw_data_eps[1].descriptor = &hdlc_usb_config_obex.ep_out;  
  44.       sw_data_ifc.descriptor = &hdlc_usb_config_obex.ifc_data;  
  45.       sw_config.descriptor = &hdlc_usb_config_obex.conf1;  
  46.     }  
  47.     else if (QHSUSB_MODE__SER_ONLY == qhsusb_bulk_mode_g)  
  48.     {  
  49.         sw_data_ifc.next = NULL;  
  50.         sw_data_eps[0].descriptor = &hdlc_usb_config_obex_only.ep_in;  
  51.         sw_data_eps[1].descriptor = &hdlc_usb_config_obex_only.ep_out;  
  52.         sw_data_ifc.descriptor = &hdlc_usb_config_obex_only.ifc_data;  
  53.         sw_config.descriptor = &hdlc_usb_config_obex_only.conf1;  
  54.         if(hdlc_usb_device_obex.idProduct == USB_PRODUCT_DIAG_MS )  
  55.         {  
  56.             /*For serial only mode, change the product ID to 0x9008*/  
  57.             hdlc_usb_device_obex.idProduct = USB_PRODUCT_DIAG_ONLY;   
  58.             hdlc_usb_device_obex.iSerialNumber = 0x0;  
  59.         }  
  60.     }  
  61.     else if (QHSUSB_MODE__SER_ONLY__DL_MODE == qhsusb_bulk_mode_g)  
  62.     {  
  63.         sw_data_ifc.next = NULL;  
  64.         sw_data_eps[0].descriptor = &hdlc_usb_config_obex_only.ep_in;  
  65.         sw_data_eps[1].descriptor = &hdlc_usb_config_obex_only.ep_out;  
  66.         sw_data_ifc.descriptor = &hdlc_usb_config_obex_only.ifc_data;  
  67.         sw_config.descriptor = &hdlc_usb_config_obex_only.conf1;  
  68.         if(hdlc_usb_device_obex.idProduct == USB_PRODUCT_DIAG_MS )  
  69.         {  
  70.             /*For serial only mode, change the product ID to 0x9008*/  
  71.             hdlc_usb_device_obex.idProduct = USB_PRODUCT_DIAG_ONLY;   
  72.             hdlc_usb_device_obex.iSerialNumber = 0x0;  
  73.         }  
  74.     }  
  75.       sw_device.descriptor = &hdlc_usb_device_obex;  
  76.       sw_config.interfaces = &sw_data_ifc;  
  77. #ifdef FEATURE_QHSUSB_MS  
  78.     if( QHSUSB_MODE__SER_MS == qhsusb_bulk_mode_g )  
  79.     {  
  80.         /*Initialize the MS stack when you are in download mode only*/  
  81.       qhsusb_fd_ms_init();  
  82.     }  
  83. #endif /* FEATURE_QHSUSB_MS */  
  84.    }  
  85.    // Set enum flag for RS bit to be turned ON in qhsusb_dci_init();  
  86.    qhsusb_dci_set_enum_flag(TRUE);  
  87.    qhsusb_dcd_init(&sw_device);  
  88.    user_rx_callback = rx_callback;  
  89.    if (tx_callback != NULL)  
  90.    {  
  91.       user_tx_callback = tx_callback;  
  92.    }  
  93.    if (enum_complete != NULL)  
  94.    {  
  95.       user_enum_complete = enum_complete;  
  96.    }  
  97. #ifdef FEATURE_QHSUSB_SAHARA_DOWNLOAD_PIPO  
  98.    if( error_handler !=NULL)  
  99.    {  
  100.       user_error_handler = error_handler;  
  101.    }  
  102. #endif  
  103.    hdlc_enum_already_exists = dci_skip_enumeration(sw_device.core_id);  
  104.   
  105.    /* Data buffers & URB's */  
  106.    /* tx */  
  107.    urb                      = &hdlc_tx_urb;  
  108.    urb->usb_device          = &sw_device;  
  109.    urb->endpoint_address    = sw_data_eps[0].descriptor->bEndpointAddress;  
  110.    urb->transfer_buffer_ptr = hdlc_tx_buffer;  
  111.    urb->transfer_length     = 0;  
  112.    urb->transfer_status     = 0;  
  113.    urb->send_zlp            = TRUE;  
  114.    urb->complete_callback   = hdlc_tx_callback;  
  115.    urb->is_zero_address_chain_required     = FALSE;  
  116.   
  117.    if (transfer_mode == FD_CLIENT_SUPPLIED_BUFFER_MODE) /* Client Supplied Buffer Mode */  
  118.    {  
  119.    /* rx */  
  120.    urb                      = &hdlc_rx_urb;  
  121.    urb->usb_device          = &sw_device;  
  122.    urb->endpoint_address    = sw_data_eps[1].descriptor->bEndpointAddress;  
  123.    urb->transfer_buffer_ptr = NULL; /* to be filled by al layer */  
  124.    urb->transfer_length     = 0; /* to be filled by al layer */  
  125.    urb->send_zlp            = FALSE;  
  126.    urb->complete_callback   = hdlc_rx_callback;  
  127.    urb->actual_length       = 0;  
  128.    /*Initially set the is_zero_address_chain_required to FALSE*/  
  129.    urb->is_zero_address_chain_required     = FALSE;  
  130.    }  
  131.    else /* Internal Buffer Mode */  
  132.    {  
  133.      uint8 i = 0;  
  134.      for (i = 0; i < 2; i++) {  
  135.        urb                      = &hdlc_rx_urb_fixed[i];  
  136.        urb->usb_device          = &sw_device;  
  137.        urb->endpoint_address    = sw_data_eps[1].descriptor->bEndpointAddress;  
  138.        urb->transfer_buffer_ptr = hdlc_rx_buffer_fixed[i];  
  139.        urb->transfer_length     = RX_BUF_SIZE_FIXED;  
  140.        urb->send_zlp            = FALSE;  
  141.        urb->complete_callback   = hdlc_rx_callback_int_buf_mode;  
  142.        urb->actual_length       = 0;  
  143.        /*Initially set the is_zero_address_chain_required to FALSE*/  
  144.        urb->is_zero_address_chain_required     = FALSE;  
  145.      }     
  146.    }  
  147.   
  148.    /* cdc_notify_urb */  
  149. #if defined(FEATURE_QHSUSB_HDLC_CDCACM)  
  150.    if ( 0 != hdlc_use_cdcacm ) {  
  151.       urb = &cdc_notify_urb;  
  152.       urb->usb_device          = &sw_device;  
  153.       urb->endpoint_address    = hdlc_usb_config_cdcacm.ep_notify.bEndpointAddress;  
  154.       urb->transfer_length     = 0;  
  155.       urb->complete_callback   = NULL;  
  156.    }  
  157. #endif /* defined(FEATURE_QHSUSB_HDLC_CDCACM) */  
  158.   
  159. #ifndef FEATURE_QHSUSB_PBL  
  160.    if (hdlc_enum_already_exists)  
  161.    {  
  162.      /**  
  163.      *  We got here without reconnect. enumeration already 
  164.      *  completed. Simulate connection and SET_CONFIG 
  165.      */  
  166.      qhsusb_dcd_port_status_changed(&sw_device); /* attachment, speed... */  
  167.      sw_device.address = 1;                      /* don't care, just not 0 */  
  168.   
  169.      qhsusb_dci_cancel_transfer_wo_dqh_dtd(sw_device.core_id, 1, QHSUSB_EP_DIR_RX);  
  170.      qhsusb_dci_cancel_transfer_wo_dqh_dtd(sw_device.core_id, 1, QHSUSB_EP_DIR_TX);  
  171.      qhsusb_dci_cancel_transfer_wo_dqh_dtd(sw_device.core_id, 2, QHSUSB_EP_DIR_RX);  
  172.      qhsusb_dci_cancel_transfer_wo_dqh_dtd(sw_device.core_id, 2, QHSUSB_EP_DIR_TX);  
  173.   
  174.      qhsusb_dcd_set_config(&sw_device, 1);  
  175.   
  176.      if (transfer_mode == FD_USB_INTERNAL_BUFFER_MODE)  
  177.      {  
  178.        hdlc_init_rx_int_buf_mode(urb->usb_device);  
  179.      }  
  180.    }  
  181. #endif  /* !FEATURE_QHSUSB_PBL */  
  182.   
  183.    return &sw_device;  
  184. }  

sbl_sahara_bulk_init函数最终调用到qhsusb_fd_ms.c文件中的函数:qhsusb_fd_ms_init , 

整个初始化过程结束后完成com端口及mass storage枚举过程。


高通 MSM8K bootloader 之二: SBL1_第2张图片

还有!!! 坑爹的高通,以前不提供生产用的软件下载工具,都得手机厂商自己开发。

高通思想终于改变了,QRD加入后,为手机厂商提供支持多路的软件升级工具:QMSCT 。

虽然设置比较繁琐,不管怎么样,总算可用。上张图吧!

高通 MSM8K bootloader 之二: SBL1_第3张图片


QFIL和QMSCT是使用紧急下载模式,由PBL及下面firehose prog代码完成下载过程。

boot_images/core/storage/tools/deviceprogrammer

五、Crash ramdump

     哎,这篇被我写得又长又臭啦。算了,这节就不详细写了。

  高通平台开放,本身也不稳定,因此做出的手机系统很多都不稳定。因此系统crash发生时,抓取crash现场就非常重要。

  这里简单说一下,高通平台抓取系统crash现场的几种方法:

  1、 通过QPST提供的 Memory Debug Application工具,当crash发生时,手机通过usb连接到PC, 然后用这个工具将crash现场的ram dump到电脑。

   显然,这种方法是最可靠的,但它有自身的局限性:不可能每次crash发生时,测试人员或者试用人员、研发人员都刚好在pc旁边。

  2、 高通平台sbl1提供将crash现场dump到sdcard的功能,如下代码。 这种方法的局性限是:

   现在高端手机,都没有外置sdcard的配置的,而内置sdcard又使用fuse ext4文件系统,而sbl1只支持fat文件系统。 

   因此,这种不配置外置sdcard的手机,这种方法根本不可行。

[cpp]  view plain  copy
 print ?
  1. /*========================================================================== 
  2.         List of SBL1 procedures to execute prior to dload entry 
  3. ===========================================================================*/  
  4. boot_procedure_func_type sbl1_pre_dload_procs[] =  
  5. {  
  6.   /*----------------------------------------------------------------------- 
  7.    * Initialization functions for dload. This has to be the first function  
  8.    * called before Dload entry 
  9.    *----------------------------------------------------------------------*/  
  10.   boot_init_for_dload,  
  11.     
  12.   /*----------------------------------------------------------------------- 
  13.    * Setup clocks for ram dump 
  14.    *----------------------------------------------------------------------*/  
  15.   sbl1_hw_dload_init,  
  16.     
  17.   /*----------------------------------------------------------------------- 
  18.    * Ram dump to eMMC raw partition, this function will reset device  
  19.    * after successful dump collection if cookie is set  
  20.    *----------------------------------------------------------------------*/  
  21.   (boot_procedure_func_type) boot_ram_dump_to_raw_parition,  
  22.     
  23.     
  24. #ifdef FEATURE_BOOT_RAMDUMPS_TO_SD_CARD     
  25.   /*---------------------------------------------------------------------- 
  26.    * Take the Ramdumps to SD card if  cookie file is 
  27.    *   present in SD card  
  28.    *---------------------------------------------------------------------*/  
  29.   boot_ram_dumps_to_sd_card,  
  30. #endif /*FEATURE_BOOT_RAMDUMPS_TO_SD_CARD*/    
  31.   
  32.   /*----------------------------------------------------------------------- 
  33.    * NULL pointer indicates the end of the list 
  34.    *-----------------------------------------------------------------------*/  
  35.   NULL  
  36. };  


  3、 campact ramdump:这是QRD提出来的思路,即:仅dump一部分比较有用的ram到一个专门为crash分配的emmc分区。

    system crash 的主要发生的,ap核的 kernel及service,rpm , modem 等核,而上层java代码不容易导致system crash。

 而现在手机的内置越来越大,1G、2G甚至3G,整个ram都dump到一个特定分区,就浪费emmc空间了。

 因此,compact ramdump就是将一部分关键的ram dump到专门为crash分配的emmc分区。 这样就不依赖于sdcard,也不依赖于usb。而且也不浪费emmc空间。

    高通很多平台都没实现这功能,比如,msm8916, msm8974等,实现思路可以参考QRD8x25平台。

六、其它

     sbl1_hw_init ()  
    boot_smem_store_pon_status()

    sbl1_hw_init_secondary()    

    =========>  pmic  初始化,电池低电时利用内部pmic进行预充电,power key 配置,获取、保存开机原因等。 见:pm_sbl_boot.c


   sbl1_tlmm_init()    //gpio 初始化

   sbl初始化gpio的初始状态代码如下:core/systemdrivers/tlmm/config/msm8916/TLMMChipset.xml

   sbl1_efs_handle_cookies   // efs backup/restore 

  

   boot_populate_ram_partition_table

   ====> 解析iram , imem , system ram 的起始地址,大小等, 并保存到smem: SMEM_USABLE_RAM_PARTITION_TABLE ,传递给lk和kernel。

    见: boot_ram_partition.c , 这里重点看看ram的情况吧.

[cpp]  view plain  copy
 print ?
  1. /*=========================================================================== 
  2. **  Function :  sbl1_update_ddr_info 
  3. ** ========================================================================== 
  4. */  
  5. /*! 
  6.  
  7. * @brief 
  8. *   This funcion will get ddr information from ddr driver and put it in  
  9. *   sbl_shared_data.  
  10.  
  11. * @param[in] bl_shared_data Pointer to shared data 
  12. *         
  13. * @par Dependencies 
  14. *   Must be called after sbl1_ddr_init 
  15. *    
  16. * @retval 
  17. *   None 
  18.  
  19. * @par Side Effects 
  20. *   None 
  21.  
  22. */  
  23. static void sbl1_update_ddr_info(bl_shared_data_type *bl_shared_data)  
  24. {  
  25.   static sbl_if_shared_ddr_device_info_type ddr_info;  
  26.   ddr_size_info ddr_available = boot_ddr_get_size();  
  27.   ddr_size_partition ddr_partition_info = boot_ddr_get_partition();  
  28.   
  29.   boot_share_extended_ddr_info(&ddr_info, &ddr_available, &ddr_partition_info);  
  30.   bl_shared_data->sbl_shared_data->ddr_shared_info = &ddr_info;  
  31.   boot_set_ddr_info(bl_shared_data);  
  32. }  
从ddr driver层获取到ddr 类型、大小,cs等信息,保存到sbl_shared_data->ddr_shared_info, 同时保存到sbl全局变量:boot_ddr_size_info

[cpp]  view plain  copy
 print ?
  1. /*=========================================================================== 
  2.  
  3. **  Function :  add_system_ram_partitions 
  4.  
  5. ** ========================================================================== 
  6. */  
  7. /*! 
  8.  
  9. * @brief 
  10. *    Function adds all the DDR interfaces to ram partition table. 
  11. *    Each DDR interface will be added as a single entry in the table. 
  12. *    Partition category  will be RAM_PARTITION_SDRAM for all DDR entries. 
  13.  
  14. * @param[in] usable_ram_part_tbl_ptr Pointer to the ram partition table that  
  15. *                                    should be populated 
  16.  
  17. * @par Dependencies 
  18. *   None 
  19. *    
  20. * @retval 
  21. *   ram_partition_return_type 
  22. *   RAM_PART_SUCCESS        - if function is successful. 
  23. *   RAM_PART_TABLE_FULL_ERR - if table is full or not enough space in  
  24. *                             the table   
  25. *   RAM_PART_CATEGORY_NOT_EXIST_ERR - if unable to populate certain DDR information 
  26. *                              
  27. * @par Side Effects 
  28. *   None 
  29. */  
  30. static ram_partition_return_type add_system_ram_partitions  
  31. (  
  32.   usable_ram_part_table_t usable_ram_part_tbl_ptr  
  33. )  
  34. {  
  35.   ram_part_entry_t ram_part_entry_ptr = NULL;  
  36.   sbl_if_shared_ddr_info_type *ddr_info = NULL;  
  37.   sbl_if_shared_extended_ddr_info_type *ddr_extended_info = NULL;  
  38.   uint32 partition_index = 0;   
  39.   ram_partition_return_type result = RAM_PART_SUCCESS;  
  40.   sbl_if_shared_ddr_device_info_type *ddr_shared_info = boot_get_ddr_info();  
  41.     
  42.   /*ram_part_entry_ptr points to first empty slot in the table*/  
  43.   ram_part_entry_ptr =  
  44.       &usable_ram_part_tbl_ptr->  
  45.         ram_part_entry[usable_ram_part_tbl_ptr->num_partitions];  
  46.     
  47.   
  48.   /*Loop through ddr_info and add all DDR interfaces into the table*/  
  49.   for(; partition_index < ddr_shared_info->noofddr  &&  
  50.         usable_ram_part_tbl_ptr->num_partitions < RAM_NUM_PART_ENTRIES;  
  51.         partition_index++)  
  52.   {  
  53.     ddr_info = &ddr_shared_info->ddr_info[partition_index];  
  54.       
  55.     ram_part_entry_ptr->partition_category = RAM_PARTITION_SDRAM;  
  56.     ram_part_entry_ptr->start_address = ddr_info->cs_addr;        
  57.     ram_part_entry_ptr->length = ddr_info->ramsize << CONVERT_TO_BYTE_SHIFT;  
  58.     ram_part_entry_ptr->partition_attribute = RAM_PARTITION_READWRITE;  
  59.     ram_part_entry_ptr->partition_domain = RAM_PARTITION_DEFAULT_DOMAIN;  
  60.     ram_part_entry_ptr->partition_type = RAM_PARTITION_SYS_MEMORY;  
  61.       
  62.     /*Add the extended ddr information to current ram partition entry*/  
  63.     if(ddr_shared_info->ddr_partition_info != NULL)  
  64.       {  
  65.       ddr_extended_info = &ddr_shared_info->ddr_partition_info[partition_index];  
  66.         
  67.       /*Make sure the base address of ddr extended info matches the current ddr base address*/  
  68.       if (ddr_extended_info->sdram_addr != ram_part_entry_ptr->start_address)  
  69.       {  
  70.         result = RAM_PART_CATEGORY_NOT_EXIST_ERR;  
  71.         break;  
  72.       }  
  73.       ram_part_entry_ptr->num_partitions = ddr_extended_info->num_partitions;  
  74.     }  
  75.       
  76.       ram_part_entry_ptr++;  
  77.       usable_ram_part_tbl_ptr->num_partitions++;  
  78.     }  
  79.      
  80.   return result;  
  81. }  

  添加如下打印log语句在代码ddr_info = &ddr_shared_info->ddr_info[partition_index];后面,

   snprintf(message, 256, 
            "noofddr %d , cs_addr %d,  ramsize %d", ddr_shared_info->noofddr, ddr_info->cs_addr, ddr_info->ramsize);
    boot_log_message(message);

可以看到如下ddr info log信息:

B -    376400 - noofddr 2 , cs_addr 80000000,  ramsize 1024
B -    376431 - noofddr 2 , cs_addr c0000000,  ramsize 1024

七、sbl1 常用的tools介绍

sbl1常用的tools及源码在如下目录:

boot_images/core/storage/tools/ 


1、 fat32 udisk 生成工具:

boot_images/core/storage/tools/fattool ,

python fatgen.py –fat32 --name=udisk.bin --size=2048   # Generate a 2GB FAT32 container.
python fatadd.py --name=udisk.bin --from=rdcookie.txt  ----add rdcookie.txt into udisk.bin ,for test

这两个py比原来7k平台可执行文件cpfatfs功能更强了,cpfatfs只支持fat16


2、QPST下载工具(shahara):emmc programmer

 :/boot_images/core/storage/tools/emmcbld/MPRG8974.mbn


3、 T32 Jtag下载工具

boot_images/core/storage/tools/jsdcc/mjsdload.cmm 与jsdcc.elf


4、分区相关工具

boot_images/core/storage/tools/ptool/

ptool.py         //分区生成工具 partition =========> rawprogram0.xml

                    Python ptool.py –x partition.xml:

msp.py          //ubuntu使用:根据 rawprogram0.xml进行升级软件工具

                        

singleimage.py  //根据singleimage_partition_8974.xml生成single boot image: 8974_msimage.mbn

                    python singleimage.py -x singleimage_partition_8974.xml

lsusb.py       // ls usb

dd.py            // dd command

checksparse.py         //sparse system/cache/userdata image

你可能感兴趣的:(高通 MSM8K bootloader 之二: SBL1)