当前位置: 首页 > news >正文

安全引导功能及ATF的启动过程(五)

安全引导功能及ATF的启动过程(五)

ATF中bl32的启动

bl31中的runtime_svc_init函数会初始化OP-TEE对应的服务,通过调用该服务项的初始化函数来完成OP-TEE的启动。对于OP-TEE的服务项会通过DECLARE_RT_SVC宏在编译时被存放到rt_svc_des段中。该段中的init成员会被初始化成opteed_setup函数,由此开始进入到OP-TEE OS的启动。整个流程如图所示。

在这里插入图片描述

DECLARE_RT_SVC

DECLARE_RT_SVC分为两种类型:

/* Define an OPTEED runtime service descriptor for fast SMC calls */
//对于快速的SMCs中断,OP-TEE操作系统将在入口堆栈上执行,
//   期间屏蔽IRQ/FIQ中断,直至执行返回到正常世界。
DECLARE_RT_SVC(opteed_fast,OEN_TOS_START,OEN_TOS_END,SMC_TYPE_FAST,opteed_setup,opteed_smc_handler
);/* Define an OPTEED runtime service descriptor for yielding SMC calls */
//对于让步型SMCs中断,OPTEE OS将会在
//        某个时刻解除对中断的屏蔽,执行所请求的服务。
DECLARE_RT_SVC(opteed_std,OEN_TOS_START,OEN_TOS_END,SMC_TYPE_YIELD,NULL,opteed_smc_handler
);

opteed_setup函数

该函数是ATF启动OP-TEE的入口函数,该函数会查找到OP-TEE镜像的信息、检查OP-TEE的入口函数指针是否有效、设置OP-TEE运行的上下文,然后调用OP-TEE的入口函数,开始执行OP-TEE的启动。该函数的内容如下:

/root/optee/trusted-firmware-a/services/spd/opteed/opteed_main.c

/******************************************************************************** OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type* (aarch32/aarch64) if not already known and initialises the context for entry* into OPTEE for its initialization.******************************************************************************/static int32_t opteed_setup(void)
{
//延迟加载模式
#if OPTEE_ALLOW_SMC_LOADopteed_allow_load = true;INFO("Delaying OP-TEE setup until we receive an SMC call to load it\n");/** We must register the interrupt handler now so that the interrupt* priorities are not changed after starting the linux kernel.*///预先注册中断处理程序,确保在 Linux 内核启动后,//           中断优先级不会被改变。 register_opteed_interrupt_handler();return 0;
#elseentry_point_info_t *optee_ep_info;uint32_t linear_id;uint64_t arg0;uint64_t arg1;uint64_t arg2;uint64_t arg3;struct transfer_list_header *tl = NULL;struct transfer_list_entry *te = NULL;void *dt = NULL;linear_id = plat_my_core_pos();  //获取当前核心的线性ID/** Get information about the Secure Payload (BL32) image. Its* absence is a critical failure.  TODO: Add support to* conditionally include the SPD service*///SECURE:获取 BL32(即 OP-TEE)的入口信息。// NON_SECURE: 获取 BL33(即 REE)的入口信息。optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE);if (!optee_ep_info) {WARN("No OPTEE provided by BL2 boot loader, Booting device"" without OPTEE initialization. SMC`s destined for OPTEE"" will return SMC_UNK\n");return 1;}/** If there's no valid entry point for SP, we return a non-zero value* signalling failure initializing the service. We bail out without* registering any handlers*///检查入口地址有效//pc 是程序计数器(Program Counter),即 OP-TEE 的入口地址。 if (!optee_ep_info->pc)return 1;//optee_ep_info结构体定义在下方tl = (void *)optee_ep_info->args.arg3;// 解析 Transfer List(可选参数传递机制)//   Transfer List:一种链式结构,允许 BL2 向//   BL31 传递任意类型的数据(FDT、内存表、版本信息等)。if (TRANSFER_LIST && transfer_list_check_header(tl)) {//查找 FDT 条目, Flattened Device Tree(FDT)te = transfer_list_find(tl, TL_TAG_FDT);//提取设备树指针dt = transfer_list_entry_data(te);//获取 OP-TEE 的执行状态(AArch32 或 AArch64)opteed_rw = GET_RW(optee_ep_info->spsr);if (opteed_rw == OPTEE_AARCH64) {if (optee_ep_info->args.arg1 !=TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION))return 1;//64位下为arg0赋值arg0 = (uint64_t)dt;arg2 = 0;} else {if (optee_ep_info->args.arg1 !=TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION))return 1;//32位下为arg1赋值arg0 = 0;arg2 = (uint64_t)dt;}//统一设置其余参数arg1 = optee_ep_info->args.arg1;arg3 = optee_ep_info->args.arg3;} else {/* Default handoff arguments */opteed_rw = optee_ep_info->args.arg0;arg0 = optee_ep_info->args.arg1; /* opteed_pageable_part */arg1 = optee_ep_info->args.arg2; /* opteed_mem_limit */arg2 = optee_ep_info->args.arg3; /* dt_addr */arg3 = 0;}// 初始化 OP-TEE 执行上下文opteed_init_optee_ep_state(optee_ep_info, opteed_rw, optee_ep_info->pc,arg0, arg1, arg2, arg3,&opteed_sp_context[linear_id]);/** All OPTEED initialization done. Now register our init function with* BL31 for deferred invocation*///所有 OPTEED 初始化已完成。// 现在将我们的初始化函数注册到 BL31,以便延迟调用。 bl31_register_bl32_init(&opteed_init);return 0;
#endif  /* OPTEE_ALLOW_SMC_LOAD */
}

entry_point_info_t结构体

定义如下:

/root/optee/trusted-firmware-a/include/export/common/ep_info_exp.h

typedef struct aapcs64_params {uint64_t arg0;uint64_t arg1;uint64_t arg2;uint64_t arg3;uint64_t arg4;uint64_t arg5;uint64_t arg6;uint64_t arg7;
} aapcs64_params_t;typedef struct aapcs32_params {uint32_t arg0;uint32_t arg1;uint32_t arg2;uint32_t arg3;
} aapcs32_params_t;/****************************************************************************** This structure represents the superset of information needed while* switching exception levels. The only two mechanisms to do so are* ERET & SMC. Security state is indicated using bit zero of header* attribute* NOTE: BL1 expects entrypoint followed by spsr at an offset from the start* of this structure defined by the macro `ENTRY_POINT_INFO_PC_OFFSET` while* processing SMC to jump to BL31.*****************************************************************************/
typedef struct entry_point_info {param_header_t h;uintptr_t pc;uint32_t spsr;
#ifdef __aarch64__aapcs64_params_t args;
#elseuintptr_t lr_svc;aapcs32_params_t args;
#endif
} entry_point_info_t;

opteed_init函数

该函数的地址会被赋值给bl32_init变量,在bl31_main函数中会被调用,主要用来完成启动OP-TEE的设置。该函数内容如下:

/root/optee/trusted-firmware-a/services/spd/opteed/opteed_main.c

#if !OPTEE_ALLOW_SMC_LOAD
//只有当 OPTEE_ALLOW_SMC_LOAD 未定义 时,这段代码才被编译进去。
static int32_t opteed_init(void)
{entry_point_info_t *optee_entry_point;/** Get information about the OP-TEE (BL32) image. Its* absence is a critical failure.*///SECURE:获取 BL32(即 OP-TEE)的入口信息。 optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);//完成 上下文恢复 + 跳转到 OP-TEEreturn opteed_init_with_entry_point(optee_entry_point);
}
#endif  /* !OPTEE_ALLOW_SMC_LOAD */

opteed_init_with_entry_point函数

这个函数真正完成 上下文恢复 + 跳转到 OP-TEE 的逻辑。

/root/optee/trusted-firmware-a/services/spd/opteed/opteed_main.c

/******************************************************************************** This function passes control to the OPTEE image (BL32) for the first time* on the primary cpu after a cold boot. It assumes that a valid secure* context has already been created by opteed_setup() which can be directly* used.  It also assumes that a valid non-secure context has been* initialised by PSCI so it does not need to save and restore any* non-secure state. This function performs a synchronous entry into* OPTEE. OPTEE passes control back to this routine through a SMC. This returns* a non-zero value on success and zero on failure.******************************************************************************/
static int32_t
opteed_init_with_entry_point(entry_point_info_t *optee_entry_point)
{//获取当前核心 IDuint32_t linear_id = plat_my_core_pos();//获取当前核心的 OP-TEE 上下文optee_context_t *optee_ctx = &opteed_sp_context[linear_id];uint64_t rc;assert(optee_entry_point);//初始化当前核心的上下文//cm:Context Managementcm_init_my_context(optee_entry_point);/** Arrange for an entry into OPTEE. It will be returned via* OPTEE_ENTRY_DONE case*///执行同步跳转 rc = opteed_synchronous_sp_entry(optee_ctx);//如果返回了 0,说明异常,系统崩溃assert(rc != 0);return rc;
}

上下文管理职责划分:

安全上下文(Secure Context)SPD(如opteed_setup()为 TEE(如 OP-TEE)准备 S-EL1/S-EL0 状态
非安全上下文(Non-secure Context)PSCI 模块为 Normal World(如 Linux)准备 EL1/EL0 状态

ATF启动过程小结

ATF作为最底层固件,OP-TEE OS、BootLoader、Linux内核的加载都是由ATF来完成的,而且ATF实现了安全引导的功能。BL31运行于EL3,待系统启动完成后,在REE侧或TEE侧触发的安全监控模式调用(SMC)都会进入BL31中被处理。OP-TEE启动完成后会返回一个包含用于处理各种类型的安全监控模式调用的函数指针结构体变量,该变量会被添加到BL31的处理句柄中,用于处理REE侧触发的安全监控模式调用。BL2启动时通过触发安全监控模式调用通知BL1将CPU控制权限交给BL31。BL31通过解析特定段中是否存在OP-TEE的入口函数指针来确定是否需要加载OP-TEE。OP-TEE启动后会触发安全监控模式调用重新进入到BL31中继续执行。BL31通过查询链表的方式获取下一个需要被加载的REE侧镜像文件,并设定好REE侧运行时CPU的状态和运行环境,然后退出EL3进入REE侧镜像文件的启动。一般第一个REE侧镜像文件为BootLoader,BootLoader会加载Linux内核。

参考资料:

  • 《手机安全和可信应用开发指南:TrustZone与OP-TEE技术详解》
http://www.lryc.cn/news/616336.html

相关文章:

  • 【GPT入门】第44课 检查 LlamaFactory微调Llama3的效果
  • ThreadLocal有哪些内存泄露问题,如何避免?
  • 商业解决方案技术栈总结
  • 洛谷 P2404 自然数的拆分问题-普及-
  • LeetCode - 搜索插入位置 / 排序链表
  • 音视频学习(五十一):AAC编码器
  • 力扣(买卖股票的最佳时机I/II)
  • 面对信号在时频平面打结,VNCMD分割算法深度解密
  • windows的cmd命令【持续更新】
  • 数据库面试题集
  • ADB简介
  • 全面了解机器语言之kmeans
  • UE5多人MOBA+GAS 41、制作一个飞弹,添加准心索敌
  • 【走进Docker的世界】Docker环境搭建
  • Java集合框架、Collection体系的单列集合
  • OpenStack热迁移一直处于迁移中怎么办
  • Dify 从入门到精通(第 26/100 篇):Dify 的知识图谱集成
  • 基于django的宠物用品购物商城的设计与实现
  • Java基础编程核心案例:从逻辑到应用
  • Python 的列表 list 和元组 tuple 有啥本质区别?啥时候用谁更合适?
  • 嵌入式第二十四课!!linux应用软件编程与文件操作!!!
  • Java开源代码源码研究:我的成长之路与实战心得分享
  • actuary notes[2]
  • 产品经理入门 - 产品解决方案(需求分析、 功能优先级划分、功能价值、用户体验)
  • 智慧社区--4
  • Spring之【详解AOP】
  • Linux入门指南:26个基础命令全解析
  • 数字图像处理3
  • Docker-04:CGroups资源控制组
  • 【代码随想录day 15】 力扣 404. 左叶子之和