文章目录
前言
在 U-Boot 引导程序中,“安全模式”(Secure Boot)和"非安全模式"(Non-Secure Boot)是两种不同的启动模式,它们主要涉及系统启动的安全性和可信度。
安全模式(Secure Boot)
启动过程:在安全模式下,U-Boot 会对启动过程进行验证。它通常会验证引导加载器、操作系统内核以及其他关键组件的签名,以确保这些组件没有被篡改。
数字签名:U-Boot 在安全模式下会使用数字签名来验证每个启动组件的完整性。签名是通过加密算法生成的,通常由一个可信的私钥签名,然后在启动时使用对应的公钥来验证。
可信根(Root of Trust):安全模式依赖于一个硬件或软件的可信根,这个可信根是整个验证链的起点。可信根通常存储在不可变的硬件中,确保启动链的初始阶段是可信的。
攻击防护:安全模式可以防护多种攻击,包括篡改引导加载器、插入恶意代码、或者试图加载未经验证的操作系统。它确保了系统启动过程的完整性和机密性。
适用场景:这种模式通常用于需要高安全性的设备,比如银行终端、嵌入式医疗设备、军事或政府使用的设备。
非安全模式(Non-Secure Boot)
启动过程:在非安全模式下,U-Boot 不会对启动的各个组件进行签名验证。启动过程更加简单和直接,但也因此缺少对引导过程的完整性检查。
无签名验证:非安全模式下,启动的各个组件不需要签名,这意味着任何代码都可以被加载和执行,无需经过额外的验证步骤。
灵活性:这种模式允许开发者和用户快速测试和开发系统,而不必处理签名和验证的复杂性。这对于开发阶段或者低安全需求的设备是有利的。
风险:因为缺乏安全验证,系统更容易受到恶意攻击或意外的篡改,这可能导致加载未经授权的软件或恶意代码。
适用场景:这种模式通常用于开发、调试环境,或者安全性要求较低的消费级设备。
总结
安全模式通过引入数字签名和可信根来确保启动过程的安全性,适用于需要高度安全性的设备。
非安全模式则跳过了这些验证步骤,提供了更大的灵活性和简便性,但也面临更高的安全风险。
1、生成Trust镜像
实际 FS-MP1A 使用的 uboot 是基于Trusted 配置的镜像
(1)建立基础的 Trusted 配置文件(设备树文件上一章内容已修改)
cp configs/stm32mp15_trusted_defconfig configs/stm32mp15_fsmp1a_trusted_defconfig
make stm32mp15_fsmp1a_trusted_defconfig
构建新的配置.config
(2)去掉PCIM
make menuconfig
(3)添加MAE0621A
make menuconfig
(4)保存配置文件
cp .config configs/stm32mp15_fsmp1a_trusted_defconfig
(5)修改上层目录下的Makefile.sdk编译脚本
修改上层目录下的 Makefile.sdk 编译脚本在 UBOOT_CONFIGS 配置项中添加“stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32”在 DEVICE_TREE 配置项中添加“stm32mp157a-fsmp1a”
这样做的目的是为了在编译U-Boot时,将特定的配置和设备树信息包含在编译过程中,从而生成适用于指定设备的U-Boot固件。具体而言: 添加特定的配置文件: stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32:这个配置文件指定了编译U-Boot时使用的配置。 trusted表示这是一个受信任的配置, u-boot.stm32是生成的U-Boot映像文件名。通过添加这个配置,您可以确保编译过程使用正确的设置和参数,生成适合特定硬件平台(如STM32MP15)的固件。 添加特定的设备树文件: stm32mp157a-fsmp1a:设备树文件包含了硬件平台的具体信息,如处理器、内存、外设等。添加这个设备树文件确保生成的U-Boot固件能够正确识别和配置硬件平台上的各个组件。
(6)编译Trust镜像
make distclean
make -f $PWD/../Makefile.sdk all UBOOT_CONFIGS=stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32
步骤解释
使用特定的Makefile:
-f $PWD/…/Makefile.sdk
指定了要使用的Makefile文件,这里是相对于当前目录的上一级目录中的 Makefile.sdk 文件。
指定配置项:
UBOOT_CONFIGS=stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32 设置了U-Boot的配置项,定义了特定的配置文件和生成的U-Boot镜像文件。
执行编译:
all 目标表示要编译所有相关的目标文件,最终生成U-Boot固件。
具体命令
sh复制代码make -f $PWD/…/Makefile.sdk all UBOOT_CONFIGS=stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32
编译过程
执行该命令后,Makefile将会加载配置文件:
使用 stm32mp15_fsmp1a_trusted_defconfig 配置文件,该文件包含了用于编译U-Boot的特定配置。
编译U-Boot:
根据配置文件中的设置,编译U-Boot源码,生成 u-boot.stm32 文件。
生成输出文件:
编译完成后,生成的U-Boot固件文件名为 u-boot.stm32,并且该固件是基于 trusted 的配置,表示这是一个受信任的固件。
目的和好处
定制化编译:通过指定特定的配置文件,确保生成的U-Boot固件适用于特定的硬件平台和使用场景。
自动化编译:使用Makefile和配置项,可以自动化整个编译过程,减少手动干预和错误。
总结
运行 make -f $PWD/…/Makefile.sdk all UBOOT_CONFIGS=stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32 命令后,会使用指定的配置文件和Makefile编译U-Boot,并生成适用于STM32MP15硬件平台的 u-boot.stm32 固件文件。这有助于确保固件的正确性和定制化。
编译完成后生成的镜像文件在上级目录下的 build-trusted 文件夹中有一个“u-boot-stm32mp157a-fsmp1a-trusted.stm32”
cd ../build-trusted
ls
u-boot-stm32mp157a-fsmp1a-trusted.stm32 即为我们后续会使用的镜像文件。
2、Trusted Firmware-A 移植
(1)导入源码
详见上一文章,若前面配置过不需要再次解压。进入 tf-a 目录下
该目录下以 patch 结尾的文件为 ST 官方提供的补丁文件;tf-a-stm32mp-2.2.r1-r0.tar.gz 为标准 tf-a 源码包。
解压标准 tf-a 源码包
解压完成后得到 tf-a-stm32mp-2.2.r1 目录
进入 tf-a 源码目录下:
将 ST 官方补丁文件打到 tf-a 源码中:
for p in
ls -1 …/*.patch; do patch -p1 < $p; done
(2)TF卡分区
见上一文章
(3)建立自己的平台
配置工具链
见上一文章
增加板级相关文件
进入到 tf-a 源码目录
cd ~/FS_MP1A/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/tf-a-stm32mp-2.2.r1-r0/tf-a-stm32mp-2.2.r1
添加设备树文件
cp fdts/stm32mp15xx-dkx.dtsi fdts/stm32mp15xx-fsmp1x.dtsi
cp fdts/stm32mp157a-dk1.dts fdts/stm32mp157a-fsmp1a.dts
修改上层目录下的 Makefile.sdk 编译脚本在 TFA_DEVICETREE 配置项中添加 stm32mp157a-fsmp1a
TFA_DEVICETREE ?= stm32mp157a-fsmp1a stm32mp157a-dk1 stm32mp157d-dk1 stm32mp157c-dk2 stm32mp157f-dk2 stm32mp157c-ed1 stm32mp157f-ed1 stm32mp157a-ev1 stm32mp157c-ev1 stm32mp157d-ev1 stm32mp157f-ev1
修改 fdts/stm32mp157a-fsmp1a.dts 将
\#include "stm32mp15xx-dkx.dtsi"
修改为
\#include "stm32mp15xx-fsmp1x.dtsi"
编译源码
执行如下指令编译 trusted:
make -f $PWD/../Makefile.sdk TFA_DEVICETREE=stm32mp157a-fsmp1a TF_A_CONFIG=trusted ELF_DEBUG_ENABLE='1' all
编译成功后,最后显示内容(部分截图)如下:
编译完成后会在上级 build/trusted 目录得到如下文件:
ls ../ build/trusted
cd ../ build/trusted
固件烧写
由于在移植过程中会多次烧写固件并且会导致正常 tf-a 无法启动,因此推荐使用 TF 卡启动的方式来验证。tf-a 需要使用 trusted 格式的 u-boot 镜像启动,具体的编译方法可参考“1、生成 Trusted 镜像”小节。
将 TF 接入 ubuntu 系统后,查看 TF 卡分区
ls /dev/sd*
/dev/sdb 为 TF 卡设备。如果该设备下只有/dev/sdb1 一个分区则重新分区。
执行如下指令烧写 u-boot:
sudo dd if=tf-a-stm32mp157a-fsmp1a-trusted.stm32 of=/dev/sdb1 conv=fdatasync
sudo dd if=tf-a-stm32mp157a-fsmp1a-trusted.stm32 of=/dev/sdb2 conv=fdatasync
cd /home/liu/FS_MP1A/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/u-boot-stm32mp-2020.01-r0/build-trusted
sudo dd if=u-boot-stm32mp157a-fsmp1a-trusted.stm32 of=/dev/sdb3 conv=fdatasync
其中前两条命令“tf-a-stm32mp157a-fsmp1a-trusted.stm32”为本章节编译得到的,第三条命令中的“u-boot-stm32mp157a-fsmp1a-trusted.stm32”则为“生成 Trusted 镜像”小节得到。
启动开发板
将拨码开关设置为 SD 卡启动方式:
将制作好的 TF 卡插入开发板,上电后会出现如下错误提示:
这个错误产生的原因是电源初始化错误,需重新调整电源相关配置
(4)调整设备树电源设置
由于官方参考板 DK1 采用电源管理芯片做电源管理,而 FS-MP1A 采用分离电路作为电源管理,本例需要将文件中原有电源管理芯片相关内容去掉,增加上固定电源相关内容。
去掉原有电源管理内容
DK1 参考板电源管理芯片挂在 I2C4 上,而 FS-MP1A 并未使用 I2C4 总线,所以直接将I2C4 相关内容完全删除即可。
修改 fdts/stm32mp15xx-fsmp1x.dtsi 文件,将文件中 i2c4 节点相关内容整体删除,删除内容如下:
&i2c4 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c4_pins_a>;
pinctrl-1 = <&i2c4_pins_sleep_a>;
i2c-scl-rising-time-ns = <185>;
i2c-scl-falling-time-ns = <20>;
clock-frequency = <400000>;
status = " okay";
secure-status = "okay";
/*内容太长此处省略*/
watchdog {
compatible = "st,stpmic1-wdt";
status = "disabled";
};
};
}
修改 fdts/stm32mp15xx-fsmp1x.dtsi 文件,删除如下内容:
&cpu0{
cpu-supply = <&vddcore>;
};
&cpu1{
cpu-supply = <&vddcore>;
};
删除以下内容:
dts复制代码&cpu0 {
cpu-supply = <&vddcore>;
};
&cpu1 {
cpu-supply = <&vddcore>;
};
其原因和目的可以包括以下几个方面:
1. 电源管理和配置的更改不再需要特定的电源供应设置:
如果硬件设计或电源管理策略发生了变化,CPU可能不再需要特定的 cpu-supply 设置。移除这些节点意味着系统将依赖于默认的电源管理策略。
硬件电源变化:
硬件设计可能已经改变, &vddcore 电源域可能已经被重命名、移除或者整合到其他电源域中。
2. 简化设备树文件
清理冗余配置:
如果 cpu-supply 配置已经默认由其他部分提供或已经不再需要显式指定,删除这些部分可以简化设备树文件,使其更易于维护。
兼容性考虑:
对于某些情况下,删除这些节点可能是为了确保设备树文件在不同版本的内核或不同的设备树解析器中能够正确工作。
3. 优化和调整性能
动态电源管理:
可能已经引入了更先进的电源管理技术,例如动态电压频率调节 (DVFS),这些技术不再需要静态的 cpu-supply 配置。
示例背景
在特定的硬件设计中, cpu0 和 cpu1 的电源供应由 vddcore 提供,设备树文件中显式声明了这一点:
dts复制代码&cpu0 {
cpu-supply = <&vddcore>;
};
&cpu1 {
cpu-supply = <&vddcore>;
};
删除这些内容可能表明 vddcore 电源管理已经被移交给一个更高层次的电源管理框架,或者是 vddcore 电源域在硬件设计中已经不再单独存在。
总结
删除设备树文件中的 cpu-supply 配置可能是由于硬件设计、电源管理策略、兼容性或简化设备树文件的需要。这种修改通常是为了适应新的硬件设计或改进系统性能。了解具体的删除原因需要参考硬件设计文档和电源管理策略。
vddcore是什么
vddcore 通常指的是嵌入式系统或处理器中的核心电压(Core Voltage)。它是专门用于为处理器的核心部分(如CPU、GPU等)供电的电压轨。核心电压的管理和调节对于确保处理器的稳定运行和优化性能非常重要。
vddcore 的作用和特点:
处理器供电:
vddcore 提供处理器核心逻辑的电源,确保其能够正常执行指令和进行数据处理。
电压调节:
处理器的工作电压通常会随负载变化进行调节。较低的电压有助于节省功耗,而较高的电压则可以提高处理器的性能。
功耗管理:
vddcore 的电压水平直接影响处理器的功耗和热设计。适当的电压管理能够在性能和功耗之间取得平衡。
稳定性和可靠性:
过高或过低的电压都会影响处理器的稳定性。确保
vddcore 在适当的范围内是硬件设计和系统稳定运行的关键。
使用 vddcore 的设备树配置
在设备树文件中,vddcore 通常会被定义为一个电源域,通过特定的电源管理控制器来控制。例如:
dts复制代码&vddcore {
compatible = "regulator-fixed";
regulator-name = "vddcore";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
};
在这种配置中,vddcore 被定义为一个固定电压的电压调节器,提供 1.1V 至 1.3V 之间的电压,并且总是开启。
设备树中的 cpu-supply
设备树中引用 vddcore 为 CPU 提供电源的典型配置如下:
dts复制代码&cpu0 {
cpu-supply = <&vddcore>;
};
&cpu1 {
cpu-supply = <&vddcore>;
};
这种配置明确指定 vddcore 为 cpu0 和 cpu1 提供电源。
总结
vddcore 是核心电压供应,在嵌入式系统和处理器设计中至关重要。它负责为处理器核心部分提供稳定的电源,并通过适当的电压管理来优化性能和功耗。在设备树文件中,通过 cpu-supply 属性将 vddcore 关联到具体的 CPU,确保其获得正确的电源供应
(5)增加固定电源设置
修改 fdts/stm32mp15xx-fsmp1x.dtsi 文件 ,添加以下内容:
vin: vin {
compatible = "regulator-fixed";
regulator-name = "vin";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
v3v3: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v8_audio: regulator-v1v8-audio {
compatible = "regulator-fixed";
regulator-name = "v1v8_audio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
};
v3v3_hdmi: regulator-v3v3-hdmi {
compatible = "regulator-fixed";
regulator-name = "v3v3_hdmi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v2_hdmi: regulator-v1v2-hdmi {
compatible = "regulator-fixed";
regulator-name = "v1v2_hdmi";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
};
vdd: regulator-vdd {
compatible = "regulator-fixed";
regulator-name = "vdd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
vdd_usb: regulator-vdd-usb {
compatible = "regulator-fixed";
regulator-name = "vdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
};
(6)重新编译内容
make -f $PWD/../Makefile.sdk TFA_DEVICETREE=stm32mp157a-fsmp1a TF_A_CONFIG=trusted ELF_DEBUG_ENABLE='1' all
(7)烧录后启动
参照上方固件烧写
(8)修改SDMMC2
修改 fdts/stm32mp15xx-fsmp1x.dtsi 增加 SDMMC2 的信息
在原有 sdmmc1 节点下增加 sdmmc2 的内容,添加内容可参考 arch/arm/dts/stm32mp15xx-edx.dtsi 中 sdmmc2 的写法,内容如下
&sdmmc2 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
non-removable;
st,neg-edge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&v3v3>;
status = "okay";
};
参照上方固件烧写
3、通过Linux更新EMMC中的u-boot
此方式是通过在 linux 终端下更新 u-boot 镜像,使用此方法需确保 linux 可以正常启动。
拨码 0 1 0 EMMC启动
- 在虚拟机下传到板子(base mode)
scp u-boot.img root@192.168.40.85:/home/root
scp u-boot-spl.stm32 root@192.168.40.85:/home/root
- 在虚拟机下传到板子(trust mode)
scp tf-a-stm32mp157a-fsmp1a-trusted.stm32 root@192.168.40.85:/home/root
scp u-boot-stm32mp157a-fsmp1a-trusted.stm32 root@192.168.40.85:/home/root
- 烧录:trust为例
开发板终端执行
echo 0 > /sys/class/block/mmcblk2boot0/force_ro
echo 0 > /sys/class/block/mmcblk2boot1/force_ro
dd if=tf-a-stm32mp157a-fsmp1a-trusted.stm32 of=/dev/mmcblk2boot0 conv=fdatasync
dd if=tf-a-stm32mp157a-fsmp1a-trusted.stm32 of=/dev/mmcblk2boot1 conv=fdatasync
echo 1 > /sys/class/block/mmcblk2boot0/force_ro
echo 1 > /sys/class/block/mmcblk2boot1/force_ro
dd if=u-boot-stm32mp157a-fsmp1a-trusted.stm32 of=/dev/mmcblk2p1 conv=fdatasync
sync
reboot