initrdRamfs资源挂载
1、system挂载
mount -t sysfs sysfs /sys
2、dev挂载
mount -t devtmpfs devtmpfs /dev
initrdRamfs资源挂载
1、system挂载
mount -t sysfs sysfs /sys
2、dev挂载
mount -t devtmpfs devtmpfs /dev
1、下载BusyBox
$ wget http://busybox.net/downloads/busybox-1.22.1.tar.bz2
2、配置
$ tar xf busybox-1.22.1.tar.bz2
$ cd busybox-1.22.1
$ make defconfig
$ make menuconfig
执行 make menuconfig 之后,把下面几个选项选上:
Busybox Settings:
- General Configuration -> Don't use /usr
- General Configuration -> Show verbose applet usage messages
- General Configuration -> Runtime SUID/SGID configuration via /etc/busybox.conf
- Build Options -> Build BusyBox as a static binary (no shared libs)
- Cross compi—>指定编译工具链路径,这个可选项
注解:
defconfig – set .config to largest generic configuration就是最大化选用通用的功能
3、编译及安装
$ make
$ make install
执行 make install 之后,会生成一个 _install 目录,里面就是 编译后Busybox,包含 bin 、 sbin 、 及 linuxrc 软链接。这个目 录的内容可以直接复制到下面制作initramfs的目录。
警告:
这里假设initramfs的根目录是 /tmp/initramfs/ 。
$ cp -r _install/* /tmp/initramfs/
到这里,编译Busybox的工作就算是完成了。
1、文件结构
经过上面的步骤之后,现在来看看initramfs根目录( /tmp/initramfs/ )的结 构,应该是这样子的:
├── bin
├── linuxrc -> bin/busybox
└── sbin
下面我们需要创建一个可执行文件 init ,这是一个Shell脚本。
2、init文件
init 起到承上启下的作用。内核加载完成之后,就会执行这个文件,在这个 文件,可以执行相关命令,最后挂载要启动的文件系统,并切换执行目标系统的 /sbin/init 文件,开始引导真实的Linux系统。
为了简单,这里直接贴出源代码,流程也相对比较简单。
#!/bin/sh
echo "Loading, please wait..."
export PATH="/bin:/sbin"
[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir --mode=0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
[ -d /mnt ] || mkdir /mnt
# Mount /proc and /sys:
mount -n proc /proc -t proc
mount -n sysfs /sys -t sysfs
# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
#mount -t tmpfs -o mode=0755 udev /dev
[ -e /dev/console ] || mknod /dev/console c 5 1
[ -e /dev/null ] || mknod /dev/null c 1 3
echo /sbin/mdev >/proc/sys/kernel/hotplug
mdev -s
# Get real root device by LABEL or UUID
get_root() {
if [ ! -z "$LABEL" ]; then
ROOT=`blkid | sed -n "/$LABEL/p" | cut -d: -f 1`
fi
if [ ! -z "$UUID" ]; then
ROOT=`blkid | sed -n "/$UUID/p" | cut -d: -f 1`
fi
}
for x in $(cat /proc/cmdline); do
case $x in
init=*)
init=${x#init=}
;;
root=*)
ROOT=${x#root=}
case $ROOT in
LABEL=*)
LABEL=${ROOT#LABEL=}
;;
UUID=*)
UUID=${ROOT#UUID=}
;;
/dev/nfs)
[ -z "${BOOT}" ] && BOOT=nfs
;;
esac
;;
rootflags=*)
ROOTFLAGS="-o ${x#rootflags=}"
;;
rootfstype=*)
ROOTFSTYPE="${x#rootfstype=}"
;;
rootdelay=*)
ROOTDELAY="${x#rootdelay=}"
;;
resumedelay=*)
RESUMEDELAY="${x#resumedelay=}"
;;
loop=*)
LOOP="${x#loop=}"
;;
loopflags=*)
LOOPFLAGS="-o ${x#loopflags=}"
;;
loopfstype=*)
LOOPFSTYPE="${x#loopfstype=}"
;;
cryptopts=*)
cryptopts="${x#cryptopts=}"
;;
nfsroot=*)
NFSROOT="${x#nfsroot=}"
;;
netboot=*)
NETBOOT="${x#netboot=}"
;;
ip=*)
IPOPTS="${x#ip=}"
;;
boot=*)
BOOT=${x#boot=}
;;
resume=*)
RESUME="${x#resume=}"
;;
noresume)
NORESUME=y
;;
panic=*)
panic="${x#panic=}"
;;
quiet)
quiet=y
;;
ro)
readonly=y
;;
rw)
readonly=n
;;
debug)
debug=y
exec >/tmp/initramfs.debug 2>&1
set -x
;;
debug=*)
debug=y
set -x
;;
break=*)
break=${x#break=}
;;
break)
break=premount
;;
0|1|2|3|4|5|6)
RUNLEVEL=$x
;;
esac
done
for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16;
do
echo "Mounting the ROOT DEVICE (Time $t) ..."
get_root $ROOT
mount -o ro $ROOT /mnt
mountpoint -q /mnt && break
echo "Sleep 4s ..."
sleep 4
done
if [ -e /mnt/sbin/init ] ;
then
umount /proc
umount /sys
exec switch_root /mnt /sbin/init $RUNLEVEL
fi
/bin/sh -i
别忘记给 init 加上执行权限:
$ chmod +x init
现在文件结构应该是这样的:
├── bin
├── init
├── linuxrc -> bin/busybox
└── sbin
到这里,initramfs已经构建好了,下面进行打包及压缩。
注解
关于mdev的几点说明:
3、打包压缩
使用下面这个命令就可以完成打包压缩工作:
cd /tmp/initramfs
find * | cpio -o -H newc | gzip -9 > ../initrd.img
现在, /tmp/initrd.img 就是制作好的initramfs。
Imagesystem.dtbinitrd.img(约 16MB)# 1. 设置加载地址(按需调整,确保不与内核/DTB 冲突)
setenv loadaddr 0x80080000 # kernel
setenv fdtaddr 0x81000000 # dtb
setenv initrd_addr 0x83000000 # initrd
# 2. 加载内核、DTB、initrd
load mmc 0:1 ${loadaddr} /boot/Image
load mmc 0:1 ${fdtaddr} /boot/system.dtb
load mmc 0:1 ${initrd_addr} /boot/initrd.img
# 3. 计算 initrd 大小(U-Boot 自动填充)
setexpr initrd_size ${filesize} - 0
# 4. 构造 bootargs(关键!必须含 initrd 参数)
setenv bootargs \
"console=ttyS0,115200n8 \
root=/dev/mmcblk0p2 rw \
init=/init \
initrd=${initrd_addr},${initrd_size} \
${extra_bootargs}"
# 5. 启动(ARM64 使用 booti)
booti ${loadaddr} ${initrd_addr}:${initrd_size} ${fdtaddr}
#!/bin/bash
echo $1
echo $(stat -c%s flash-system.bin)
if [ "$1" = "Image" ];then
rm flash-system.bin
cp fip-all.bin flash-system.bin
echo "Image"
dd if=$1 of=flash-system.bin bs=1M seek=8 conv=notrunc
elif [ "$1" = "s5000c-64c.dtb" ];then
echo "s5000c-64c.dtb"
dd if=$1 of=flash-system.bin bs=1M seek=78 conv=notrunc
else
echo "Input Error"
exit 1
fi
参考《飞腾编程手册》,0x1a100000为qspi基地址
1、uboot指令操作
mw.l 0x1a100010 0x9f003000 //参考 flash 数据手册,RDID=0x9f
md.l 0x1a10001c 1 (2801401c: 000000c8 )
mw 0x1a100010 0xb7001000 //参考 flash 数据手册,Enable 4-byte Mode cmd=0xb7
mw 0x1a10001c 1
mw 0x1a100010 0x35003000 //参考 flash 数据手册,RDSD=0x35
md.l 0x1a10001c 1 (此处打印 2801401c: 00000008 )
mw 0x1a100000 0x00000005
mw 0x1a100004 0x0308000e
md 0x1000000
2、uboot程序修改
writel(0xb7001000,0x1a100010);
writel(0x1,0x1a10001c);
writel(0x5,0x1a100000);
writel(0x0308000e,0x1a100000);
3、设置启动参数
setenv boot_fdt “booti 0x800000 -:- 0x4e00000”
0x800000为Image起始地址
0x4e00000为dtb起始地址
1、下载补丁
Index of /pub/linux/kernel/projects/rt/5.10/older/
根据内核实际版本下载相应的补丁
2、补丁工具
3、执行
把工具和补丁放在内核的根目录下,直接执行,等待完成。
tkinter.TclError: wrong # args: should be "wm iconphoto window ?-default? image1 ?image2 ...?"
是由于在 Windows 上调用 root.iconphoto(False, photo) 时,传入了 None(即 self._create_icon() 返回 None),而 iconphoto 不接受 None 作为图像参数 —— 这在部分 Windows 版本(尤其是未安装 PIL 的环境)中会直接崩溃。
✅ 根本原因:
您的系统中未安装 Pillow(PIL),导致 _create_icon() 中的 from PIL import Image 失败,回退逻辑也因异常未正确返回默认图标,最终向 iconphoto 传入了 None。
Cmd
pip install Pillow
当加载驱动的时候总是遇到跟内核系统版本不匹配问题,特别是这个+号,这儿是git自动增加的,主要原因就是本地存在未提交改动。解决方式两种:
1、git add提交
2、kernel跟目录下
echo ” > .scmversion # 清除 git 版本标记
echo ‘CONFIG_LOCALVERSION_AUTO=n’ >> .config
┌───────────────┐
│ 上电或复位 │
└──────┬────────┘
↓
┌──────┴────────┐
│ FPGA 拉低 SYNC~│ ← 通知 ADC 停止发数据
└──────┬────────┘
↓
┌──────┴────────────┐
│ ADC 发送 CGS(K28.5)│ ← 帮助 FPGA 实现字符边界对齐、CDR 锁定
└──────┬────────────┘
↓
┌──────┴──────────────┐
│ FPGA 识别 CGS 并拉高 SYNC~│ ← 表示准备接收 ILAS
└──────┬──────────────┘
↓
┌──────┴────────────────────┐
│ ADC 发送 ILAS(4 Multi-Frame) │ ← 传输 JESD 参数 & 多 Lane 对齐
└──────┬────────────────────┘
↓
┌──────┴────────────────────┐
│ FPGA 检查 ILAS 是否一致 │ ← 校验 F、K、M、L、S 等参数
└──────┬────────────────────┘
↓
┌──────┴─────────────┐
│ 进入数据传输状态(DATA) │ ← 链路 Ready!
└────────────────────┘
SYNC~ 启动/K28.5/ 控制符✅ 2️⃣ ILAS 阶段(Initial Lane Alignment Sequence)
🧠 Subclass 特殊流程说明(Subclass 1)
在 Subclass 1 中,额外存在:
| 状态 | 描述 |
|---|---|
| CGS | 接收 K28.5,同步 CD & 边界 |
| ILAS | 接收 4 个多帧的初始化参数 |
| CHECK | 校验 JESD 配置是否匹配 |
| DATA | 正常数据传输 |
| LOST | 如果出现错误,状态机会跳回 CGS 重建链路 |
📦 FPGA 中实现建链过程的模块
| 模块 | 功能 |
|---|---|
GT Transceiver | 串行解码、CDR、8b10b 编码/解码 |
JESD204 RX IP | 包含链路状态机(CGS/ILAS/DATA),配置校验等 |
SYNC~ 控制 | 控制建链流程,通常是输出引脚连到 ADC SYNC |
SYSREF 输入 | Subclass 1 中的外部同步输入 |
| 阶段 | 关键信号 | 发射方行为 | 接收方行为 |
|---|---|---|---|
| CGS | SYNC~ = 0 | 发 /K28.5/ | 边界同步、CDR 锁定 |
| ILAS | SYNC~ = 1 | 发 4 个多帧(含参数) | 解码 JESD 参数、同步 LMFC |
| DATA | SYNC~ = 1 | 发真实采样数据 | 数据解帧、传送到用户逻辑 |
飞腾S5000C处理器支持双BIOS镜像(Dual BIOS)功能,通过SE_RECOVERY硬件引脚和Reset Source状态寄存器实现主备镜像的切换。当主BIOS镜像损坏时,可以通过硬件触发方式切换到备份镜像启动,提高系统可靠性。
S5000C芯片内部集成了一个 Reset Source硬件状态寄存器 ,用于记录芯片复位的原因。该寄存器由芯片硬件自动设置,软件通过SMC(Secure Monitor Call)调用读取。
Reset Source取值定义:
| 值 | 含义 | 说明 |
|---|---|---|
| 0x01 | PowerOn Reset | 上电复位 |
| 0x04 | SoftWare Warm Reset | 软件热复位 |
| 0x05 | Recover | SE_RECOVERY 恢复模式 |
| 0x80 | Watchdog Reset | 看门狗复位 |
| 0x100 | PII Reset | PLL 复位 |
| 0xAA | S3 Reset | S3 休眠恢复 |
| 0xA9 | Standby Reset | 待机恢复 |
SE_RECOVERY是S5000C芯片的一个 硬件配置引脚 ,在芯片复位时刻被采样:
在 s5000c_pack-V1.30 打包工具中,通过Kconfig配置启用双镜像功能:
config RECOVER_ENABLE
bool "recover enable"
default n
if RECOVER_ENABLE
menu "recover config"
config RECOVER_BL33
hex "config bl33 recover address"
default 0x800000
config RECOVER_BL32
hex "config bl32 recover address"
default 0xc00000
endmenu
endif
bl33_recovery的地址在0x800000
bl32_recovery的地址在0xc00000
双镜像文件存放结构:
s5000c_pack-V1.30/
├── pbf_bin/v1_30/ # ATF编译生成的默认镜像
│ ├── bl33.bin
│ └── bl33_recover.bin
└── ...
打包后的固件在SPI Flash中的布局:
| 镜像 | Flash 偏移地址 | 大小 | 说明 |
|---|---|---|---|
| BL1 (Boot ROM) | 0x000000 | – | 启动代码 |
| FIP (BL2/BL31) | – | – | ARM Trusted Firmware |
| BL33 (主镜像) | 0x500000 (5MB) | 根据实际 | 正常启动的 UEFI |
| BL33_RECOVER | 0x800000 (8MB) | 根据实际 | 备份 UEFI 镜像 |
| BL32/BL32_RECOVER | 0xb00000 (11MB) | 根据实际 | TEE 镜像(可选) |
芯片上电/复位
↓
硬件采样SE_RECOVERY引脚 = 高电平
↓
Reset Source = 0x01 (PowerOn) 或 0x04 (Soft Reset)
↓
BL1 (Boot ROM) 运行
↓
读取Reset Source = 0x01/0x04
↓
从Flash 0x500000加载BL33 (主镜像)
↓
启动正常UEFI
外部拉低SE_RECOVERY引脚
↓
触发芯片复位(上电或软复位)
↓
硬件采样SE_RECOVERY引脚 = 低电平
↓
Reset Source = 0x05 (Recover)
↓
BL1 (Boot ROM) 运行
↓
读取Reset Source = 0x05
↓
从Flash 0x800000加载BL33_RECOVER (备份镜像)
↓
启动备份UEFI
在UEFI代码中,通过PSSI库获取Reset Source:
// PssiLib.c
UINT32
PssiGetResetSource (VOID)
{
ARM_SMC_ARGS ArmSmcArgs;
ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));
ArmSmcArgs.Arg0 = PSSI_GET_RST_SOURCE; // SMC调用号: 0xC2000F01
ArmCallSmc (&ArmSmcArgs);
// 返回值即为Reset Source
// 0x01=PowerOn, 0x04=SoftReset, 0x05=Recover...
return ArmSmcArgs.Arg0;
}
UEFI根据Reset Source设置Boot Mode:
// PlatformPei.c
EFI_BOOT_MODE BootMode;
// 获取硬件复位源
RstSource = GetResetSource();
DEBUG ((DEBUG_INFO, "Check reset source : 0x%x\n", RstSource));
// 设置UEFI Boot Mode
Status = PeiServicesSetBootMode (ArmPlatformGetBootMode ());
Status = PeiServicesGetBootMode (&BootMode);
// 如果是Recover模式,安装Recovery Boot Mode PPI
if (BootMode == BOOT_IN_RECOVERY_MODE) {
Status = PeiServicesInstallPpi (&mPpiListRecoveryBootMode);
}
在 theone 打包脚本中,双镜像的处理逻辑:
# 固件定义
BL33=bl33.bin # 主镜像
BL33_RECOVER=bl33_recover.bin # 备份镜像
# 地址配置
bl33_base=0x500000 # 主镜像地址
bl33_recover_addr=0x800000 # 备份镜像地址
# 如果启用recover功能
if [ "$recover_enable" = "y" ];then
# 创建recover镜像证书
echo "create bl33 recover info"
bl33_size=$(wc -c $BL33_RECOVER | awk '{print $1}')
my_scripts/cert_info.sh $bl33_recover_addr $bl33_size bl33_info.
bin
dd if=bl33_info.bin of=$INFO bs=16 seek=1 conv=notrunc
fi
bl33.bin bl33_recover.bin放到pbf_bin文件夹里
场景 :主BIOS镜像(0x500000)损坏,系统无法正常启动
恢复步骤 :
场景 :BIOS升级过程中断电,导致主镜像损坏
恢复机制 :
飞腾S5000C的SE_RECOVERY双BIOS镜像机制通过 硬件引脚 + 状态寄存器 + 固件支持 实现了可靠的故障恢复能力:
Nor Flash XIP 直接执行时,要求 Flash 硬件总线地址等于 SYS_TEXT_BASE,目的是让代码硬编码的链接地址和 CPU 实际取指地址一致,不用拷贝;
bl33.bin和bl33_recovery.bin的SYS_TEXT_BASE地址要根据pack实际使用地址进行修改。否则会报”Synchronous Abort” handler错误。