UEFI固件与系统镜像制作指南

UEFI固件与系统镜像制作指南

截至2025年07月01日, 当前只支持 使用 spinor 启动的产品 搭配 UEFI 固件。

本文基于 Bianbu Minimal 2.2 环境,适用于 MUSE Pi Pro 板卡。

教你如何一步一步制作基于EDK2的 RISC-V UEFI 固件,并制作可以刷机的系统镜像(支持 Titan 固件包 + SD 卡镜像)。

文档内容概览​

本指南共包含以下部分:

环境要求 - 工作空间配置和环境准备

UEFI 固件制作 - 使用EDK2编译生成 edk2.itb 固件文件

GRUB环境搭建 + ESP 分区 - 创建 ES P分区和配置 GRUB 启动器

重新制作文件系统 - 生成 bootfs 和 rootfs 分区镜像

制作 Titan 固件包 - 打包用于 Titan 工具烧录的固件包

SD卡镜像制作 - 制作可直接写入SD卡的镜像文件

环境要求​

准备宿主机的环境, 制作 的 ROOTFS 请参考 Bianbu 2.1/2.2 ROOTFS制作 完成 Bianbu Minimal 2.2 ROOTFS 制作。

设置工作目录

设置工作空间环境变量,分别管理UEFI固件编译和镜像制作:

export UEFI_WORKSPACE=/mnt/uefi-workspaceexport ROOTFS_WORKSPACE=/mnt/image-workspacemkdir -p $UEFI_WORKSPACEmkdir -p $ROOTFS_WORKSPACE

准备 rootfs 和 boot 内容

清理先前制作的分区镜像文件 rootfs.ext4 和 bootfs.ext4

将 rootfs 和 bootfs 目录的内容整合到工作目录,后续会重新制作文件系统:

# 删除之前生成的分区镜像文件rm -f rootfs.ext4 bootfs.ext4# 将bootfs内容合并回rootfs的/boot目录mv bootfs/* rootfs/boot/ # 将整合后的rootfs移动到专用工作空间mv rootfs $ROOTFS_WORKSPACE/rootfs

UEFI 固件制作​

在制作UEFI系统镜像之前,我们需要先制作UEFI固件。这是因为UEFI固件是系统启动的基础组件,它负责硬件初始化和引导加载程序的启动。传统的U-Boot启动方式需要特定的U-Boot镜像,而UEFI启动方式则需要符合UEFI标准的固件镜像。通过先制作UEFI固件(edk2.itb),我们才能替换掉传统的U-Boot镜像,从而实现UEFI标准的启动流程。

安装编译依赖

apt install -y git sudo make gcc g++ uuid-dev python3 u-boot-tools 2to3 brotli

获取 edk2 项目代码

edk2 是 TianoCore 项目的核心仓库,提供UEFI固件开发的基础框架和通用代码;edk2-platforms 是平台特定的代码仓库,包含各种硬件平台的支持代码和配置文件。两者配合使用来构建针对特定硬件平台的UEFI固件。

cd $UEFI_WORKSPACEgit clone https://gitee.com/spacemit-buildroot/edk2.gitgit -C edk2 submodule update --initgit clone https://gitee.com/spacemit-buildroot/edk2-platforms.gitgit -C edk2-platforms submodule update --init

编译UEFI固件

cd $UEFI_WORKSPACEexport GCC5_RISCV64_PREFIX=riscv64-linux-gnu-export PACKAGES_PATH=$UEFI_WORKSPACE/edk2:$UEFI_WORKSPACE/edk2-platformsexport PYTHON_COMMAND=python3export WORKSPACE=$UEFI_WORKSPACE# 初始化EDK2构建环境cd edk2/source edksetup.shcd $UEFI_WORKSPACEln /usr/bin/python3 /usr/bin/python# 编译BaseToolsmake -C $UEFI_WORKSPACE/edk2/BaseTools# 编译UEFI固件build -a RISCV64 -p Platform/Spacemit/K1/MUSE-Pi-Pro/MUSE-Pi-Pro.dsc -t GCC5 -b DEBUG# 将生成的ITB固件文件复制到ROOTFS文件系统工作空间并重命名cp $WORKSPACE/fitimage/MUSE-Pi-Pro/MUSE-Pi-Pro.itb $ROOTFS_WORKSPACE/edk2.itb

验证生成的固件文件

编译完成后,可以在 ROOTFS 文件系统工作空间中找到生成的 UEFI固件文件:

ls -la $ROOTFS_WORKSPACE/edk2.itb

该文件即为用于SpacemiT K1平台的 UEFI 固件镜像。

GRUB 安装与配置​

在UEFI固件制作完成后,我们需要安装和配置GRUB引导器。GRUB是一个多重引导程序,它在UEFI固件初始化硬件后接管系统启动流程。UEFI固件会查找并加载存储在 ESP(EFI System Partition)分区中的GRUB引导器,然后由GRUB根据配置文件加载Linux内核、设备树和初始化镜像。因此,我们需要创建ESP分区、安装GRUB到ESP分区,并配置GRUB来正确识别和启动我们的Bianbu系统。

环境准备

下载并烧录 Bianbu 2.2 镜像到 MUSE Pi Pro,建议使用 Bianbu GNOME 2.2版本的固件,镜像获取方式及 Titan 烧录工具使用方法可参见: 镜像

烧录系统后,请确保系统能够正常连接网络且网络,因为制作分区文件的过程中需要下载软件包。

创建ESP分区文件(给 GRUB 引导用)

在 MUSE Pi Pro 设备上,进入 Bianbu 2.2 系统后,执行以下命令制作ESP分区文件。

sudo apt updatesudo apt install -y dosfstoolssudo dd if=/dev/zero of="$(echo ~)/efi.img" bs=1M count=200sudo mkfs.fat -F32 ~/efi.imgsudo mkdir -p /boot/efisudo mount ~/efi.img /boot/efisudo apt install -y grub-efisudo grub-install riscv64-efisudo update-grubsudo umount /boot/efisudo fsck.vfat -a ~/efi.img

创建的 efi.img 文件就是我们需要的ESP分区文件,请设法将这个文件转移到我们的ROOTFS文件系统工作空间中,例如采用scp远程传输。

以下是一个传输示例:

首先,在Muse Pi Pro 上执行以下命令获取制作ESP分区的用户名以及系统的IP地址。

whoami# 假设输出为: bianbuip a | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1# 假设输出为: 192.168.10.156

然后,切换到宿主机环境,注意这里是宿主机环境,不在虚拟机中,使用 scp 命令将 efi.img 文件远程传输到工作目录。

scp username@ip_addr:~/efi.img ~/bianbu-workspace# 例如:scp bianbu@192.168.10.156:~/efi.img ~/bianbu-workspacedocker cp ~/bianbu-workspace/efi.img build-bianbu-rootfs:/mnt/image-workspace/# 这样efi.img文件就被我们传输到了制作系统镜像的工作目录下

获取 bootfs 和 rootfs 的 UUID

记录 Bianbu 2.2 系统的 bootfs 和 rootfs 对应磁盘分区的 UUID,稍后制作 UEFI 的系统镜像时,要为 rootfs 和 bootfs 设置相同的 UUID。这样做是因为我们的 ESP 分区文件和系统配置是从先前烧录的 Bianbu 系统中提取出来的,如果制作的 UEFI 镜像使用不同的 UUID,那么从原系统复制的配置文件就无法正确识别新的分区,导致系统无法正常启动。

# 查看rootfs分区的UUIDblkid -s UUID -o value $(findmnt -n -o SOURCE /)# 假设输出为: 964235f6-e9c0-4b6d-9b4d-2567f6630358# 查看bootfs分区的UUIDblkid -s UUID -o value $(findmnt -n -o SOURCE /boot)# 假设输出为: 26d39279-a9ae-485e-8467-dda899d9c3bf

GRUB 配置

将更改获取的UUID同步到环境变量中,rootfs的UUID对应UUID_ROOTFS, bootfs的UUID对应UUID_BOOTFS.

# 请将‘xxxxx’替换为对应的UUIDexport UUID_ROOTFS=xxxxxexport UUID_BOOTFS=xxxxx# 例如:# export UUID_ROOTFS=964235f6-e9c0-4b6d-9b4d-2567f6630358# export UUID_BOOTFS=26d39279-a9ae-485e-8467-dda899d9c3bf

准备好ESP分区文件之后,需要在rootfs中安装并配置grub.

cd $ROOTFS_WORKSPACE# 挂载系统资源mount -t proc /proc rootfs/procmount -t sysfs /sys rootfs/sysmount -o bind /dev rootfs/devmount -o bind /dev/pts rootfs/dev/ptsmkdir -p rootfs/boot/efi# 创建临时ESP分区镜像文件,用于grub-install操作# 这个临时文件仅用于满足grub-install的安装要求,让它能够在chroot环境中正确安装GRUB相关文件到rootfs中# 实际使用的ESP分区文件是从真实Bianbu 2.2系统中提取的efi.imgdd if=/dev/zero of=tmp.img bs=1M count=200apt updateapt install -y dosfstoolsmkfs.fat -F32 tmp.imgmount tmp.img rootfs/boot/efi/chroot rootfs /bin/bash -c "apt update"chroot rootfs /bin/bash -c "apt install -y grub-efi"chroot rootfs /bin/bash -c "grub-install riscv-efi"chroot rootfs /bin/bash -c "update-grub"chroot rootfs /bin/bash -c "DEBIAN_FRONTEND=noninteractive apt-get clean"# 卸载并删除临时ESP分区文件,因为实际的ESP分区使用的是从真实系统提取的efi.imgumount tmp.imgrm tmp.img# 卸载系统资源mount | grep "rootfs/proc" > /dev/null && umount -l rootfs/procmount | grep "rootfs/sys" > /dev/null && umount -l rootfs/sysmount | grep "rootfs/dev/pts" > /dev/null && umount -l rootfs/dev/ptsmount | grep "rootfs/dev" > /dev/null && umount -l rootfs/devecho 'usb_start=usb start' >> rootfs/boot/env_k1-x.txtexport UUID_ESP=$(blkid efi.img | grep -o 'UUID="[^"]*"' | cut -d '"' -f 2)cat > rootfs/boot/grub/grub.cfg <

修改fstab配置文件,让ESP分区自动挂载。

cat >rootfs/etc/fstab <

UUID=$UUID_ROOTFS / ext4 defaults,noatime,errors=remount-ro 0 1UUID=$UUID_BOOTFS /boot ext4 defaults 0 2UUID=$UUID_ESP /boot/efi vfat umask=0077 0 1EOF

重新制作文件系统​

cd $ROOTFS_WORKSPACE# 创建bootfs目录并移动boot内容mkdir -p bootfsmv rootfs/boot/* bootfs/# 生成新的文件系统mke2fs -d bootfs -L bootfs -t ext4 -U $UUID_BOOTFS bootfs.ext4 "256M"mke2fs -d rootfs -L rootfs -t ext4 -N 524288 -U $UUID_ROOTFS rootfs.ext4 "2048M"

需要注意的是,因为这里制作的是 Bianbu Minimal, 文件系统体积会比较小,所以设置 rootfs.ext4 文件系统大小为 2048M。如果是制作 Bianbu GNOME桌面版本 或 Bianbu LXQt桌面版本,请根据实际情况调整文件系统大小,例如 10240M。

制作 Titan 固件包​

安装依赖

apt -y install zip

拷贝固件依赖的文件

export TMP=$ROOTFS_WORKSPACE/pack_dirmkdir -p $TMP/factory/# 复制基础固件文件cp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_emmc.bin $TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_sd.bin $TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_spinand.bin $TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_spinor.bin $TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/FSBL.bin $TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/u-boot.itb $TMPcp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/env.bin $TMPcp $ROOTFS_WORKSPACE/rootfs/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb $TMP# 复制UEFI固件文件cp $ROOTFS_WORKSPACE/edk2.itb $TMP# 复制ESP分区文件cp $ROOTFS_WORKSPACE/efi.img $TMP# 复制文件系统镜像cp $ROOTFS_WORKSPACE/bootfs.ext4 $TMPcp $ROOTFS_WORKSPACE/rootfs.ext4 $TMP

下载参考分区表

wget -P $TMP https://gitee.com/bianbu/image-config/raw/main/fastboot.yamlwget -P $TMP https://gitee.com/bianbu/image-config/raw/main/partition_2M.jsonwget -P $TMP https://gitee.com/bianbu/image-config/raw/main/partition_flash.jsonwget -P $TMP https://gitee.com/bianbu/image-config/raw/main/partition_universal.json

修改分区表

修改 partition_2M.json 分区表,将 u-boot.itb 文件替换为 edk2.itb 文件:

# 将u-boot.itb替换为edk2.itbsed -i 's/"image": "u-boot.itb"/"image": "edk2.itb"/g' $TMP/partition_2M.json

修改 partition_universal.json 分区表,添加ESP分区并调整分区顺序:

# 使用jq工具添加ESP分区并调整后续分区偏移量apt install -y jq# 备份原文件cp $TMP/partition_universal.json $TMP/partition_universal.json.bak# 第一步:调整现有分区的偏移量jq '.partitions = (.partitions | map( if .name == "bootfs" then .offset = "260M" elif .name == "rootfs" then .offset = "516M" else . end))' $TMP/partition_universal.json > $TMP/partition_universal_temp.json# 第二步:在uboot分区后插入ESP分区jq '.partitions = ( (.partitions | map(select(.name == "bootinfo" or .name == "fsbl" or .name == "env" or .name == "opensbi" or .name == "uboot"))) + [{ "name": "ESP", "offset": "4M", "size": "256M", "image": "efi.img" }] + (.partitions | map(select(.name == "bootfs" or .name == "rootfs"))))' $TMP/partition_universal_temp.json > $TMP/partition_universal_new.jsonmv $TMP/partition_universal_new.json $TMP/partition_universal.jsonrm $TMP/partition_universal_temp.json# 验证修改结果echo "=== 修改后的分区配置 ==="jq '.partitions[] | select(.name == "uboot" or .name == "ESP" or .name == "bootfs" or .name == "rootfs") | {name, offset, size}' $TMP/partition_universal.json# 删除多余文件rm $TMP/partition_universal.json.bak

修改 partition_flash.json,在 bootfs 分区的 image 数组中添加 edk2.itb 和 efi.img 文件:

# 备份原文件cp $TMP/partition_flash.json $TMP/partition_flash.json.bak# 使用jq工具在bootfs分区的image数组中添加edk2.itb和efi.imgjq '# 在bootfs分区的image数组中添加edk2.itb和efi.img.partitions = (.partitions | map( if .name == "bootfs" then .image += ["edk2.itb", "efi.img"] else . end))' $TMP/partition_flash.json > $TMP/partition_flash_new.jsonmv $TMP/partition_flash_new.json $TMP/partition_flash.json# 验证修改结果echo "=== bootfs分区的image配置 ==="jq '.partitions[] | select(.name == "bootfs") | .image' $TMP/partition_flash.json# 删除多余文件rm $TMP/partition_flash.json.bak

打包 - 生成 zip 文件

cd $TMP# 创建Titan固件包zip -r ../bianbu-custom.zip *

SD卡镜像制作​

如果需要制作可直接写入SD卡的镜像文件,可以使用 genimage 工具:

安装 genimage 工具

echo 'tzdata tzdata/Areas select Asia' | debconf-set-selectionsecho 'tzdata tzdata/Zones/Asia select Shanghai' | debconf-set-selectionsDEBIAN_FRONTEND=noninteractive apt-get -y install wget python3 genimage

准备 SD 卡镜像内容

export SDCARD_TMP=$ROOTFS_WORKSPACE/sdcard_pack_dirmkdir -p $SDCARD_TMP/factory/# 复制固件文件cp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_emmc.bin $SDCARD_TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_sd.bin $SDCARD_TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_spinand.bin $SDCARD_TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/bootinfo_spinor.bin $SDCARD_TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/FSBL.bin $SDCARD_TMP/factorycp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/u-boot.itb $SDCARD_TMPcp $ROOTFS_WORKSPACE/rootfs/usr/lib/u-boot/spacemit/env.bin $SDCARD_TMPcp $ROOTFS_WORKSPACE/rootfs/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb $SDCARD_TMP# 复制UEFI相关文件cp $ROOTFS_WORKSPACE/edk2.itb $SDCARD_TMPcp $ROOTFS_WORKSPACE/efi.img $SDCARD_TMP# 复制文件系统镜像cp $ROOTFS_WORKSPACE/bootfs.ext4 $SDCARD_TMPcp $ROOTFS_WORKSPACE/rootfs.ext4 $SDCARD_TMP

下载并修改分区表配置

# 下载基础分区表wget -P $SDCARD_TMP https://gitee.com/bianbu/image-config/raw/main/partition_universal.json# 修改分区表以支持UEFI启动# 第一步:调整现有分区的偏移量jq '.partitions = (.partitions | map( if .name == "bootfs" then .offset = "260M" elif .name == "rootfs" then .offset = "516M" else . end))' $SDCARD_TMP/partition_universal.json > $SDCARD_TMP/partition_universal_temp.json# 第二步:在uboot分区后插入ESP分区jq '.partitions = ( (.partitions | map(select(.name == "bootinfo" or .name == "fsbl" or .name == "env" or .name == "opensbi" or .name == "uboot"))) + [{ "name": "ESP", "offset": "4M", "size": "256M", "image": "efi.img" }] + (.partitions | map(select(.name == "bootfs" or .name == "rootfs"))))' $SDCARD_TMP/partition_universal_temp.json > $SDCARD_TMP/partition_universal_new.jsonmv $SDCARD_TMP/partition_universal_new.json $SDCARD_TMP/partition_universal.jsonrm $SDCARD_TMP/partition_universal_temp.json

生成 genimage 配置文件

# 下载genimage配置生成脚本wget -P $SDCARD_TMP https://gitee.com/spacemit-buildroot/scripts/raw/bl-v1.0.y/gen_imgcfg.py# 生成genimage配置python3 $SDCARD_TMP/gen_imgcfg.py -i $SDCARD_TMP/partition_universal.json -n bianbu-uefi.sdcard -o $SDCARD_TMP/genimage.cfg

制作SD卡镜像

# 创建临时目录ROOTPATH_TMP="$(mktemp -d)"GENIMAGE_TMP="$(mktemp -d)"# 生成SDCARD镜像genimage \ --config "$SDCARD_TMP/genimage.cfg" \ --rootpath "$ROOTPATH_TMP" \ --tmppath "$GENIMAGE_TMP" \ --inputpath "$SDCARD_TMP" \ --outputpath "."# 清理临时目录rm -rf "$ROOTPATH_TMP" "$GENIMAGE_TMP"echo "=== SDCARD镜像制作完成 ==="ls -la bianbu-uefi.sdcard

当看到以下信息时,说明打包成功。

INFO: hdimage(bianbu-uefi.sdcard): adding partition 'bootinfo' from 'factory/bootinfo_sd.bin' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'fsbl' (in MBR) from 'factory/FSBL.bin' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'env' (in MBR) from 'env.bin' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'opensbi' (in MBR) from 'fw_dynamic.itb' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'uboot' (in MBR) from 'u-boot.itb' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'ESP' (in MBR) from 'efi.img' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'bootfs' (in MBR) from 'bootfs.ext4' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition 'rootfs' (in MBR) from 'rootfs.ext4' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition '[MBR]' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition '[GPT header]' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition '[GPT array]' ...INFO: hdimage(bianbu-uefi.sdcard): adding partition '[GPT backup]' ...INFO: hdimage(bianbu-uefi.sdcard): writing GPTINFO: hdimage(bianbu-uefi.sdcard): writing protective MBRINFO: hdimage(bianbu-uefi.sdcard): writing MBR


二维码红包怎么做的
1个月水刑183次,“直肠补液”更加羞辱!911嫌犯刑讯内幕曝光