1. 为什么需要自制ARM设备启动盘如果你手头有一台飞腾、鲲鹏或者瑞芯微芯片的ARM笔记本、工控机或者开发板想装银河麒麟V10或者统信UOS第一道坎往往不是系统本身而是怎么把ISO写进U盘让它能引导起来。x86平台上有Rufus、Ventoy这些成熟工具插上U盘点两下就完事但到了ARM平台情况完全不一样——很多ARM设备的固件UEFI或者U-Boot对U盘引导的支持非常挑剔直接用dd命令写入的ISO经常出现插上没反应卡在启动logo提示找不到引导文件这类问题。我自己前前后后折腾过十来台不同品牌的ARM设备从联想开天、长城擎天到各种国产工控板踩过的坑足够写一本小册子。最后发现最稳的方案是用GRUB2手工搭建一个多引导U盘U盘上只放一个GRUB2引导环境ISO文件以普通文件的形式存放在分区里通过GRUB2的loopback功能动态挂载启动。这样做的好处是一个U盘可以同时放银河麒麟V10、统信UOS、甚至Debian ARM64的ISO想装哪个选哪个不用反复格式化。这篇文章面向的是有一定Linux基础、需要在ARM设备上部署国产操作系统的运维人员、适配工程师和折腾爱好者。我会从分区方案讲起一步步带你做出一个能同时引导银河麒麟和统信UOS的万能启动盘所有命令都可以直接复制执行。整个过程不需要你在ARM设备上操作在一台普通的x86 Linux机器或者虚拟机上就能完成制作。2. 制作前的整体设计与方案选型2.1 为什么不用Rufus和Ventoy先说清楚为什么绕开这些傻瓜工具。Rufus在x86上确实好用但它写入ARM ISO时默认走的是dd模式会把ISO的引导扇区原样写到U盘开头。问题在于银河麒麟和统信UOS的ARM版ISO其引导结构是为光盘或者特定固件设计的直接dd到U盘后很多ARM设备的UEFI固件识别不了这种混合结构表现就是启动项里根本看不到U盘。Ventoy的思路其实和我要讲的方案很像——也是把ISO当文件放用引导器动态挂载。但Ventoy的ARM64支持一直不算完善早期版本在部分国产ARM固件上会出现花屏、卡死而且Ventoy的引导链比较深出问题时排查起来很麻烦。相比之下手工用GRUB2搭建每一层都是透明的出问题能精确定位到是GRUB没起来、还是loopback没挂上、还是内核参数不对。提示如果你的设备固件比较新、对标准UEFI支持良好Ventoy的ARM64版本可以一试。但如果是2020年前后的老固件手工GRUB2方案的成功率明显更高。2.2 分区方案怎么定U盘的分区方案直接决定了兼容性。我试过单分区、双分区、三分区各种组合最后稳定下来的是双分区方案分区文件系统大小建议作用第1分区FAT321-2GB存放GRUB2引导文件固件识别这个分区第2分区exFAT或ext4剩余全部存放ISO镜像文件第一分区必须是FAT32因为几乎所有ARM设备的UEFI固件都只认FAT文件系统里的EFI引导程序。这个分区不用大1GB足够放GRUB2的模块和配置文件。第二分区用来放ISO用exFAT的好处是Windows和Linux都能读写方便你随时往里拷新镜像如果你只在Linux环境下用ext4也行但注意有些固件会尝试扫描所有分区ext4分区可能引起干扰所以更推荐exFAT。分区表类型用GPT不要用MBR。现在主流ARM设备的UEFI固件都支持GPT而且GPT对大于2TB的U盘支持更好。分区时记得给第一分区打上boot和esp标志这是让固件识别它为EFI系统分区的关键。2.3 GRUB2引导的核心原理整个方案的核心就一句话让GRUB2从U盘的FAT32分区启动然后GRUB2用loopback模块把ISO文件当成一个块设备挂载再从里面加载内核和initrd。这里涉及两个关键机制。第一个是loopbackGRUB2内置的loopback模块可以把一个普通文件映射成虚拟磁盘设备命令是loopback loop0 /path/to/image.iso之后就能用(loop0)这个设备名访问ISO内部的文件系统。第二个是linux和initrd命令分别用来加载内核和初始内存盘加载时通过rootlive:CDLABELxxx这样的参数告诉内核去哪里找根文件系统。银河麒麟和统信UOS的ISO内部结构略有差异麒麟的引导文件通常在/images/pxeboot/目录下统信的则在/live/或者/casper/下。制作时需要先挂载ISO确认一下具体路径这个后面实操部分会详细讲。3. 核心细节解析与实操要点3.1 准备工作确认ISO的引导结构拿到银河麒麟V10或者统信UOS的ARM64 ISO后第一件事不是急着写U盘而是先看清楚它内部长什么样。在Linux下执行mkdir -p /mnt/iso_check sudo mount -o loop Kylin-Server-V10-ARM64.iso /mnt/iso_check ls /mnt/iso_check你会看到类似EFI、images、isolinux、LiveOS这样的目录。重点看两个地方一是/images/pxeboot/下有没有vmlinuz和initrd.img二是/EFI/BOOT/下有没有grubaa64.efi或者BOOTAA64.EFI。前者是内核和initrd的位置后者是ISO自带的ARM64引导程序。统信UOS的结构稍有不同通常在/live/下有vmlinuz和initrd.lz引导程序在/EFI/BOOT/下叫grubaa64.efi。把这些路径记下来写GRUB配置时要用。注意不同小版本的ISO路径可能有细微差别比如麒麟V10 SP1和SP2的pxeboot目录名就变过。一定要以你手头ISO的实际结构为准不要照搬网上的配置。3.2 获取ARM64版的GRUB2这是整个制作过程中最容易卡住的一步。你手头的x86 Linux机器上装的GRUB2是x86版本的不能直接拿来给ARM设备用。你需要ARM64版本的GRUB2引导文件具体来说是这几个grubaa64.efiGRUB2的EFI引导程序grub.cfg配置文件arm64-efi/目录下的各种模块normal.mod、loopback.mod等获取途径有三个。最省事的是直接从银河麒麟或统信UOS的ISO里提取——它们的/EFI/BOOT/grubaa64.efi就是现成的ARM64 GRUB2。但ISO里的GRUB2往往缺少loopback模块需要额外补。第二个途径是从Debian或Ubuntu的arm64仓库下载grub-efi-arm64-bin包解压后能得到完整的模块集。第三个途径是在一台ARM设备上执行grub-install生成但这对大多数人来说不现实。我实测下来最稳的做法是从Ubuntu的arm64仓库下载grub-efi-arm64-bin的deb包用dpkg-deb -x解压把/usr/lib/grub/arm64-efi/整个目录拷到U盘第一分区的/EFI/grub/下再把grubaa64.efi放到/EFI/BOOT/BOOTAA64.EFI。这样模块齐全loopback肯定能用。3.3 关键参数内核命令行怎么写GRUB配置里最容易出错的就是内核命令行参数。以银河麒麟V10为例一个能正常启动的配置大概长这样linux (loop0)/images/pxeboot/vmlinuz inst.stage2hd:LABELKylinARM quiet initrd (loop0)/images/pxeboot/initrd.img这里的inst.stage2hd:LABELKylinARM是告诉安装程序去哪个卷标的分区找第二阶段文件。这个LABEL必须和你U盘第二分区的卷标一致否则会提示找不到安装源。统信UOS的参数不太一样通常是linux (loop0)/live/vmlinuz bootlive unionoverlay livecd-installer initrd (loop0)/live/initrd.lz统信用的是live-boot机制bootlive是必须的livecd-installer表示启动后进入安装模式。如果只是想体验不安装去掉livecd-installer即可。提示卷标建议用纯英文大写不要带空格和特殊字符。我见过有人把卷标设成麒麟安装盘结果GRUB解析时直接报错。用KylinARM、UOSARM这种最保险。4. 完整实操过程与核心环节实现4.1 第一步U盘分区与格式化插上U盘先用lsblk确认设备名假设是/dev/sdb。务必确认清楚写错设备名会清空你的硬盘。确认后执行sudo umount /dev/sdb* 2/dev/null sudo parted /dev/sdb --script mklabel gpt sudo parted /dev/sdb --script mkpart primary fat32 1MiB 2GiB sudo parted /dev/sdb --script set 1 boot on sudo parted /dev/sdb --script set 1 esp on sudo parted /dev/sdb --script mkpart primary exfat 2GiB 100%然后格式化两个分区sudo mkfs.vfat -F32 -n BOOTARM /dev/sdb1 sudo mkfs.exfat -n KylinARM /dev/sdb2注意第一分区的卷标BOOTARM和第二分区的KylinARM后面GRUB配置里会用到。如果你要同时放统信UOS第二分区卷标可以改成更通用的名字比如ISODATA然后在GRUB配置里对应修改。4.2 第二步部署GRUB2引导环境挂载第一分区把GRUB2文件拷进去sudo mkdir -p /mnt/bootarm sudo mount /dev/sdb1 /mnt/bootarm sudo mkdir -p /mnt/bootarm/EFI/BOOT sudo mkdir -p /mnt/bootarm/EFI/grub假设你已经从deb包里解压出了arm64-efi模块目录把它拷过去sudo cp -r /path/to/grub-efi-arm64-bin/usr/lib/grub/arm64-efi/* /mnt/bootarm/EFI/grub/ sudo cp /path/to/grubaa64.efi /mnt/bootarm/EFI/BOOT/BOOTAA64.EFI这里有个细节GRUB2的EFI程序默认会去/EFI/grub/找模块和配置但不同编译版本的默认路径可能不同。为了保险可以在/EFI/BOOT/下也放一份grub.cfg内容就是指定prefixset prefix(hd0,gpt1)/EFI/grub normal这样GRUB启动后会先加载这个配置把模块搜索路径指对再进入正常模式。4.3 第三步编写GRUB主配置文件在/mnt/bootarm/EFI/grub/grub.cfg里写入完整配置。下面是我实际在用的一个多引导配置同时支持银河麒麟V10和统信UOSset timeout30 set default0 insmod part_gpt insmod fat insmod exfat insmod loopback insmod linux insmod normal menuentry Kylin V10 ARM64 Installer { set isofile/Kylin-Server-V10-ARM64.iso loopback loop0 (hd0,gpt2)$isofile linux (loop0)/images/pxeboot/vmlinuz inst.stage2hd:LABELKylinARM quiet initrd (loop0)/images/pxeboot/initrd.img } menuentry UOS ARM64 Installer { set isofile/UOS-ARM64.iso loopback loop0 (hd0,gpt2)$isofile linux (loop0)/live/vmlinuz bootlive unionoverlay livecd-installer initrd (loop0)/live/initrd.lz }几个关键点解释一下。insmod exfat是必须的因为第二分区是exFATGRUB2默认不带exFAT驱动不加载这个模块就找不到ISO文件。(hd0,gpt2)指的是第一块磁盘的第二个GPT分区如果你的U盘在设备上被识别为第二块磁盘这里要改成(hd1,gpt2)不过大多数情况下U盘启动时就是hd0。注意GRUB2的磁盘编号从0开始分区编号从1开始。GPT分区在GRUB里用gpt2表示第二个分区不要写成msdos2。4.4 第四步拷贝ISO并验证把银河麒麟和统信UOS的ISO拷到第二分区sudo mkdir -p /mnt/isodata sudo mount /dev/sdb2 /mnt/isodata sudo cp Kylin-Server-V10-ARM64.iso /mnt/isodata/ sudo cp UOS-ARM64.iso /mnt/isodata/ sync拷完后一定要sync确保数据全部落盘。然后卸载两个分区sudo umount /mnt/bootarm /mnt/isodata到这里U盘就做好了。但别急着拔先在x86机器上用QEMU验证一下GRUB能不能正常起来。装个qemu-system-aarch64用U盘镜像启动测试sudo qemu-system-aarch64 -M virt -cpu cortex-a57 -m 2048 \ -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ -drive file/dev/sdb,formatraw,ifnone,idusb \ -device usb-storage,driveusb如果能看到GRUB菜单说明引导环境没问题。看不到的话多半是BOOTAA64.EFI路径不对或者模块缺失回到4.2节检查。4.5 第五步在ARM设备上实测把U盘插到ARM设备上开机狂按启动热键不同品牌不一样联想开天是F12长城擎天是F7工控板常见的是Del或Esc。在启动菜单里选择U盘注意要选带UEFI字样的那个条目不要选Legacy。进入GRUB菜单后选对应的系统条目。银河麒麟的安装程序加载会慢一些因为要从U盘读取整个squashfs镜像耐心等一两分钟。如果卡在Loading initial ramdisk超过三分钟多半是内核参数里的卷标不对检查inst.stage2hd:LABEL后面的值是否和实际卷标一致。统信UOS启动后如果花屏可以在GRUB菜单里按e编辑条目在linux行末尾加nomodeset然后按CtrlX启动。这是显卡驱动不兼容的典型表现装上系统后再装正确的驱动即可。5. 常见问题与排查技巧实录5.1 启动项里根本看不到U盘这是最常见的问题原因通常有三个。第一U盘分区表是MBR而不是GPT部分ARM固件只认GPT。用parted /dev/sdb print确认如果是msdos就重新分区。第二第一分区没有esp标志固件不把它当EFI分区。用parted的set 1 esp on补上。第三BOOTAA64.EFI文件名大小写不对有些固件严格区分大小写必须全大写。5.2 GRUB起来了但找不到ISO文件报错通常是file not found或者unknown filesystem。先确认insmod exfat有没有写进配置这是exFAT分区必须的。如果用的是ext4分区要改成insmod ext2。再确认(hd0,gpt2)这个设备路径对不对可以在GRUB命令行下用ls命令逐个查看比如ls (hd0,gpt2)/看能不能列出ISO文件。5.3 安装过程中提示找不到安装源银河麒麟的inst.stage2hd:LABELxxx里的卷标必须和U盘第二分区完全一致包括大小写。用sudo fatlabel /dev/sdb2或者sudo exfatlabel /dev/sdb2查看当前卷标。另外有些版本的麒麟安装程序不支持从exFAT分区读取安装源这种情况只能把第二分区改成ext4但要注意GRUB里对应的模块也要换。5.4 统信UOS启动后黑屏或花屏前面提过加nomodeset能解决大部分花屏。如果黑屏连GRUB菜单都看不到可能是固件的显示输出模式问题试试在GRUB里加set gfxpayloadtext强制文本模式。还有个小概率情况是U盘读写速度太慢导致initrd加载超时换个USB3.0的U盘基本能解决。5.5 常见问题速查表现象最可能原因快速解决启动项无U盘分区表MBR/缺esp标志改GPTset esp onGRUB报unknown filesystem缺exfat/ext2模块配置里加insmod找不到ISO设备路径写错GRUB命令行ls排查找不到安装源卷标不匹配核对LABEL值花屏/黑屏显卡驱动不兼容加nomodeset卡Loading ramdiskU盘太慢或参数错换USB3.0查卷标5.6 几个我踩过的坑第一个坑是GRUB2模块版本不匹配。我有一次从Ubuntu 22.04的包里拿模块但grubaa64.efi是从麒麟ISO里提取的结果加载normal.mod时报版本错误。后来统一用同一个来源的模块和EFI程序就好了。所以模块和EFI程序一定要来自同一个GRUB2版本。第二个坑是exFAT分区在GRUB下的读取稳定性。大文件超过4GB的ISO在exFAT上读取时偶尔会出错尤其是劣质U盘。后来我改用ext4存ISO虽然Windows下读写麻烦点但稳定性明显提升。如果你主要在Linux环境下制作建议第二分区直接用ext4。第三个坑是U盘本身的质量。我买过某品牌的便宜U盘做出来的启动盘在x86上好好的插到ARM设备上就是各种玄学问题。后来换了三星和闪迪的正规盘同样的制作流程一次成功。ARM设备的USB控制器兼容性普遍不如x86U盘质量真的很关键。6. 进阶玩法与后续扩展6.1 一个U盘塞进多个系统GRUB2的menuentry是可以无限加的你完全可以把银河麒麟V10、统信UOS、Debian ARM64、Ubuntu Server ARM64的ISO全塞进第二分区每个写一个menuentry。唯一要注意的是ISO文件名不要有中文和空格用纯英文短横线命名最稳。我现在的维护盘里放了五个系统的ISO128GB的U盘还剩一大半空间。6.2 加入内存测试和固件更新工具GRUB2还能引导memtest86和UEFI Shell这两个在排查ARM设备硬件问题时很有用。memtest的ARM64 EFI版本可以从官网下载放到第一分区menuentry里用chainloader加载即可。UEFI Shell更简单很多ARM固件自带在启动菜单里直接选就行。6.3 自动化制作脚本如果你经常需要做这种启动盘可以把整个流程写成一个bash脚本。核心就是把分区、格式化、拷贝GRUB、生成配置这几步串起来用变量控制U盘设备名和ISO路径。我自己的脚本大概80行跑一次不到两分钟比手工操作快得多也不容易出错。脚本里记得加设备名确认环节防止误写硬盘。6.4 关于持久化存储默认的live模式重启后所有改动都会丢失。如果想让统信UOS的live环境能保存设置可以在第二分区创建一个persistence.conf文件内容写/ union然后在GRUB的linux行加persistence参数。这样系统会把改动保存到U盘上下次启动还在。不过要注意持久化会拖慢启动速度而且U盘写入寿命有限别把它当日常系统用。最后分享一个我自己的习惯每次做好启动盘后都会在U盘根目录放一个readme.txt写清楚制作日期、包含哪些ISO、对应的GRUB配置要点。过几个月再拿出来用的时候看一眼就全想起来了省得重新排查。这个习惯帮我省了不少时间你也可以试试。
