ARM的安全启动—ATF TF-A以及它与UEFI的互动_atf runtime spmd ...

打印 上一主题 下一主题

主题 872|帖子 872|积分 2616


泉源:参考资料2
注意蓝色箭头上的数字,它是启动顺序。统统劈头于在EL3的BL1。
BL1:Trusted Boot ROM
启动最早的ROM,它可以类比Boot Guard的ACM,
老狼:什么是Boot Guard?电脑启动中的信任链条解析269 赞同 · 44 评论文章​编辑
不外它是在CPU的ROM里而不是和BIOS在一起,是统统的信任根。它的代码在这里:

代码很简朴(略去不紧张内容):
  1. func bl1_entrypoint
  2.         ....
  3.         bl        bl1_early_platform_setup
  4.         bl        bl1_plat_arch_setup
  5.         ....
  6.         bl        bl1_main
  7.         ....
  8.         b        el3_exit
  9. endfunc bl1_entrypoint
复制代码
bl1_main()开始就是c步调了,那c运行依靠的堆和栈空间在哪里呢?在CPU内部的SRAM里。SRAM一启动就已经可以访问了,bl1_plat_arch_setup()简朴地在其中分别出来一块作为Trusted SRAM给c步调用,而不用像x86在cache里面扣一块出来,简朴了许多。
BL1主要目的是建立Trusted SRAM、exception vector、初始化串口console等等。然后找到并验证BL2(验签CSF头),然后跳过去。
BL2:Trusted Boot Firmware
同样运行在EL3上的BL2和BL1一个明显的不同是它在Flash上,作为外置的一个Firmware,它的可信建立在BL1对它的验证上。它也有完备的源代码:

它也会初始化一些关键安全硬件和软件框架。更主要的是,也是我盼望大家下载NXP 2160A的分支的紧张缘故起因,BL2会初始化许多硬件,而这些硬件初始化在x86中是BIOS完成的(无论是在PEI中还是包在FSP/AGESA中),而在ARM的ATF体系中,许多种CPU是在BL2中完成的。2160A在Plat目录下提供了许多开源的硬件初始化代码,供ATF BL2框架代码调用。比较紧张的是bl2_main()
  1. void bl2_main(void)
  2. {
  3.         ...
  4.         bl2_arch_setup();
  5.         ...
  6.         /* initialize boot source */
  7.         bl2_plat_preload_setup();
  8.         /* Load the subsequent bootloader images. */
  9.         next_bl_ep_info = bl2_load_images();
  10.         ...
  11.         bl2_run_next_image(next_bl_ep_info);
  12. }
复制代码
最紧张的两步都在这个函数中完成:初始化硬件和找到BL31。
bl2_plat_preload_setup()中会初始化一堆硬件,包括读取RCW初始化Serdes等,对内存初始化感兴趣的人(好比我)也可以在里面找到初始化DDR4的代码:dram_init(),它在Plat\nxp\drivers\ddr\nxp-ddr下。比较遗憾的是DDR4 PHY的代码是个Binary,不含源码,这里对DDR4的初始化仅仅聚焦设置timing寄存器和功能寄存器,而没有内存的Training过程。
Anyway,x86带内初始化硬件的许多代码ARM ATF体系都包括在BL2中,而不在UEFI代码中,这是和x86 UEFI代码的一个明显区别。部分缘故起因这些代码都要求是Secure的。更加糟糕的是,许多ARM平台,BL1和BL2,甚至背面的BL31都是以二进制的形式提供,让定制显得很困难。BL2可否提供足够的信息和定制化选择给固件厂商和提供足够信息给UEFI代码,考验BL2的详细设计实现。NXP在两个方面都做的不错,不但提供RCW等配置接口,还开源了大部分代码,十分方便。
BL2在初始化硬件后,开始探求BL3的几个小兄弟:BL31,BL32和BL33。它先找到BL31,并验签它,最后转入BL31。
BL31:EL3 Runtime Firmware
BL31作为EL3最后的安全堡垒,它不像BL1和BL2是一次性运行的。如它的runtime名字暗示的那样,它通过SMC为Non-Secure连续提供设计安全的服务。关于SMC的调用calling convention我们今后再详细介绍,这里只需要知道它的服务主要是通过BL32。它负责找到BL32,验签,并运行BL32。
BL32:OPTee OS + 安全app
BL32实际上是闻名的Open Portable Trusted Execution Enveiroment[5] OS,它是由Linaro创立的。它是个很大的话题,我们今后再细聊。如今仅需要知道OPTee OS运行在 S-EL1,而其上的安全APP运行在S-EL0。OPTee OS运行完毕后,返回EL3的BL31,BL31找到BL33,验签它并运行。
BL33: Non-Trusted Firmware
BL33实际上就是UEFI firmware大概uboot,也有实如今这里直接放上Linux Kernel。2160A的实现是UEFI和uboot都支持。我们仅仅来看UEFI的路径。
第一次看到UEFI居然是Non-Trusted,我是有点伤心的。UEFI运行在NS_EL2,步调的入口点在ARM package
  1. edk2/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S
复制代码
做了一些简朴初始化,就跳到C语言的入口点CEntryPoint( )。其中ArmPlatformInitialize()做了一些硬件初始化,调用了
edk2-platforms/Silicon/NXP/ 的代码。紧张的是PrimaryMain()。
PrimaryMain()有两个实例,2160A NXP选择的是PrePI的版本(edk2/ArmPlatformPkg/PrePi/MainUniCore.c),说明它跳过了SEC的部分,直接进入了PEI的后期阶段,在BL2已经干好了大部分硬件初始化的情况下,这个也是正常选择。PrePI的实例直接调用PrePiMain()(仅保存紧张部分)
  1. VOID
  2. PrePiMain (
  3.   IN  UINTN                     UefiMemoryBase,
  4.   IN  UINTN                     StacksBase,
  5.   IN  UINT64                    StartTimeStamp
  6.   )
  7. {
  8.   ....
  9.   ArchInitialize ();
  10.   SerialPortInitialize ();
  11.   InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
  12.   // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
  13.   Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
  14.   BuildCpuHob (ArmGetPhysicalAddressBits (), PcdGet8 (PcdPrePiCpuIoSize));
  15.   BuildGuidDataHob (&gEfiFirmwarePerformanceGuid, &Performance, sizeof (Performance));
  16.   SetBootMode (ArmPlatformGetBootMode ());
  17.   // Initialize Platform HOBs (CpuHob and FvHob)
  18.   Status = PlatformPeim ();
  19.   ....
  20.   Status = DecompressFirstFv ();
  21.   Status = LoadDxeCoreFromFv (NULL, 0);
  22. }
复制代码
从中我们可以看到,这里险些就是UEFI PEI阶段DXEIPL的阶段了,背面就是直接DXE阶段。
好了,我们来梳理一下,ATF整个信任链条是逐步建立的:

泉源:参考资料2
从作为信任根的BL1开始,一步一步验签CSF头中的签名,最厥后到BL33,背面就是OS了。那BL33背面怎么就断了呢?实在背面的验签就是UEFI Secure Boot了
老狼:趣话安全启动:迷思与启示152 赞同 · 24 评论文章​编辑
结语

ATF的官网一张图包罗了更多的信息:

如果你仅仅对ATF的UEFI启动路径感兴趣,下面这张图大概更加简朴明了:

NXP 2160A的开源和精良的文档,让我们可以在一个详细的平台上切片观察ATF的详细实现,发起大家仔细阅读参考资料2和下载代码来看看。
关于ATF启动这里先整个宏观的概念。
这个blog讲的很好,就不重复写了,自己写还写不到这么清晰,图页很美丽。
原文链接:https://www.cnblogs.com/arnoldlu/p/14175126.html
启动正文

下图分别成不同EL,分别描述BL1、BL2、BL31、BL32、BL33启动流程,以及PSCI、SP处理流程。
1. 冷启动(Cold boot)流程及阶段分别

restart–冷启动
reset–热启动
ATF冷启动实现分为5个步骤:


  • BL1 - AP Trusted ROM,一般为BootRom。
  • BL2 - Trusted Boot Firmware,一般为Trusted Bootloader。
  • BL31 - EL3 Runtime Firmware,一般为SML,管理SMC执行处理和中断,运行在secure monitor中。
  • BL32 - Secure-EL1 Payload,一般为TEE OS Image。
  • BL33 - Non-Trusted Firmware,一般为uboot、linux kernel。
ATF输出BL1、BL2、BL31,提供BL32和BL33接口。
(我想提供的接口就是BL32和BL33的镜像可以是指定的,atf实在是一个启动框架,这其中包罗的五个步骤,每个步骤你想要的内容,可以由厂商自己界说。)
启动流程如下:

1.1 BL1

BL1位于ROM中,在EL3下从reset vector处开始运行。(bootrom就是芯片上电运行的(chip-rom的作用就是跳转到bootrom))
BL1做的工作主要有:


  • 决定启动路径:冷启动还是热启动。
  • 架构初始化:异常向量、CPU复位处理函数配置、控制寄存器设置(SCRLR_EL3/SCR_EL3/CPTR_EL3/DAIF)
  • 平台初始化:使能Trusted Watchdog、初始化控制台、配置硬件一致性互联、配置MMU、初始化相干存储设备。
  • 固件更新处理
  • BL2镜像加载和执行:

    • BL1输出“Booting Trusted Firmware"。
    • BL1加载BL2到SRAM;如果SRAM不敷大概BL2镜像错误,输出“Failed to load BL2 firmware.”。
    • BL1切换到Secure EL1并将执行权交给BL2.

1.2 BL2

BL2位于SRAM中,运行在Secure EL1主要工作有:


  • 架构初始化:EL1/EL0使能浮点单位和ASMID。
  • 平台初始化:控制台初始化、相干存储设备初始化、MMU、相干设备安全配置、
  • SCP_BL2:体系控制核镜像加载,单独核处理体系功耗、时钟、复位等控制。
  • 加载BL31镜像:BL2将控制权交给BL1;BL1关闭MMU并关cache;BL1将控制权交给BL31。
  • 加载BL32镜像:BL32运行在安全世界,BL2依赖BL31将控制权交给BL32。SPSR通过Secure-EL1 Payload Dispatcher进行初始化。
  • 加载BL33镜像:BL2依赖BL31将控制权交给BL33。
1.3 BL31

BL31位于SRAM中,EL3模式。除了做架构初始化和平台初始化外,还做了如下工作:


  • PSCI服务初始化,后续提供CPU功耗管理操作。
  • BL32镜像运行初始化,处于Secure EL1模式。
  • 初始化非安全EL2或EL1,跳转到BL33执行。
  • 负责安全非安全世界切换。
  • 进行安全服务哀求的分发。

这两幅图真的不错,棒。
小结

ATF将体系启动从最底层进行了完备的同一分别,将secure monitor的功能放到了bl31中进行,如许当体系完全启动之后,在CA大概TEE OS中触发了smc大概是其他的中断之后,起首是遍历注册到bl31中的对应的service来判定详细的handle,如许可以对体系所有的关键smc大概是中断操作做同一的管理和分配
在上述启动过程中,每个Image跳转到写一个image的方式各不相同,下面将列出启动过程中每个image跳转到下一个image的过程:
1. bl1跳转到bl2执行

在bl1完成了bl2 image加载到RAM中的操作,中断向量表设定以及其他CPU相干设定之后,在bl1_main函数中解析出bl2 image的描述信息,获取入口地址,并设定下一个阶段的cpu上下文,完成之后,调用el3_exit函数实现bl1到bl2的跳转操作,进入到bl2中执行.
2.bl2跳转到bl31执行

在bl2中将会加载bl31, bl32, bl33的image到对应权限的RAM中,并将该三个image的描述信息组成一个链表保存起来,以备bl31启动bl32和bl33使用在AACH64中,bl31位于EL3 runtime software,运行时的主要功能是管理smc指令的处理和中断的主力,运行在secure monitor状态中
bl32一般为TEE OS image,本章节以OP-TEE为例进行说明
bl33为非安全image,比方uboot, linux kernel等,当前该部分为bootloader部分的image,再由bootloader来启动linux kernel.(以是不会这么久就是为了整个bootloader吧,应该是kernel吧)
从bl2跳转到bl31是通过带入bl31的entry point info调用smc指令触发在bl1中设定的smc异常来通过cpu将全向交给bl31并跳转到bl31中执行。(这个handle是再bl1配置的)
3.bl31跳转到bl32执行

在bl31中会执行runtime_service_inti操作,该函数会调用注册到EL3中所有service的init函数, 其中有一个service就是为TEE服务,该service的init函数会将TEE OS的初始化函数赋值给bl32_init变量,当所有的service执行完init后,在bl31中会调用bl32_init执行的函数来跳转到TEE OS的执行
4.bl31跳转到bl33执行

当TEE_OS image启动完成之后会触发一个ID为TEESMC_OPTEED_RETURN_ENTRY_DONE的smc调用来告知EL3 TEE OS image已经完成了初始化,然后将CPU的状态恢复到bl31_init的位置继承执行。
bl31通过遍历在bl2中记录的image链表来找到需要执行的bl33的image。然后通过获取到bl33 image的镜像信息,设定下一个阶段的CPU上下文,退出el3然后进入到bl33 image的执行
这一步对宏观的步骤有所认识,下一步对每个步骤的细节进行认识。
在上述启动过程中,每个Image跳转到写一个image的方式各不相同,下面将列出启动过程中每个image跳转到下一个image的过程:
1. bl1跳转到bl2执行

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

知者何南

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表