Xilinx ZYNQ FSBL解读:LoadBootImage()
篇首
最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博主准备以FSBL为例,与大家深入探讨一番,从而加深对ZYNQ的加载过程的理解,以便大家作出更精彩的设计!
LoadBootImage() 解读
本文以Zynq7000 FSBL工程代码为基础,分析启动流程核心函数 L o a d B o o t I m a g e ( ) LoadBootImage() LoadBootImage()的执行逻辑与关键技术细节。
一、函数调用框架
int LoadBootImage(void) {FsblHookBeforeBitstreamDdr(); // 钩子函数Status = XFsbl_LoadPartitions(...); // 核心加载FsblHookBeforeHandoff(); // 移交前预处理return Status;
}
二、 函数执行全流程分解
** 函数入口与预处理**
int LoadBootImage(void) {u32 Status = XFSBL_SUCCESS;XTime tStart, tEnd; // 64位计时器(若启用性能分析)
- 硬件依赖:
- 依赖
psu_init.c完成的PS端基础初始化(时钟、MIO、SLCR锁等) - DDR物理层已通过
Xil_DDRInit()完成训练(psu_ddr_phyinit.c)
- 依赖
** F s b l H o o k B e f o r e B i t s t r e a m D d r ( ) FsblHookBeforeBitstreamDdr() FsblHookBeforeBitstreamDdr() 钩子函数**
#ifdef FSBL_PERFXTime_GetTime(&tStart); // 记录TSC起始值(AXI Timer 0)
#endif
/* 用户自定义扩展点:可插入DDR重配置代码 */
- 关键寄存器操作:
- DDRC控制:通过
Xil_Out32(0xFD070000, 0x00040010)设置DDRC_ADDRMAP0调整地址映射 - OCM重映射:关闭OCM缓存(
SLCR.OCM_CFG寄存器位3置1)
- DDRC控制:通过
X F s b l L o a d P a r t i t i o n s ( ) XFsbl_LoadPartitions() XFsblLoadPartitions() 核心加载
阶段1:Boot Header解析
XFsblPs_BootHdr Header;
XFsbl_CheckBootHeader(ImageAddr, &Header); // 从QSPI/NAND读取头部
- 头部结构体(
xfsbl_ps_boothdr.h):typedef struct {u32 ImageID; // 魔数0xAA995566u32 NumPartitions; // 分区总数(含PL比特流+应用)u32 AuthType; // 加密类型:0=None, 1=RSA-2048u32 Checksum; // 头部的CRC32校验// ... 其他字段(分区表偏移、证书偏移等) } XFsblPs_BootHdr;
阶段2:安全认证(以RSA-2048为例)
XSecure_Sha3Init(&Sha3Instance); // 初始化SHA-3引擎
XSecure_Sha3Update(&Sha3Instance, (u8*)ImageAddr, Header.HashLength);
XSecure_Sha3Final(&Sha3Instance, CalculatedHash); // 计算哈希
XSecure_VerifySignature(CalculatedHash, StoredSignature); // RSA验签
- 硬件加速:
- 使用PS内置的CSU模块(Crypto Subsystem)
- RSA密钥存储在eFUSE或BBRAM中(通过
XSecure_GetEfuseKek()读取)
阶段3:分区加载循环
for (u8 i=0; i<Header.NumPartitions; i++) {XFsblPs_PartitionHdr PartHdr;XFsbl_ReadPartitionHdr(ImageAddr + Offset, &PartHdr);if (PartHdr.Attr & PART_ATTR_PL) { // PL比特流分区XFsbl_LoadPlBitstream(PartHdr.LoadAddr, PartHdr.Size);} else { // PS应用程序分区XFsbl_LoadElf(PartHdr.LoadAddr, PartHdr.Size); // ELF解析}
}
- 关键操作细节:
- PL加载:通过DevCfg接口(
XDcfg_CfgInitialize())写入PCAP - ELF加载:解析Program Headers,使用
Xil_Out32()逐段写入DDR - 地址对齐:通过
XLAT_FSBL_TABLE处理非32位对齐访问(触发Data Abort时自动转换)
- PL加载:通过DevCfg接口(
F s b l H o o k B e f o r e H a n d o f f ( ) FsblHookBeforeHandoff() FsblHookBeforeHandoff() 移交前处理
Xil_DCacheFlush(); // 数据缓存刷新(确保DDR数据一致性)
Xil_Out32(CRL_APB_BASE + 0x24, 0x01000F00); // 配置时钟分频
- 寄存器详解:
- CRL_APB (0xFF5E0024): 设置
RPLL_CTRL分频系数(CPU=1.3GHz, DDR=1066MHz) - SLCR_UNLOCK (0xF8000008): 写入
0xDF0D解锁保护寄存器
- CRL_APB (0xFF5E0024): 设置
三、关键子函数解析
-
F s b l H o o k B e f o r e B i t s t r e a m D d r ( ) FsblHookBeforeBitstreamDdr() FsblHookBeforeBitstreamDdr()
- 作用:DDR初始化前的预处理钩子
- 执行内容:
#ifdef FSBL_PERF XTime_GetTime(&tStart); // 性能计数器启动 #endif
-
X F s b l L o a d P a r t i t i o n s ( ) XFsbl_LoadPartitions() XFsblLoadPartitions()
- 流程分解:
- X F s b l C h e c k B o o t H e a d e r ( ) XFsbl_CheckBootHeader() XFsblCheckBootHeader()
验证BIN文件头结构(含 s i z e o f ( X F s b l P s B o o t H d r ) sizeof(XFsblPs_BootHdr) sizeof(XFsblPsBootHdr)) - X F s b l A u t h e n t i c a t i o n ( ) XFsbl_Authentication() XFsblAuthentication()
执行RSA-2048签名验证(通过 X S e c u r e S h a 3 I n i t ( ) XSecure_Sha3Init() XSecureSha3Init()等加密API) - 分区加载循环
遍历分区表加载:for(u8 PartNum=0; PartNum<Header.NumPartitions; PartNum++){XFsbl_LoadPartition(...); // 加载单个分区#ifdef FSBL_DEBUGxil_printf("Partition %d Loaded\r\n", PartNum);#endif }
- X F s b l C h e c k B o o t H e a d e r ( ) XFsbl_CheckBootHeader() XFsblCheckBootHeader()
- 流程分解:
-
F s b l H o o k B e f o r e H a n d o f f ( ) FsblHookBeforeHandoff() FsblHookBeforeHandoff()
- 执行DDR刷新操作( X i l D C a c h e F l u s h ( ) Xil_DCacheFlush() XilDCacheFlush())
- 配置时钟分频器(通过 X i l O u t 32 ( ) Xil_Out32() XilOut32()写CRL_APB寄存器)
四、核心宏定义
- $FSBL_DEBUG
控制调试输出(默认关闭) - KaTeX parse error: Double subscript at position 15: XPAR_PSU_DDR_0_̲S_AXI_BASEADDR
DDR控制器基地址宏(值 0 x 00100000 0x00100000 0x00100000) - X L A T F S B L T A B L E XLAT_FSBL_TABLE XLATFSBLTABLE
地址转换表(处理非对齐访问)
五、执行流程图
初始化硬件 → 验证头部 ↓ ↓ DDR预处理 → 加载分区 ↘ ↓ 移交控制权 \begin{array}{ccc} \text{初始化硬件} & \rightarrow & \text{验证头部} \\ \downarrow & & \downarrow \\ \text{DDR预处理} & \rightarrow & \text{加载分区} \\ & \searrow & \downarrow \\ & & \text{移交控制权} \end{array} 初始化硬件↓DDR预处理→→↘验证头部↓加载分区↓移交控制权
六、 关键数据流与硬件交互
数据加载路径
QSPI Flash → AXI Quad-SPI控制器 OCM缓存 → DMA DDR3 \text{QSPI Flash} \xrightarrow{\text{AXI Quad-SPI控制器}} \text{OCM缓存} \xrightarrow{\text{DMA}} \text{DDR3} QSPI FlashAXI Quad-SPI控制器OCM缓存DMADDR3
- 性能优化:
- 启用DMA传输(
XQspiPs_DmaTransfer()) - 使用线性突发模式(QSPI配置为DDR模式,时钟速率83MHz)
- 启用DMA传输(
安全认证流程
原始镜像 → SHA-3/384 哈希值 哈希值 → RSA-2048签名 验签结果 \begin{aligned} &\text{原始镜像} \xrightarrow{\text{SHA-3/384}} \text{哈希值} \\ &\text{哈希值} \xrightarrow{\text{RSA-2048签名}} \text{验签结果} \end{aligned} 原始镜像SHA-3/384哈希值哈希值RSA-2048签名验签结果
- 抗攻击设计:
- 哈希计算前会清空CSU的密钥缓存(
XSecure_CsuAesKcvClear()) - 签名失败触发安全锁定(通过
XSecure_SetTamperConfig())
- 哈希计算前会清空CSU的密钥缓存(
七、调试与错误处理
调试宏启用
#define FSBL_DEBUG // 启用调试输出
- 典型输出:
XFsbl_Debug: Partition 0 Loaded at 0x00100000 (Size 1MB) XFsbl_Debug: PL Bitstream CRC Check Passed
** 错误码定义**
#define XFSBL_ERROR_BOOTHEADER 0x1000 // 头部校验失败
#define XFSBL_ERROR_AUTHFAIL 0x1001 // RSA验签错误
#define XFSBL_ERROR_PLLLOCK 0x1002 // 时钟锁相环失锁
- 错误处理:
- 记录错误到PMU全局状态寄存器(
XFsbl_WriteReg(PMU_GLOBAL_GLOB_GEN_STORAGE, errCode)) - 触发系统复位(
XFsbl_FallbackReset())
- 记录错误到PMU全局状态寄存器(
**八、 总结 **
L o a d B o o t I m a g e ( ) LoadBootImage() LoadBootImage()作为Zynq7000启动链的核心,其执行涵盖硬件初始化、安全认证、多阶段加载三大模块。函数首先通过 F s b l H o o k B e f o r e B i t s t r e a m D d r ( ) FsblHookBeforeBitstreamDdr() FsblHookBeforeBitstreamDdr()完成DDR时序微调与性能监控启动,随后 X F s b l L o a d P a r t i t i o n s ( ) XFsbl_LoadPartitions() XFsblLoadPartitions()深度解析Boot Header结构,利用CSU硬件模块实现RSA-2048/SHA-3安全认证,并依据分区属性(PL比特流或PS应用)选择PCAP配置或ELF加载机制。关键点包括:通过DevCfg接口的PL动态重配置、基于XLAT表的非对齐地址访问补偿、以及DMA加速的QSPI数据传输。移交控制权前,函数会强制刷新数据缓存(确保内存一致性)并通过CRL_APB寄存器组重配时钟域。调试方面,FSBL_DEBUG宏可实时输出分区加载状态,而错误处理机制将异常状态固化至PMU寄存器,为后续故障分析提供关键日志。该函数的设计充分体现了Zynq架构中PS-PL协同、硬件安全加速、以及多级启动链的技术特点。
注:具体实现细节需参考对应版本的 f s b l _ h o o k s . c fsbl\_hooks.c fsbl_hooks.c和 x f s b l _ p a r t i t i o n l o a d . c xfsbl\_partition_load.c xfsbl_partitionload.c源码文件。
相关文章:
Xilinx ZYNQ FSBL解读:LoadBootImage()
篇首 最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博…...
flutter的HTTP headers用法介绍
flutter的HTTP headers用法介绍 在 Flutter 中,HTTP headers 是用于在发送 HTTP 请求时传递额外信息的关键部分。它们可以用于身份验证、缓存控制、内容类型声明等。以下是关于 Flutter 中 HTTP headers 的详细说明和用法。 1. 什么是 HTTP Headers? H…...
Flutter开发避坑指南:高频问题排查与性能调优实战
目录 一、使用中常见问题 1.环境与配置问题 2.Widget 重建与状态管理 3.布局与绘制问题 4.动画与卡顿(Jank)问题 5.平台相关问题 二、Flutter实战14问 1.如何使用 Flutter 进行多语言支持? 1. 添加依赖 2. 配置 Material App 3. 创…...
Uniapp实现地图获取定位功能
摘要:本文将手把手教你如何在Uniapp项目中集成地图功能、实现定位获取,并解决微信小程序、APP、H5三端的兼容性问题🚀🚀🚀 一、环境准备 地图平台选择 微信小程序:腾讯地图(强制使用)…...
Ubuntu 24.04 安装与配置 JetBrains Toolbox 指南
📌 1. JetBrains Toolbox 介绍 JetBrains Toolbox 是 JetBrains 开发的工具管理器,可用于安装、更新和管理 IntelliJ IDEA、PyCharm、WebStorm、CLion 等。本指南记录了 JetBrains Toolbox 在 Ubuntu 24.04 上的 安装、路径调整、权限管理 及 遇到的问题…...
【AI】神经网络|机器学习——图解Transformer(完整版)
Transformer是一种基于注意力机制的序列模型,最初由Google的研究团队提出并应用于机器翻译任务。与传统的循环神经网络(RNN)和卷积神经网络(CNN)不同,Transformer仅使用自注意力机制(self-attention)来处理输入序列和输出序列,因此可以并行计算,极大地提高了计算效率…...
【VUE2】第二期——生命周期及工程化
目录 1 生命周期 1.1 介绍 1.2 钩子 2 可视化图表库 3 脚手架Vue CLI 3.1 使用步骤 3.2 项目目录介绍 3.3 main.js入口文件代码介绍 4 组件化开发 4.1 组件 4.2 普通组件注册 4.2.1 局部注册 4.2.2 全局注册 1 生命周期 1.1 介绍 Vue生命周期:就是…...
贪心算法三
> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解什么是贪心算法,并且掌握贪心算法。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! >…...
猫耳大型活动提效——组件低代码化
1. 引言 猫耳前端在开发活动的过程中,经历过传统的 pro code 阶段,即活动页面完全由前端开发编码实现,直到 2020 年接入公司内部的低代码活动平台,满足了大部分日常活动的需求,运营可自主配置活动并上线,释…...
机器学习 Day02,matplotlib库绘图
1.matplotlib图像结构 容器层:画板,画布,坐标系辅助层:刻度,标题,网格,图例等图像层:折线图(主讲),饼图,直方图,柱状图等…...
MySQL中有哪几种锁?
大家好,我是锋哥。今天分享关于【MySQL中有哪几种锁?】面试题。希望对大家有帮助; MySQL中有哪几种锁? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中,锁是用于确保数据的一致性和并发控制的机…...
Unity单例模式更新金币数据
单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在游戏开发中,单例模式非常适合用于管理全局唯一的数据,比如玩家的金币数量。通过使用单例…...
【javaEE】多线程(进阶)
1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…...
python从入门到精通(二十四):python爬虫实现登录功能
这里写目录标题 requests实现登录功能selenium实现登录功能 requests实现登录功能 使用 requests 库结合会话(Session)来尝试登录。不过豆瓣有反爬虫机制,这种方式可能会受到验证码等因素的限制 import requests import re# 豆瓣登录页面 l…...
Flask Jinja语法总结篇
目录 1️⃣ 变量(Variables) 2️⃣ 条件语句(if 语句) 3️⃣ 循环(for 语句) 4️⃣ 过滤器(Filters) 5️⃣ 宏(Macros,类似于函数) 6️⃣ 模板继承(Template Inheritance) 7️⃣ 包含模板(Include) 8️⃣ Flask 结合 Jinja 总结 Jinja 是 Flask 默认使…...
Vue3实战学习(Element-Plus常用组件的使用(输入框、下拉框、单选框多选框、el-image图片))(上)(5)
目录 一、Vue3工程环境配置、项目基础脚手架搭建、Vue3基础语法、Vue3集成Element-Plus的详细教程。(博客链接如下) 二、Element-Plus常用组件使用。 (1)el-input。(input输入框) <1>正常状态的el-input。 <2>el-input的disable状态。 <3…...
C++ 链表List使用与实现:拷贝交换与高效迭代器细致讲解
目录 list的使用: 构造与赋值 元素访问 修改操作 容量查询 链表特有操作 拼接(Splice) C11 新增方法 注意: stl_list的模拟实现: 一、链表节点设计的艺术 1.1 结构体 vs 类的选择 二、迭代器实现的精髓 2…...
安当TDE透明加密技术:为Manus大模型构建用户会话数据保护的“安全金库”
摘要 在人工智能技术深度落地的今天,大模型开发者面临的核心挑战已从算法优化转向数据安全。作为垂直领域大模型的代表,Manus凭借其强大的语义理解与个性化交互能力,在金融、医疗、教育等行业获得广泛应用。然而,其海量的用户会话…...
知乎后台管理系统:数据库系统原理实验1——数据库基础概念
实验背景 通过练习绘制语义网络,加深对于基本概念之间关系的理解和掌握。掌握在VISIO中绘制能准确表达基本概念之间关系的语义网络的技能。了解并比较数据模型的Chen’s表示法和UML表示法。理解关系模型设计中的完整性约束的重要性。掌握在Linux操作系统下远程访问…...
docker compose 以redis为例
常见docker compose 命令 》》注意这个是旧版本的,新版本 docker 与compose 之间没有 - 新版本的 docker compose 把 version 取消了 ,redis 默认是没有配置文件的 ,nginx,mysql 默认是有的 services:redis:image: redis:lat…...
ES C++客户端安装及使用
1. ES 介绍 Elasticsearch , 简称 ES ,它是个开源分布式搜索引擎,它的特点有:分布式,零配 置,自动发现,索引自动分片,索引副本机制, restful 风格接口,多…...
【软件工程】一篇入门UML建模图(状态图、活动图、构件图、部署图)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀软件开发必练内功_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…...
应急响应--流量分析
(一)Cobalt Strike流量特征分析 1.HTTP特征 源码特征: 在流量中,通过http协议的url路径,在checksum8解密算法计算后,32位的后门得到的结果是92,64位的后门得到的结果是93,该特征符…...
name ‘bare_metal_version‘ is not mamba_ssm安装
目录 解决方法: 测试ok: mamba_ssm安装报错,windows 安装时, pip install mamba_ssm name bare_metal_version is not defined mamba代码地址: https://github.com/state-spaces/mamba/tree/main 解决方法&…...
自然语言处理:高斯混合模型
介绍 大家好,博主又来给大家分享知识了,今天给大家分享的内容是自然语言处理中的高斯混合模型。 在自然语言处理这个充满挑战与机遇的领域,我们常常面临海量且复杂的文本数据。如何从这些数据中挖掘出有价值的信息,对文本进行有…...
【C++指南】一文总结C++类和对象【中】
🌟 各位看官好,我是egoist2023! 🌍 种一棵树最好是十年前,其次是现在! 🚀 今天来学习C类和对象的语法知识。注意:在本章节中,小编会以Date类举例 👍 如果觉得…...
再聊 Flutter Riverpod ,注解模式下的 Riverpod 有什么特别之处,还有发展方向
三年前我们通过 《Flutter Riverpod 全面深入解析》 深入理解了 riverpod 的内部实现,而时隔三年之后,如今Riverpod 的主流模式已经是注解,那今天就让我们来聊聊 riverpod 的注解有什么特殊之处。 前言 在此之前,我们需要先回忆…...
Go语言集成DeepSeek API和GoFly框架文本编辑器实现流式输出和对话(GoFly快速开发框架)
说明 本文是GoFly快速开发框架集成Go语言调用 DeepSeek API 插件,实现流式输出和对话功能。为了方便实现更多业务功能我们在Go服务端调用AI即DeepSeek接口,处理好业务后再用Gin框架实现流失流式输出到前端,前端使用fetch请求接收到流式的mar…...
docker不停机部署
背景 最近做大疆项目时,后台更新部署时,机场和无人机就会掉线。设备自动重连注册时间比较长,应用长时间不可用。所以需要灰色发布服务。docker-compose的swarm模式可解决此问题。 服务构建脚本Dockerfile # 使用官方Java基础镜像ÿ…...
ZLG嵌入式笔记 | ZLG核心板散热设计指引
在嵌入式系统设计中,散热是影响处理器性能与稳定性的关键问题。本文聚焦于高端嵌入式处理器的散热设计,探讨核心板的热设计与系统级热设计方法,以及导热材料和布局的建议,为解决高温问题提供参考。 用高端嵌入式处理器设计系统&am…...
