当前位置:   article > 正文

2. ATF(ARM Trusted firmware)启动---bl1_arm64 启动 bl1 bl2 bl3

arm64 启动 bl1 bl2 bl3

   

ATF(ARM Trusted Firmware)是一针对ARM芯片给出的底层的开源固件代码。固件将整个系统分成四种运行等级,分别为:EL0,EL1,EL2,EL3,并规定了每个安全等级中运行的Image名字。本文以ARCH64为示例,介绍冷启动时,ATF的运行过程。ATF的源代码可以从github上获取,具体地址如下:

  系统上电之后首先会运行SCP boot ROM。之后会跳转到ATF的bl1中继续执行。bl1主要初始化CPU,设定异常向量,将bl2的image加载到安全RAM中,然后跳转到bl2中进行执行。

  在bl2中将会去加载bl31和bl32以及bl33,其中的cpu状态切换以及跳转将在以下章节详细介绍。

  bl1的主要代码存放在bl1目录中, bl1的连接脚本是bl1/bl1.ld.s文件,其中可以看到bl1的入口函数是:bl1_entrypoint。

1.1 bl1_entrypoint

  该函数主要需要执行EL3环境的基本初始化,设定向量表,加载bl2 image并跳转到bl2等操作

  1. func bl1_entrypoint
  2. /* ---------------------------------------------------------------------
  3. * If the reset address is programmable then bl1_entrypoint() is
  4. * executed only on the cold boot path. Therefore, we can skip the warm
  5. * boot mailbox mechanism.
  6. * ---------------------------------------------------------------------
  7. */
  8. /* EL3级别运行环境的初始化,该函数定义在 include/common/aarch64/el3_common_macros.S文件中
  9. */
  10. el3_entrypoint_common \
  11. _set_endian=1 \
  12. _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
  13. _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
  14. _init_memory=1 \
  15. _init_c_runtime=1 \
  16. _exception_vectors=bl1_exceptions
  17. /* ---------------------------------------------
  18. * Architectural init. can be generic e.g.
  19. * enabling stack alignment and platform spec-
  20. * ific e.g. MMU & page table setup as per the
  21. * platform memory map. Perform the latter here
  22. * and the former in bl1_main.
  23. * ---------------------------------------------
  24. */
  25. bl bl1_early_platform_setup //调用bl1_early_platform_setup函数完成底层初始化
  26. bl bl1_plat_arch_setup //调用bl1_plat_arch_setup完成平台初始化
  27. /* --------------------------------------------------
  28. * Initialize platform and jump to our c-entry point
  29. * for this type of reset.
  30. * --------------------------------------------------
  31. */
  32. bl bl1_main //调用bl1_main函数,初始化验证模块,加载下一阶段的image到RAM中
  33. /* --------------------------------------------------
  34. * Do the transition to next boot image.
  35. * --------------------------------------------------
  36. */
  37. b el3_exit //调用el3_exit函数,跳转到下一个image(bl2)
  38. endfunc bl1_entrypoint

1.2 el3_entrypoint_common函数

该函数是以宏的形式被定义的,主要完成el3基本设置和向量表注册

  1. .macro el3_entrypoint_common \
  2. _set_endian, _warm_boot_mailbox, _secondary_cold_boot, \
  3. _init_memory, _init_c_runtime, _exception_vectors
  4. /* 设定大小端 */
  5. .if \_set_endian
  6. /* -------------------------------------------------------------
  7. * Set the CPU endianness before doing anything that might
  8. * involve memory reads or writes.
  9. * -------------------------------------------------------------
  10. */
  11. mrs x0, sctlr_el3
  12. bic x0, x0, #SCTLR_EE_BIT
  13. msr sctlr_el3, x0
  14. isb
  15. .endif /* _set_endian */
  16. /* 判定是否需要调用do_cold_boot流程 */
  17. .if \_warm_boot_mailbox
  18. /* -------------------------------------------------------------
  19. * This code will be executed for both warm and cold resets.
  20. * Now is the time to distinguish between the two.
  21. * Query the platform entrypoint address and if it is not zero
  22. * then it means it is a warm boot so jump to this address.
  23. * -------------------------------------------------------------
  24. */
  25. bl plat_get_my_entrypoint
  26. cbz x0, do_cold_boot
  27. br x0
  28. do_cold_boot:
  29. .endif /* _warm_boot_mailbox */
  30. /* ---------------------------------------------------------------------
  31. * It is a cold boot.
  32. * Perform any processor specific actions upon reset e.g. cache, TLB
  33. * invalidations etc.
  34. * ---------------------------------------------------------------------
  35. */
  36. bl reset_handler //执行reset handle操作
  37. /* 初始化异常向量 */
  38. el3_arch_init_common \_exception_vectors
  39. /* 判定当前CPU是否是主CPU,如果是则做主CPU的初始化 */
  40. .if \_secondary_cold_boot
  41. /* -------------------------------------------------------------
  42. * Check if this is a primary or secondary CPU cold boot.
  43. * The primary CPU will set up the platform while the
  44. * secondaries are placed in a platform-specific state until the
  45. * primary CPU performs the necessary actions to bring them out
  46. * of that state and allows entry into the OS.
  47. * -------------------------------------------------------------
  48. */
  49. bl plat_is_my_cpu_primary
  50. cbnz w0, do_primary_cold_boot
  51. /* This is a cold boot on a secondary CPU */
  52. bl plat_secondary_cold_boot_setup
  53. /* plat_secondary_cold_boot_setup() is not supposed to return */
  54. bl el3_panic
  55. do_primary_cold_boot:
  56. .endif /* _secondary_cold_boot */
  57. /* ---------------------------------------------------------------------
  58. * Initialize memory now. Secondary CPU initialization won't get to this
  59. * point.
  60. * ---------------------------------------------------------------------
  61. */
  62. /* 初始化memory */
  63. .if \_init_memory
  64. bl platform_mem_init
  65. .endif /* _init_memory */
  66. /* ---------------------------------------------------------------------
  67. * Init C runtime environment:
  68. * - Zero-initialise the NOBITS sections. There are 2 of them:
  69. * - the .bss section;
  70. * - the coherent memory section (if any).
  71. * - Relocate the data section from ROM to RAM, if required.
  72. * ---------------------------------------------------------------------
  73. */
  74. /* 初始化C语言的运行环境 */
  75. .if \_init_c_runtime
  76. #ifdef IMAGE_BL31
  77. /* -------------------------------------------------------------
  78. * Invalidate the RW memory used by the BL31 image. This
  79. * includes the data and NOBITS sections. This is done to
  80. * safeguard against possible corruption of this memory by
  81. * dirty cache lines in a system cache as a result of use by
  82. * an earlier boot loader stage.
  83. * -------------------------------------------------------------
  84. */
  85. adr x0, __RW_START__
  86. adr x1, __RW_END__
  87. sub x1, x1, x0
  88. bl inv_dcache_range
  89. #endif /* IMAGE_BL31 */
  90. ldr x0, =__BSS_START__
  91. ldr x1, =__BSS_SIZE__
  92. bl zeromem
  93. #if USE_COHERENT_MEM
  94. ldr x0, =__COHERENT_RAM_START__
  95. ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__
  96. bl zeromem
  97. #endif
  98. #ifdef IMAGE_BL1
  99. ldr x0, =__DATA_RAM_START__
  100. ldr x1, =__DATA_ROM_START__
  101. ldr x2, =__DATA_SIZE__
  102. bl memcpy16
  103. #endif
  104. .endif /* _init_c_runtime */
  105. /* ---------------------------------------------------------------------
  106. * Use SP_EL0 for the C runtime stack.
  107. * ---------------------------------------------------------------------
  108. */
  109. msr spsel, #0
  110. /* ---------------------------------------------------------------------
  111. * Allocate a stack whose memory will be marked as Normal-IS-WBWA when
  112. * the MMU is enabled. There is no risk of reading stale stack memory
  113. * after enabling the MMU as only the primary CPU is running at the
  114. * moment.
  115. * ---------------------------------------------------------------------
  116. */
  117. bl plat_set_my_stack //设定堆栈
  118. #if STACK_PROTECTOR_ENABLED
  119. .if \_init_c_runtime
  120. bl update_stack_protector_canary
  121. .endif /* _init_c_runtime */
  122. #endif
  123. .endm
  124. #endif /* __EL3_COMMON_MACROS_S__ */


该函数是需要带参数调用,参数说明如下:

_set_endian:设定大小端

_warm_boot_mailbox:检查当前是属于冷启动还是热启动(power on or reset)

_secondary_cold_boot: 确定当前的CPU是主CPU还是从属CPU

_init_memory:是否需要初始化memory

_init_c_runtime: 是否需要初始化C语言的执行环境

_exception_vectors: 异常向量表地址

1.3 bl1_early_patform_setup

该函数用来完成早期的初始化操作,主要包括memory, page table, 所需外围设备的初始化以及相关状态设定等;

  1. void bl1_early_platform_setup(void)
  2. {
  3. /* 使能看门狗,初始化console,初始化memory */
  4. arm_bl1_early_platform_setup();
  5. /*
  6. * Initialize Interconnect for this cluster during cold boot.
  7. * No need for locks as no other CPU is active.
  8. */
  9. plat_arm_interconnect_init();//初始化外围设备
  10. /*
  11. * Enable Interconnect coherency for the primary CPU's cluster.
  12. */
  13. plat_arm_interconnect_enter_coherency();//使能外围设备
  14. }

1.4 bl_main

该函数完成bl2 image的加载和运行环境的设置,如果开启了trusted boot,则需要对image进行verify操作

  1. void bl1_main(void)
  2. {
  3. unsigned int image_id;
  4. /* Announce our arrival */
  5. NOTICE(FIRMWARE_WELCOME_STR);
  6. NOTICE("BL1: %s\n", version_string);
  7. NOTICE("BL1: %s\n", build_message);
  8. INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE,
  9. (void *)BL1_RAM_LIMIT);
  10. print_errata_status();
  11. #if DEBUG
  12. u_register_t val;
  13. /*
  14. * Ensure that MMU/Caches and coherency are turned on
  15. */
  16. #ifdef AARCH32
  17. val = read_sctlr();
  18. #else
  19. val = read_sctlr_el3();
  20. #endif
  21. assert(val & SCTLR_M_BIT);
  22. assert(val & SCTLR_C_BIT);
  23. assert(val & SCTLR_I_BIT);
  24. /*
  25. * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
  26. * provided platform value
  27. */
  28. val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
  29. /*
  30. * If CWG is zero, then no CWG information is available but we can
  31. * at least check the platform value is less than the architectural
  32. * maximum.
  33. */
  34. if (val != 0)
  35. assert(CACHE_WRITEBACK_GRANULE == SIZE_FROM_LOG2_WORDS(val));
  36. else
  37. assert(CACHE_WRITEBACK_GRANULE <= MAX_CACHE_LINE_SIZE);
  38. #endif
  39. /* Perform remaining generic architectural setup from EL3 */
  40. bl1_arch_setup(); //设置下一个image的EL级别
  41. #if TRUSTED_BOARD_BOOT
  42. /* Initialize authentication module */
  43. auth_mod_init(); //初始化image的验证模块
  44. #endif /* TRUSTED_BOARD_BOOT */
  45. /* Perform platform setup in BL1. */
  46. bl1_platform_setup(); //平台相关设置,主要是IO的设置
  47. /* Get the image id of next image to load and run. */
  48. image_id = bl1_plat_get_next_image_id(); //获取下一个阶段image的ID值。默认返回值为BL2_IMAGE_ID
  49. /*
  50. * We currently interpret any image id other than
  51. * BL2_IMAGE_ID as the start of firmware update.
  52. */
  53. if (image_id == BL2_IMAGE_ID)
  54. bl1_load_bl2(); //将bl2 image加载到安全RAM中
  55. else
  56. NOTICE("BL1-FWU: *******FWU Process Started*******\n");
  57. bl1_prepare_next_image(image_id); //获取bl2 image的描述信息,包括名字,ID,entry potin info等,并将这些信息保存到bl1_cpu_context的上下文中
  58. console_flush();
  59. }

1.5 bl1_prepare_next_image

该函数用来获取bl2 image的描述信息,获取bl2的入口地址,这只下个阶段的CPU上下文,以备执行从bl1跳转到bl2的操作使用

  1. void bl1_prepare_next_image(unsigned int image_id)
  2. {
  3. unsigned int security_state;
  4. image_desc_t *image_desc;
  5. entry_point_info_t *next_bl_ep;
  6. #if CTX_INCLUDE_AARCH32_REGS
  7. /*
  8. * Ensure that the build flag to save AArch32 system registers in CPU
  9. * context is not set for AArch64-only platforms.
  10. */
  11. if (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SHIFT)
  12. & ID_AA64PFR0_ELX_MASK) == 0x1) {
  13. ERROR("EL1 supports AArch64-only. Please set build flag "
  14. "CTX_INCLUDE_AARCH32_REGS = 0");
  15. panic();
  16. }
  17. #endif
  18. /* Get the image descriptor. */
  19. /* 获取bl2 image的描述信息,主要包括入口地址,名字等信息 */
  20. image_desc = bl1_plat_get_image_desc(image_id);
  21. assert(image_desc);
  22. /* Get the entry point info. */
  23. /* 获取image的入口地址信息 */
  24. next_bl_ep = &image_desc->ep_info;
  25. /* Get the image security state. */
  26. /* 获取bl2 image的安全状态(判定该image是属于安全态的image的还是非安全态的image) */
  27. security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
  28. /* Setup the Secure/Non-Secure context if not done already. */
  29. /* 设定用于存放CPU context的变量 */
  30. if (!cm_get_context(security_state))
  31. cm_set_context(&bl1_cpu_context[security_state], security_state);
  32. /* Prepare the SPSR for the next BL image. */
  33. /* 为下个阶段的image准备好SPSR数据 */
  34. if (security_state == SECURE) {
  35. next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
  36. DISABLE_ALL_EXCEPTIONS);
  37. } else {
  38. /* Use EL2 if supported else use EL1. */
  39. if (read_id_aa64pfr0_el1() &
  40. (ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) {
  41. next_bl_ep->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
  42. DISABLE_ALL_EXCEPTIONS);
  43. } else {
  44. next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
  45. DISABLE_ALL_EXCEPTIONS);
  46. }
  47. }
  48. /* Allow platform to make change */
  49. bl1_plat_set_ep_info(image_id, next_bl_ep);
  50. /* Prepare the context for the next BL image. */
  51. /* 使用获取到的bl2 image的entrypoint info数据来初始化cpu context */
  52. cm_init_my_context(next_bl_ep);
  53. /* 为进入到下个EL级别做准备 */
  54. cm_prepare_el3_exit(security_state);
  55. /* Indicate that image is in execution state. */
  56. /* 设定image的执行状态 */
  57. image_desc->state = IMAGE_STATE_EXECUTED;
  58. /* 打印出bl2 image的入口信息 */
  59. print_entry_point_info(next_bl_ep);
  60. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/610058
推荐阅读
相关标签
  

闽ICP备14008679号