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 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博…...
mysql中in和exists的区别?
大家好,我是锋哥。今天分享关于【mysql中in和exists的区别?】面试题。希望对大家有帮助; mysql中in和exists的区别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中,IN 和 EXISTS 都用于进行子查询,但它…...
oracle 数据导出方案
工作中有遇到需要将oracle 数据库表全部导出,还需要去除表数据中的换行符。 方案 shell 设计 封装函数 1 function con_oracle() 用于连接oracle 2 function send_file() 用于发送文件 3 主程序 使用循环将所有表导出并发送到数据服务器 主程序 程序代码 #!…...
Apache Commons Lang3 和 Commons Net 详解
目录 1. Apache Commons Lang3 1.1 什么是 Apache Commons Lang3? 1.2 主要功能 1.3 示例代码 2. Commons Net 2.1 什么是 Commons Net? 2.2 主要功能 2.3 示例代码 3. 总结 3.1 Apache Commons Lang3 3.2 Commons Net 3.3 使用建议 4. 参考…...
从0开始的操作系统手搓教程33:挂载我们的文件系统
目录 代码实现 添加到初始化上 上电看现象 挂载分区可能是一些朋友不理解的——实际上挂载就是将我们的文件系统封装好了的设备(硬盘啊,SD卡啊,U盘啊等等),挂到我们的默认分区路径下。这样我们就能访问到了ÿ…...
【Linux】36.简单的TCP网络程序
文章目录 1. TCP socket API 详解1.1 socket():打开一个网络通讯端口1.2 bind():绑定一个固定的网络地址和端口号1.3 listen():声明sockfd处于监听状态1.4 accept():接受连接1.5 connect():连接服务器 2. 实现一个TCP网络服务器2.1 Log.hpp - "多级日志系统"2.2 Daem…...
时序分析
1、基本概念介绍 1.1、 建立时间 T(su) 建立时间:setup time,它是指有效的边沿信号到来之前,输入端口数据保持稳定的时间。 1.1.1、 建立时间要求: 建立时间要求指的是 想要寄存器如期的工作,在有效时…...
doris:ClickHouse
Doris JDBC Catalog 支持通过标准 JDBC 接口连接 ClickHouse 数据库。本文档介绍如何配置 ClickHouse 数据库连接。 使用须知 要连接到 ClickHouse 数据库,您需要 ClickHouse 23.x 或更高版本 (低于此版本未经充分测试)。 ClickHouse 数据库的 JDBC 驱动程序&a…...
NLP常见任务专题介绍(1)-关系抽取(Relation Extraction, RE)任务训练模板
📌 关系抽取(Relation Extraction, RE)任务训练示例 本示例展示如何训练一个关系抽取模型,以识别两个实体之间的关系。 1️⃣ 任务描述 目标:从文本中提取两个实体之间的语义关系,例如 “人物 - 组织”、“药物 - 疾病”、“公司 - 创始人” 等。输入:句子 + 标注的实…...
大模型Transformer的MOE架构介绍及方案整理
前言:DeepSeek模型最近引起了NLP领域的极大关注,也让大家进一步对MOE(混合专家网络)架构提起了信心,借此机会整理下MOE的简单知识和对应的大模型。本文的思路是MOE的起源介绍、原理解释、再到现有MOE大模型的整理。 一…...
零基础掌握Linux SCP命令:5分钟实现高效文件传输,小白必看!
引言 “为什么我传个文件到服务器要折腾半小时?” 如果你也曾在Linux系统中为文件传输抓狂,今天这篇保姆级教程就是你的救星!SCP命令——一个基于SSH协议的高效传输工具,只需5分钟,彻底告别FTP客户端和繁琐操作&#…...
分类评价指标
基础概念解释 TP、TN、FP、FN 这里T是True,F是False,P为Positive,N为Negative TP:被模型正确地预测为正样本(原本为正样本,预测为正样本) TN:被模型正确地预测为负样本࿰…...
Python项目-基于Django的在线教育平台开发
1. 项目概述 在线教育平台已成为现代教育的重要组成部分,特别是在后疫情时代,远程学习的需求显著增加。本文将详细介绍如何使用Python的Django框架开发一个功能完善的在线教育平台,包括系统设计、核心功能实现以及部署上线等关键环节。 本项…...
子数组问题——动态规划
个人主页:敲上瘾-CSDN博客 动态规划 基础dp:基础dp——动态规划-CSDN博客多状态dp:多状态dp——动态规划-CSDN博客 目录 一、解题技巧 二、最大子数组和 三、乘积最大子数组 四、最长湍流子数组 五、单词拆分 一、解题技巧 区分子数组&…...
linux设置pem免密登录和密码登录
其实现在chatgpt 上面很多东西问题都可以找到比较好答案了,最近换了一个服务器,记录一下。 如果设置root用户,就直接切换到cd .ssh目录下生成ssh key即可,不需要创建用户创建用户的ssh文件夹了 比如说我要让danny这个用户可以用p…...
什么是Flask
Flask是Python中一个简单、灵活和易用的Web框架,适合初学者使用。它提供了丰富的功能和扩展性,可以帮助开发者快速构建功能完善的Web应用程序。 以下是Python Flask框架的一些特点和功能: Flask 是一个使用 Python 编写的轻量级 WSGI 微 Web…...
Spark(8)配置Hadoop集群环境-使用脚本命令实现集群文件同步
一.hadoop的运行模式 二.scp命令————基本使用 三.scp命令———拓展使用 四.rsync远程同步 五.xsync脚本集群之间的同步 一.hadoop的运行模式 hadoop一共有如下三种运行方式: 1. 本地运行。数据存储在linux本地,测试偶尔用一下。我们上一节课使用…...
【cocos creator】热更新
一、介绍 试了官方的热更新功能,总结一下 主要用于安卓包热更新 参考: Cocos Creator 2.2.2 热更新简易教程 基于cocos creator2.4.x的热更笔记 二、使用软件 1、cocos creator v2.4.10 2、creator热更新插件:热更新manifest生成工具&…...
黑金风格人像静物户外旅拍Lr调色教程,手机滤镜PS+Lightroom预设下载!
调色教程 针对人像、静物以及户外旅拍照片,运用 Lightroom 软件进行风格化调色工作。旨在通过软件中的多种工具,如基本参数调整、HSL(色相、饱和度、明亮度)调整、曲线工具等改变照片原本的色彩、明度、对比度等属性,将…...
部署vue+django项目(初版)
1.准备 vscode 插件Remote SSH,连接远程,打开远程中home文件夹。 镜像和容器的一些常用命令 docker images docker ps 查看所有正在运行的容器 docker ps -a docker rmi -f tk-django-app 删除镜像 docker rm xxx 删除容器 docker start xxxx …...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
MySQL体系架构解析(三):MySQL目录与启动配置全解析
MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录,这个目录下存放着许多可执行文件。与其他系统的可执行文件类似,这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中,用…...
GraphRAG优化新思路-开源的ROGRAG框架
目前的如微软开源的GraphRAG的工作流程都较为复杂,难以孤立地评估各个组件的贡献,传统的检索方法在处理复杂推理任务时可能不够有效,特别是在需要理解实体间关系或多跳知识的情况下。先说结论,看完后感觉这个框架性能上不会比Grap…...
