QEMU入门4:aarch64虚拟机安装grub

前言

网上关于在aarch64的qemu虚拟机使用的磁盘镜像中使用grub的文章较少,我自己摸索了一下

环境信息

ubuntu22.04
qemu-8.1.5
linux-6.6.57
本文所用内容已上传github,文章全部内容均在arco-qemu/arco-virt路径下
github仓库地址:https://github.com/ARCO-D/arco-qemu

系列文章

QEMU入门1:ubuntu22.04搭建QEMU运行环境
QEMU入门2:使用qemu简单的运行一个aarch64 linux内核
QEMU入门3:制作initrd、根文件系统

grub简介

嵌入式系统的话,一般是uboot引导内核
如果是服务器芯片的话,比较常见的就是UEFI+grub引导
grub就相当于bootloader

编译grub

需要有交叉编译工具链,没工具链不用看了,依赖项配的人想s
制作交叉编译工具链

编译依赖项

grub-2.06
efibootmgr-18
efivar-39
popt-1.18

pkg-config简介

通过xxx.pc文件来查找库的位置(大概吧

编译说明

虽然放到这里有点晚了,但还是要说明下为什么不直接在宿主机上搞——x86的ubuntu上直接执行报错缺arm64的某些模块,apt install也只能装x86的,难绷。

编译popt

(它是efivar的依赖项)
popt是有configure的,指定prefix到交叉编译工具链的…/sysroot/usr目录就行了

编译efivar

(它是efibootmgr的依赖项)
这什么老古董的配置方式(真老古董啊,现在的潮流是meson+ninja)
它指定编译器的配置在src/include/default.mk文件里,这里配置了CC加上CROSS_COMPILE前缀

emm,有个小问题,在make的时候中通过make DESTDIR=…指定DESTDIR不生效,我不知道是为啥
所以我手动编辑了src/Makefile,在前几行指定了

DESTDIR = /home/arco/x-tools/aarch64-arco-linux-gnu/aarch64-arco-linux-gnu/sysroot

注意:通过Make指定的DESTDIR只到sysroot,通过configure指定的需要到sysroot/usr这一层

编译efibootmgr

(不编译efibootmgr也能编grub,但是运行不起来,所以还是得编)
首先,需要导出两个环境变量,EFIDIR是后面会用到的EFI分区的路径,PKG这个是指定pkg-config搜索的路径(不指定的话他又会去搜索系统默认的那堆x86的了

export EFIDIR=/boot/efi
export PKG_CONFIG_PATH="/home/arco/x-tools/aarch64-arco-linux-gnu/aarch64-arco-linux-gnu/sysroot/usr/lib/pkgconfig"

然后,它也是个老古董
它指定编译器的配置方式在Make.defaults里(有些项目是Make.rules)
也默认指定了CROSS_COMPILE前缀,make就行

编译grub

终于。。。我们可以编译grub了,编的人都麻了。。。
不过要说依赖地狱还得是systemd,一个接一个的依赖,还有要处理版本匹配关系

1、下载grub2.06
gnu grub下载地址
不要下载2.12,2.12的归档文件里缺东西,必须要git才行,我很烦且不理解这种行为

2、编译

./configure --prefix=/home/arco/x-tools/aarch64-arco-linux-gnu/aarch64-arco-linux-gnu/sysroot --host=x86_64 --build=aarch64-arco-linux-gnu --with-platform=efi

–with-platform=efi(我已经忘记这是啥了,加上吧)

编译efivars.ko

grub需要这个
linux-6.6.57版本的内核中这个驱动叫efivarfs.ko了,不过没关系,编出来能插就行

安装grub

划EFI分区

这一步需要说明下:网上的示例大部分都是直接使用真实磁盘,没有这个动作
但我这dd出来的空文件哪有这个,得自己划:

参考 划分带分区的文件系统镜像

脚本示例:

mkdir rootfs
# create empty image file
dd if=/dev/zero of=arco.img bs=1024k count=2048
echo "n
p
1

+100M
n
p
2

+1800M
t
1
ef
w
"| fdisk arco.img
lof=`losetup -f`
# p1 is for uefi, p2 is for rootfs
echo "free loop device:$lof"
losetup -P $lof arco.img
mkfs.vfat -F32 "${lof}p1"
mkfs.ext4 "${lof}p2"
mount "${lof}p2" rootfs

启动

进入系统,安装grub

insmod efivarfs.ko
mount -t efivarfs efivarfs /sys/firmware/efi/efivars/
grub-install --efi-directory=/boot/efi --target arm64-efi /dev/vda1
mkdir /boot/efi/EFI/BOOT
cp /boot/efi/EFI/grub/grubaa64.efi /boot/efi/EFI/BOOT/BOOTAA64.EFI

–efi-directory指定的是EFI分区的根目录,这个我挂载的就是/boot/efi,而不是/boot(ubuntu22.04也是,照着搞总没错的)
注意: aarch64的UEFI并不会去查找grubaa64.efi这个文件,它识别的名称是BOOTAA64.EFI
记得sync

更改qemu启动脚本

我之前的启动脚本是:

../build/qemu-system-aarch64 \
-nographic \
-M virt \
-cpu cortex-a55 \
-smp 4 \
-m 1G \
-bios edk2-aarch64-code.fd \
-kernel Image-6.6.57 \
-initrd initrd.cpio.gz \
-append "root=/dev/ram0 console=ttyAMA0 init=/linuxrc ignore_loglevel nokaslr" \
-drive file=arco.img,if=none,id=sdc,format=raw \
-device virtio-blk-device,drive=sdc \
-netdev tap,id=n1,ifname=tap0,script=qemu-ifup,downscript=qemu-ifdown \
-net nic,model=virtio-net-pci,netdev=n1 \
-s

但这样不是通过UEFI启动的,qemu自带的bootloader貌似不会读EFI分区,而是直接加载内核

所以想通过grub启动需要改一下:

../build/qemu-system-aarch64 \
-nographic \
-M virt \
-cpu cortex-a55 \
-smp 4 \
-m 1G \
-bios edk2-aarch64-code.fd \
-net none \
-drive file=arco.img,if=none,id=sdc,format=raw \
-device virtio-blk-device,drive=sdc \
-netdev tap,id=n1,ifname=tap0,script=qemu-ifup,downscript=qemu-ifdown \
-net nic,model=virtio-net-pci,netdev=n1 \
-s

取消了对kernel、initrd的指定,加上了和-bios和-net参数(防止通过PXE启动)

进入grub!

这里进入的还是grub命令行(grub菜单参见下一段)
在这里插入图片描述
通过linux、initrd指定文件位置,然后执行boot引导
(和uboot有点像嗷)

配置grub菜单

更改etc/grub.d/下的配置文件

暂时没深入了解,写个简单的示例(两个略微不同版本的内核来回切):
首先把两个内核的Image放到磁盘镜像的/boot目录下(我这里是6.6.57和6.6.63)
然后编辑40_custom和41_custom两个文件

## 40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry "arco-linux-6.6.57" {
    set root=(hd0,msdos2)
   linux /boot/Image-6.6.57 root=/dev/ram0 console=ttyAMA0 init=/linuxrc ignore_loglevel nokaslr
   initrd /boot/initrd.cpio.gz
}

## 41_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry "arco-linux-6.6.63" {
    set root=(hd0,msdos2)
   linux /boot/Image-6.6.63 root=/dev/ram0 console=ttyAMA0 init=/linuxrc ignore_loglevel nokaslr
   initrd /boot/initrd.cpio.gz
}

grub配置文件不是直接修改grub.cfg来的,而是通过编辑etc/grub.d下的这些配置文件,然后grub-mkconfig生成的:

grub-mkconfig -o /boot/grub/grub.cfg

再次重启,就可以看到像装了双系统那样,熟悉的grub菜单啦

grub菜单

<think>首先,用户的问题是在虚拟机安装特定版本的Linux内核:4.19.90-24.4.v2101.ky10.aarch64。这是一个aarch64架构的内核,表明是针对ARM64架构的。 我需要根据系统级指令来构建我的回答: - 所有行内数学表达式使用$...$格式,但在这个问题中,可能没有数学表达式,所以我可以忽略。 - 独立公式使用$$...$$格式,但同样,可能不需要。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 参考提供的引用内容,但用户说这些引用仅供参考,不是用户真正的需求。用户真正的需求是安装这个内核版本。 提供的引用内容: - [^1]: 关于Linux内核版本的字符串。 - [^2]: 关于docker0网络接口的信息。 - [^3]: 关于Linux软件安装方式的介绍。 这些引用似乎不直接相关到内核安装。用户提到“上述引用仅供参考”,所以我应该基于内核安装的一般知识来回答。 步骤来安装特定内核版本: 1. **确认架构**:用户指定的内核是aarch64架构,所以我需要确保虚拟机环境支持ARM64。如果用户使用的是基于x86的虚拟机,可能需要调整或使用ARM模拟器。 2. **获取内核包**:需要下载这个特定版本的内核包。 3. **安装内核**:使用包管理工具如yum或apt来安装,或者手动编译安装4. **配置和启动**:安装后更新启动加载器配置。 用户提到的是CentOS或类似系统,因为引用[3]提到了yum和RPM。 具体步骤: - 由于内核版本是4.19.90-24.4.v2101.ky10.aarch64,这看起来像是一个定制版本,可能是麒麟软件(KYLIN)的版本。 - 用户需要在虚拟机安装,所以第一步是设置一个ARM64虚拟机,例如使用QEMU或云服务。 - 然后,下载或构建内核包。 如何获取这个内核包? - 可能来自官方仓库或特定源。 - 引用[1]显示了一个内核版本字符串,但它是x86_64架构的,而用户需要aarch64。 - 我应该建议用户检查是否有可用的RPM包或源码。 安装方法: 1. 使用包管理器:如果这个版本在仓库中可用。 2. 手动下载RPM并安装。 3. 从源码编译。 由于这是一个特定版本,可能不在标准仓库中。用户可能需要从麒麟软件的源获取。 回答结构: - 分步骤解释。 - 使用中文。 - 在末尾生成相关问题。 - 添加引用标识,但引用内容不直接相关,所以我需要谨慎使用。用户说“请尽可能多的参考用户上一次的问题和你的回答”,但这是第一次交互,所以没有上一次问题。我可以基于引用[3]来讨论安装方法。 引用[3]提到了软件安装方式:二进制包、RPM包、yum在线安装、源码编译。我可以引用这个来讨论选项。 最终回答大纲: 1. **确认虚拟机环境**:确保虚拟机支持ARM64架构。 2. **查找内核包**:建议搜索麒麟软件仓库或下载RPM包。 3. **安装方法**: - 使用yum安装(如果可用)。 - 手动安装RPM包。 - 源码编译(如果必要)。 4. **配置系统**:更新grub或其他启动加载器。 5. **验证安装**:重启并检查内核版本。 生成相关问题: - 类似于示例,例如: 1. 如何检查Linux系统的架构? 2. 如何添加第三方仓库到yum? 3. 如何从源码编译Linux内核? 添加引用: - 在讨论安装方法时,引用[3]提到yum和RPM安装方式,所以我可以说“根据软件安装的常见方式[^3]”。 - 引用[1]显示了一个内核版本,但架构不同,所以可能不直接相关。 用户指定了内核版本4.19.90-24.4.v2101.ky10.aarch64,我需要确保回答针对aarch64。 在虚拟机安装ARM64内核: - 如果主机是x86,用户需要使用QEMU等模拟器来运行ARM虚拟机。 - 或者直接在ARM硬件上运行虚拟机。 我应该先询问用户当前的设置,但作为AI,我需要提供一般指导。 回答: - 步骤1: 设置ARM64虚拟机环境。 - 步骤2: 获取内核包。 - 步骤3: 安装内核。 - 步骤4: 配置和测试。</think>根据您的需求,在虚拟机安装特定版本的Linux内核(4.19.90-24.4.v2101.ky10.aarch64)需要分步操作。这个内核是针对ARM64架构(aarch64)的定制版本,可能来源于麒麟软件(KYLIN)。以下是详细步骤,基于Linux软件安装的常见方式(如二进制包、RPM包、yum在线安装等)[^3]。整个过程假设您已有基本的Linux操作知识,并在虚拟机环境中工作(如使用QEMU/KVM或VirtualBox,但需确保虚拟机支持ARM64架构)。如果您的宿主机是x86_64,您需要先配置ARM64模拟器(如QEMU),否则无法直接运行aarch64内核。 ### 步骤1: 确认虚拟机环境和架构 在安装前,必须确保虚拟机环境兼容ARM64架构: - 如果您的宿主机是x86_64(如常见PC),需安装ARM模拟器。例如,使用QEMU创建ARM64虚拟机: ```bash # 安装QEMU(以Ubuntu为例) sudo apt update sudo apt install qemu-system-arm qemu-utils # 创建ARM64虚拟机磁盘 qemu-img create -f qcow2 arm_vm.img 20G # 启动ARM64虚拟机(需下载ARM64 ISO镜像,如Ubuntu Server for ARM) qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 4 -M virt -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -hda arm_vm.img -cdrom ubuntu-22.04-live-server-arm64.iso -netdev user,id=net0 -device virtio-net-device,netdev=net0 ``` - 在虚拟机内部,检查当前架构和内核版本: ```bash uname -m # 应输出 aarch64 uname -r # 查看当前内核版本 ``` 如果输出不是aarch64,您无法安装此内核。引用[1]显示了x86_64架构的内核版本(如`Linux version 4.19.90-24.4.v2101.ky10.x86_64`),但您需要的是aarch64版本,两者不兼容[^1]。 ### 步骤2: 获取内核安装包 由于4.19.90-24.4.v2101.ky10.aarch64是一个定制版本,可能不在标准仓库中。您需要从麒麟软件官方源或其他可信源下载: - **推荐方法:使用yum/RPM包安装(如果仓库可用)** 麒麟软件通常提供yum仓库。添加仓库并安装: ```bash # 添加麒麟软件仓库(示例,需替换实际URL) sudo tee /etc/yum.repos.d/kylin.repo <<EOF [kylin] name=Kylin Linux baseurl=http://archive.kylinos.cn/yum/ky10/aarch64/ # 替换为实际ARM64仓库URL enabled=1 gpgcheck=0 # 如果仓库有GPG签名,需导入密钥 EOF # 更新仓库并搜索内核包 sudo yum update yum search kernel-4.19.90-24.4.v2101.ky10.aarch64 # 如果找到,安装内核 sudo yum install kernel-4.19.90-24.4.v2101.ky10.aarch64 ``` 如果仓库不可用,尝试从麒麟官网下载RPM包手动安装[^3]。 - **备选方法:手动下载RPM包** 访问麒麟软件下载页面(如 http://archive.kylinos.cn/)或第三方镜像站,搜索`kernel-4.19.90-24.4.v2101.ky10.aarch64.rpm`。下载后安装: ```bash wget http://example.com/path/to/kernel-4.19.90-24.4.v2101.ky10.aarch64.rpm # 替换为实际URL sudo rpm -ivh kernel-4.19.90-24.4.v2101.ky10.aarch64.rpm ``` - **最后方法:源码编译安装(如果无预编译包)** 从麒麟GitHub或官网获取源码,编译安装: ```bash # 安装编译依赖 sudo yum groupinstall "Development Tools" sudo yum install ncurses-devel bc openssl-devel elfutils-libelf-devel # 下载内核源码(示例URL,需替换) wget http://archive.kylinos.cn/src/kernel-4.19.90-ky10.tar.gz tar -xvf kernel-4.19.90-ky10.tar.gz cd kernel-4.19.90 # 配置和编译(针对ARM64) make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig # 使用默认配置 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) # 安装内核 sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules_install sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install ``` 源码编译耗时较长(30分钟以上),且需要确保虚拟机有足够内存(推荐4GB+)[^3]。 ### 步骤3: 配置启动加载器和验证 安装后,更新启动加载器(如GRUB)并重启: ```bash # 更新GRUB配置 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # 重启系统 sudo reboot # 重启后验证内核版本 uname -r # 应输出 4.19.90-24.4.v2101.ky10.aarch64 ``` 如果启动失败,进入GRUB菜单选择旧内核恢复。 ### 注意事项 - **架构兼容性**:aarch64内核只能运行在ARM64硬件或模拟器上。如果您的虚拟机环境是x86_64(如常见VirtualBox),必须使用QEMU模拟ARM64,否则安装会失败。 - **依赖问题**:麒麟内核可能依赖特定驱动或库。如果yum安装时出现依赖错误,尝试`sudo yum install --skip-broken`或手动解决依赖。 - **风险提示**:安装自定义内核可能导致系统不稳定。建议在测试环境中操作,并备份重要数据。 - **引用说明**:引用[3]介绍了Linux软件安装方式(如yum/RPM),适用于此场景;引用[1]展示了类似内核版本,但架构不同,仅供参考[^1][^3]。 如果您在获取内核包时遇到问题(如仓库URL失效),请联系麒麟软件支持或搜索社区论坛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值