ATF加载自定义镜像

news2024/12/31 6:48:14

实际上包含了两个问题:

  1. 如何把自定义的二进制文件打包到fip.bin中?
  2. 如何在secure boot流程中load和认证自定义的二进制文件?

如何打包

证书创建工具和FIP打包工具是通过命令行传参的方式进行证书创建和打包的,如下:

image

由于我们需要打包自定义得image到fip,但是证书创建工具和FIP打包工具预定义的选项中并没有该选项,所以需要修改cert_createfip_tool工具。

准备自定义的image

我直接在ATF的platform.mk中生成了一个测试用的dtb作为image:

FDT_SOURCES += ${PLAT_QEMU_PATH}/test.dts
HW_CONFIG := ${BUILD_PLAT}/fdts/test.dtb

修改cert_create

  1. include/tools_share/tbbr_oid.h​文件中添加自定义的证书拓展域OID,定义如下(需保证与其他OID不同):

    #define USER_IMAGE_HASH_OID                     "1.3.6.1.4.1.4128.2100.1401"
    
  2. tools/cert_create/include/tbbr/tbb_ext.h​添加一行自定义image的证书拓展域枚举类型:

    /* TBBR extensions */
    enum {
    	TRUSTED_FW_NVCOUNTER_EXT,
    	NON_TRUSTED_FW_NVCOUNTER_EXT,
    	TRUSTED_BOOT_FW_HASH_EXT,
    	TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
    .................
    
    	SCP_FWU_CFG_HASH_EXT,
    	AP_FWU_CFG_HASH_EXT,
    	FWU_HASH_EXT,
    	USER_IMAGE_EXT, /* user-defined image ext */
    };
    
  3. 我们想要使用TRUSTED_BOOT_FW_CERT​去认证这个image,所以在tools/cert_create/src/tbbr/tbb_cert.c​文件中TRUSTED_BOOT_FW_CERT​的拓展域添加USER_IMAGE_EXT​枚举类型。

    /*
     * Certificates used in the chain of trust
     *
     * The order of the certificates must follow the enumeration specified in
     * tbb_cert.h. All certificates are self-signed, so the issuer certificate
     * field points to itself.
     */
    static cert_t tbb_certs[] = {
    	[TRUSTED_BOOT_FW_CERT] = {
    		.id = TRUSTED_BOOT_FW_CERT,
    		.opt = "tb-fw-cert",
    		.help_msg = "Trusted Boot FW Certificate (output file)",
    		.fn = NULL,
    		.cn = "Trusted Boot FW Certificate",
    		.key = ROT_KEY,
    		.issuer = TRUSTED_BOOT_FW_CERT,
    		.ext = {
    			TRUSTED_FW_NVCOUNTER_EXT,
    			TRUSTED_BOOT_FW_HASH_EXT,
    			TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
    			HW_CONFIG_HASH_EXT,
    			FW_CONFIG_HASH_EXT,
    			USER_IMAGE_EXT, /* user-defined image ext */
    		},
    		.num_ext = 6 /*modify the size from five to six */
    	},
    
  4. 接着,在tools/cert_create/src/tbbr/tbb_ext.c​中添加该拓展域的内容:

    static ext_t tbb_ext[] = {
    	[TRUSTED_FW_NVCOUNTER_EXT] = {
    		.oid = TRUSTED_FW_NVCOUNTER_OID,
    		.opt = "tfw-nvctr",
    		.help_msg = "Trusted Firmware Non-Volatile counter value",
    		.sn = "TrustedWorldNVCounter",
    		.ln = "Trusted World Non-Volatile counter",
    		.asn1_type = V_ASN1_INTEGER,
    		.type = EXT_TYPE_NVCOUNTER,
    		.attr.nvctr_type = NVCTR_TYPE_TFW
    	},
    ....................
    
    /* new added */
    	[USER_IMAGE_EXT] = {
    		.oid = USER_IMAGE_HASH_OID, /* 自定义的OID */
    		.opt = "user-img", /*这个会生成cert_create的选项 --user-img */
    		.help_msg = "User-defined Image file",
    		.sn = "UserImgHash",
    		.ln = "User-defined image HASH (SHA256)",
    		.asn1_type = V_ASN1_OCTET_STRING,
    		.type = EXT_TYPE_HASH, /* 使用hash校验该image */
    		.optional = 1
    	}
    };
    
    REGISTER_EXTENSIONS(tbb_ext);
    

自此,cert_create可以使用–user-img命令为自定义的image生成hash并将hash值存储在TRUSTED_BOOT_FW_CERT​证书中。

修改fip_tool

image准备好了,证书生成了,该打包进fip了。

  1. 首先在include/tools_share/firmware_image_package.h​添加一个标识该image的唯一的UUID号,该UUID将会在加载认证阶段用于识别该image:

    #define UUID_USER_DEFINED_IMG \
    	{{0x23, 0x6e, 0xd3, 0x30}, {0x4e, 0xdf}, {0x11, 0xef}, 0x8d, 0xd7, {0x00, 0x15, 0x5d, 0xba, 0x59, 0x68} }
    
  2. tools/fiptool/tbbr_config.c​文件中为fip_tool添加一个命令行选项--user-img​。

    toc_entry_t toc_entries[] = {
    	{
    		.name = "Platform Key Certificate",
    		.uuid = UUID_PLAT_KEY_CERT,
    		.cmdline_name = "plat-key-cert"
    	},
    	.................................
        //添加命令
    	{
    		.name = "User-defined Image",
    		.uuid = UUID_USER_DEFINED_IMG,
    		.cmdline_name = "user-img"
    	},
    	{
    		.name = NULL,
    		.uuid = { {0} },
    		.cmdline_name = NULL,
    	}
    };
    

    这里的命令行选项需要和cert_create的保持一致。

  3. 做完以上操作,在使用fip_tool工具时在–user-img后面跟上自定义的image的路径就可以将image打包到fip_tool。

打包image

最后我们在platform.mk中使用一个宏TOOL_ADD_PAYLOAD即可完成:

  1. 将image的hash记录在TRUSTED_BOOT_FW_CERT​证书中,用于后续的验签
  2. 将image打包到fip.bin。

image

如何加载

可以拆解为以下问题:

  1. 从哪里加载?(需要修改IO storage)
  2. 加载到哪里?(定义加载的位置并进行MMU映射)
  3. 如何加载?怎么验签?(修改信任链)

从哪里加载

  1. 首先我们在include/export/common/tbbr/tbbr_img_def_exp.h​定义一个ID唯一标识该image:

    #define PLAT_USER_IMG_ID		U(38)
    
    /* Max Images */
    #define MAX_IMAGE_IDS			U(39)
    
  2. 在平台路径plat/qemu/common/qemu_io_storage.c​中定义自定义image的描述符:

    static const io_uuid_spec_t user_image_uuid_spec = {
    	.uuid = UUID_USER_DEFINED_IMG,
    };
    
  3. 在平台路径plat/qemu/common/qemu_io_storage.c​中的plat_io_policy数组中添加以下内容,表示该image从fip文件中根据UUID进行解析提取。

    static const struct plat_io_policy policies[] = {
    	[FIP_IMAGE_ID] = {
    		&memmap_dev_handle,
    		(uintptr_t)&fip_block_spec,
    		open_memmap
    	},
    .....................
    	[PLAT_USER_IMG_ID] = {
    		&fip_dev_handle,
    		(uintptr_t)&user_image_uuid_spec,
    		open_fip
    	},
    };
    

加载到哪里

  1. 首先需要在plat/qemu/qemu/include/platform_def.h​中定义自定义镜像加载的基地址和边界,我这里定义的是在RAM的其实地址,最大为一个PAGE_SIZE(4KB),毕竟设备树很小。

    #define USER_IMG_BASE			BL_RAM_BASE
    #define USER_IMG_LIMIT			(USER_IMG_BASE + PAGE_SIZE)
    
  2. 我们计划是在BL2阶段load镜像,所以需要在BL2起来之后进行memory map,不然未经过MMU平坦映射的地址是无法访问的。在plat/qemu/common/qemu_bl2_setup.c​中添加以下映射,内存属性为普通memory、可读写、secure。

    #define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
    					bl2_tzram_layout.total_base,	\
    					bl2_tzram_layout.total_size,	\
    					MT_MEMORY | MT_RW | MT_SECURE), \
    				/* new added */ \
    				MAP_REGION_FLAT(			\
    					USER_IMG_BASE,			\
    					USER_IMG_LIMIT			\
    						- USER_IMG_BASE,	\
    					MT_MEMORY | MT_RW | MT_SECURE)
    

如何加载?怎么验签?

  1. 然后需要告诉BL2阶段需要加载这个自定义的image,在plat/qemu/common/qemu_bl2_mem_params_desc.c​的bl2_mem_params_descs​数组中添加如下内容。如此,BL2在load_image时就会解析该数组,根据镜像UUID在fip中查找到该镜像,并将镜像load到指定的镜像基地址进行验证。

    static bl_mem_params_node_t bl2_mem_params_descs[] = {
    	/* Fill BL32 related information */
    	{ .image_id = BL32_IMAGE_ID,
    	  SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
    				entry_point_info_t, BL32_EP_ATTRIBS),
    	  .ep_info.pc = BL32_BASE,
    	  SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
    				image_info_t, BL32_IMG_ATTRIBS),
    	  .image_info.image_base = BL32_BASE,
    	  .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
    
    	  .next_handoff_image_id = BL33_IMAGE_ID,
    	},
    ...................................
    	/* new added */
    	{ .image_id = PLAT_USER_IMG_ID, /* 镜像ID */
    	   SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, VERSION_2,
    				 entry_point_info_t, SECURE | NON_EXECUTABLE),
    	   SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, VERSION_2,
    				 image_info_t, 0),
    	   .image_info.image_base = USER_IMG_BASE, /* 加载的基地址 */
    	   .image_info.image_max_size = USER_IMG_LIMIT - USER_IMG_BASE, /*镜像最大size*/
    	   .next_handoff_image_id = INVALID_IMAGE_ID,
    	},
    };
    
  2. 然后还需要修改COT(chain of trust),否则BL2不知道如何验证该镜像的完整性。在drivers/auth/tbbr/tbbr_cot_common.c​中添加如下内容,表明TRUSTED_BOOT_FW_CERT_ID​证书的拓展域存储了自定义image的hash值。

    line 32: static unsigned char user_img_hash_buf[HASH_DER_LEN];
    line 56: auth_param_type_desc_t user_img_hash = AUTH_PARAM_TYPE_DESC(
    	AUTH_PARAM_HASH, USER_IMAGE_HASH_OID);
    
    * trusted_boot_fw_cert */
    line 63: const auth_img_desc_t trusted_boot_fw_cert = {
    	.img_id = TRUSTED_BOOT_FW_CERT_ID,
    	.img_type = IMG_CERT,
    	.parent = NULL,
    	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
    	 .................
    	},
    	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
    		[0] = {
    			.type_desc = &tb_fw_hash,
    			.data = {
    				.ptr = (void *)tb_fw_hash_buf,
    				.len = (unsigned int)HASH_DER_LEN
    			}
    		},
    		................................
    		/* new added */
    		[4] = {
    			.type_desc = &user_img_hash, /* hash 校验 */
    			.data = {
    				.ptr = (void *)user_img_hash_buf, /* 证书拓展域的hash buffer */
    				.len = (unsigned int)HASH_DER_LEN
    			}
    		},
    	}
    };
    
  3. 还需要在drivers/auth/tbbr/tbbr_cot_common.c​文件中增加一个需要认证的节点的描述结构:

    const auth_img_desc_t user_img = {
    	.img_id = PLAT_USER_IMG_ID,
    	.img_type = IMG_RAW,
    	.parent = &trusted_boot_fw_cert, /* 指定它需要由trusted_boot_fw_cert认证*/
    	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
    		[0] = {
    			.type = AUTH_METHOD_HASH, /* 认证方法为hash */
    			.param.hash = {
    				.data = &raw_data,
    				.hash = &user_img_hash
    			}
    		}
    	}
    };
    
  4. 最后将该结构加入到COT当中。在文件drivers/auth/tbbr/tbbr_cot_bl2.c​增加。这样,在验证该image时,BL2就可以根据COT找到认证该image所需的父节点和方法。

    static const auth_img_desc_t * const cot_desc[] = {
    	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
    	[HW_CONFIG_ID]				=	&hw_config,
    	[TRUSTED_KEY_CERT_ID]			=	&trusted_key_cert,
    	[SCP_FW_KEY_CERT_ID]			=	&scp_fw_key_cert,
    	[SCP_FW_CONTENT_CERT_ID]		=	&scp_fw_content_cert,
    
    	.................................
    	[PLAT_USER_IMG_ID]			=	&user_img, //new added
    };
    

Demo

从启动过程中log可以看出:BL2在加载ID为38的镜像(即我们添加的自定义镜像PLAT_USER_IMG_ID​)时,去加载了ID=6的TRUSTED_BOOT_FW_CERT​证书对齐进行认证,认证成功后才开始去解析该image。

image

文档提供完整patch资源,在ATF2.9.0的qemu平台的代码上实现了将一个自定义的dtb打包到fip中,并且在BL2阶段对该dtb进行加载和验证。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1971999.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图新地球-新图源来一波(地表覆盖物、地表水、岩土圈)

0.序 以前的GlobalLand30图源不可访问了,很多需要地物分类的朋友很苦恼。 现在星图新上了一批图源,不仅包括地物分类、水域、还包括土壤酸碱度、有机碳、粘土、阳离子等各种岩土相关的地图服务。 这边全部配置成了图新地球可以直接加载的图源&#xff…

人生总会有自认为迈不过去的坎【西藏旅记1】

人生总会有自认为迈不过去的坎 孤独,也是人生一态。 有两个人说过我这样的性格,不会有真正的朋友,一个是旅行时的领队,另一个也是旅行时的领队。 以他们的视角,形形色色的人,应接不暇的景,他们修…

Github 2024-08-01 开源项目日报Top10

根据Github Trendings的统计,今日(2024-08-01统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量非开发语言项目3Go项目2Python项目2C项目1C#项目1Rust项目1TypeScript项目1编程面试大学:成为软件工程师的全面学习计划 创建周期:2859 天协议…

如何基于欧拉系统完成本地软件仓库安装

挂载 [rootlocalhost ~]# mount /dev/sr0/openeuler/ 查看一下 在脚本里添加以下两行 [rootlocalhost ~]# vim /etc/rc.d/rc.local 给一个可执行权限,并重启 [rootlocalhost ~]# chmod x /etc/rc.d/rc.local [rootlocalhost ~]# reboot 记住挂载点 切换到 /et…

CANoe系统变量模块里定义的结构体类型和变量从CAPL代码角度理解

CAPL里声明一个结构体类型: variables {struct DoIPMessage{byte version;byte inVersion;word type;dword length;byte payload[1500];};struct DoIPMessage doipMessage; }声明一个结构体类型DoIPMessage,定义了一个此结构体…

【C语言】C语言期末突击/考研--指针(一篇就够)

目录 一、指针的本质(间接访问原理) 1.1.指针的定义 1.2.取地址操作符与取值操作符,指针本质 二、指针的传递使用场景 2.1.什么是指针的传递 2.2.指针的传递使用场景 三、指针的偏移使用场景 3.1.指针的偏移 3.2.指针与一维数组 四…

风景视频素材高清无水印的网站有哪些?6个热门素材网站分享

高清无水印风景视频素材网站推荐,让您的视频内容独树一帜! 对于视频创作者来说,一段引人入胜的风景视频素材往往能够瞬间抓住观众的注意力,仿佛将他们带入了一个全新的世界。然而,很多创作者在实际拍摄过程中会面临时…

(二)springboot2.7.6集成activit5.23.0之集成设计器

引入官方流程设计器 1. activiti-webapp-explorer2-5.23.0.war项目并解压。 2.将文件夹diagram-viewer和editor-app以及modeler.html拷贝到项目resources/static目录下: 顺便说一下: 在Spring Boot中,静态资源的访问顺序是先找static&#…

QT 安装指南

简介 Qt 是一个跨平台的应用程序开发框架,被广泛应用于桌面、移动设备和嵌入式系统等领域。本文将详细介绍如何在 Windows 操作系统上安装 Qt 5.14.2 版本(这个版本较为稳定适用)。 安装前准备 操作系统: 确保您的计算机运行的是 Windows 10 或更高版本。硬件要求…

【数据结构初阶】二叉树与堆(一)

文章目录 一、树的基础概念1、节点与度数2、树的度与高度3、引入:数组下标为何从0开始4、祖先节点5、树是递归定义的6、树与非树的区别7、代码表示 二、二叉树2.1、满二叉树2.2、完全二叉树2.3、完全二叉树的存储 三、堆 一、树的基础概念 1、节点与度数 节点分为…

app逆向实战之定位关键代码

前言 在保证App能够正常使用的前提下,我们可以通过抓包查看是否存在抓包检测。如果可以进行抓包,我们首先进行登录代码定位,并伪造请求进行登录,然后实现App中的某个功能。本文以某嘟牛app为例,抓包结果如下&#xff…

【投标】运维服务方案(2024Word完整版)

1.项目情况 2.服务简述 2.1服务内容 2.2服务方式 2.3服务要求 2.4服务流程 2.5工作流程 2.6业务关系 2.7培训 3.资源提供 3.1项目组成员 3.2服务保障 软件资料清单列表部分文档: 工作安排任务书,可行性分析报告,立项申请审批表&a…

vue后台管理系统 vue3+vite+pinia+elementui+axios下

这篇文章来完成用户组件 也就是增删改查表格 用户页面信息页面由头部&#xff0c;表格,和弹框组成 <template><div class"user-header"><el-button type"primary" click"handleAdd">新增</el-button><el-form :inl…

(2024,LlamaGen,Llama,自回归下一token预测,模型扩展)自回归模型优于扩散:Llama 用于可扩展图像生成

Autoregressive Model Beats Diffusion: Llama for Scalable Image Generation 目录 0. 摘要 1. 引言 2. 自回归模型在图像生成中的应用 2.1 概述 2.2 图像 tokenizer 2.3 自回归模型生成图像 2.4 规模扩展 2.5 服务 3. 实验 5. 结论 0. 摘要 我们介绍 LlamaGen&…

使用mid360从0开始搭建实物机器人入门级导航系统,基于Fast_Lio,Move_Base

Introduction 本文原本只是自己在拿到mid360后&#xff0c;开始进行开发过程的一些问题和学习的记录。毕竟实物和仿真还是有很多不同&#xff0c;且由于碰到的问题也比较多&#xff0c;READEME也越来越详细&#xff0c;所以就干脆整合起来&#xff0c;做成了一篇使用mid360的搭…

嵌入式初学-C语言-十一

#接嵌入式初学-C语言-十,以及部分例题# 循环结构 break和continue break 功能&#xff1a; 1. 用在switch中&#xff0c;用来跳出switch的case语句&#xff1b;如果case没有break&#xff0c;可能会产生case穿透。 2. 用在循环中&#xff08;while、do..while、for..&#…

Linux压缩/解压缩工具:tar命令详解

目录 一、概述 二、基本概念 三、tar命令的基本语法 1、基本语法 2、常用选项 3、帮助获取 四、用法和示例 1. 创建归档文件 &#xff08;1&#xff09;用法 &#xff08;2&#xff09;示例 2. 解压缩归档文件 &#xff08;1&#xff09;用法 &#xff08;2&#…

经典非比较排序—计数排序的Java实现方式

目录 1.具体思路&#xff1a; 2.代码实现&#xff1a; 3.代码分析 4.示例测试&#xff1a; 测试源码&#xff1a; 测试结果&#xff1a; 计数排序&#xff0c;又被称为鸽巢原理&#xff0c;属于桶排序的一种&#xff0c;其本质是通过哈希映射思想&#xff0c;设定计数数组输入以…

音视频入门基础:WAV专题(5)——FFmpeg源码中解码WAV Header的实现

音视频入门基础&#xff1a;WAV专题系列文章&#xff1a; 音视频入门基础&#xff1a;WAV专题&#xff08;1&#xff09;——使用FFmpeg命令生成WAV音频文件 音视频入门基础&#xff1a;WAV专题&#xff08;2&#xff09;——WAV格式简介 音视频入门基础&#xff1a;WAV专题…

论文翻译:Large Language Models in Education: Vision and Opportunities

Large Language Models in Education: Vision and Opportunities 文章目录 教育中的大型语言模型&#xff1a;愿景与机遇摘要1 引言2. 教育与LLMsA. 教育背景B. LLMs背景C. 智能教育D. 教育中的LLMs 3. EduLLMs的关键技术4. LLM赋能教育A. LLMs在教育中的应用B. LLMs下教育的特…