Yocto 映像无法启动

Yocto 映像无法启动

我之前在 StackOverflow 上问过这个问题,但被告知这里是正确的提问地点。

由于我是 Yocto 新手,我在尝试从 HDD 启动我的 intel-corei7-64 core-image-minimal 时遇到了一些问题。我使用 dd 将其放在硬盘驱动器上,但在启动时它因内核恐慌而停止:

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown block (0,0)

我尝试了很多并寻找解决方案。首先,我必须执行 grub 安装并在引导分区中配置 grub.cfg 文件以列出 GRUB 中的映像,但除此之外我没有得到任何进一步的信息。在一些论坛中,他们说这意味着 initramfs 丢失了。我不认为图像本身已损坏,因为它可以在 USB 闪存驱动器上运行。

我的 grub.cfg 如下所示:

set default="0"
set timeout="30"

menuentry 'Yocto' {
        insmod part_msdos
        insmod part_gpt
        insmod ext2
        insmod all_video
        set root='(hd0,gpt2)'
        linux /boot/bzImage-4.19.40-intel-pk-standard root=/dev/sda2
}

如果你们能帮我修复启动错误,那就太好了。此时我几乎无能为力。

此致

亚历克斯

答案1

bzImage-4.19.40-intel-pk-standard root=/dev/sda2

这是直接从 Uefi shell 启动的方法。但实际上,initrd=缺少了!我遇到了完全相同的问题:SATA/SCSI 模块不在内核中,它们是 initramfs 中的模块(大部分)。复制内核旁边的 initrd/initramfs 并将initrd=initram-cpio.gz(adapt "image" name!) 选项添加到命令行。

VFS 错误显示:您给我的根 (/dev/sda2) 位于我无法读取的块设备上。


查找“yocto”后,我想添加:您应该将所需的模块配置为内置模块(“y”)而不是模块(“m”)。这样你就不需要 initrd,这似乎就是这个“嵌入式”项目背后的想法。


在查找 yocto 更多内容后添加...

这个 yocto(和你的 Q)并没有让我孤单。我从 2016 年的一次会议/文章(lwn.net 上)中发现了这一点:

在基础层面 [...]约克托构建根都可以给你相同的最终产品:根文件系统图像对于您的嵌入式设备,核心, A引导装载程序以及兼容的工具链。

在我看来,您宁愿使用“make”来编译内核,加上模块,如果您愿意的话,还可以加上 initrd。

你能告诉我你为什么写这个吗:

我使用 dd 将[内核映像]放在硬盘上

现在这让我很困惑。就好像你已经做到了一样dd ... of=/dev/sda。我会说:我将内核映像复制到分区 x 上的目录中。

所以你已经完成了 Yocto 构建的所有内容,烘烤过的一个内核和 initrd,现在你不知道如何启动一个 linux 内核?!?


我从一个新的迷你电脑套件开始,所以磁盘是空的。我决定使用 GPT 和 Uefi。我上次使用MBR已经是很久以前的事了。首先,我从 USB 闪存启动了 slackware 安装程序。

我使用 fdisk 创建了一些分区,包括“EFI”或“ESP”类型。我明智地把它设为2GB。有些建议仅 100MB。 ESP 需要 vfat 格式化,因为它也由 BIOS 读取。

我发现的唯一(已编译的)Linux 内核是安装程序和实时系统的 ISO 映像中的内核。从 opensuse live usb 系统我可以挂载任何 ISO,然后挂载包含两个文件的 squashs rootfs:kernel 和 initrd。

我将这两个文件(内核和初始 RAM 磁盘)复制到我的 2GB ESP 中。一个内核为 3 到 8 MB,一个 initrd 为 10 到 30 MB。

我将 BIOS 引导至 Uefi shell,在其中我可以通过像 uefi shell 命令一样输入内核名称来启动内核。

这一切都花了我一些时间来弄清楚,所以当我遇到内核恐慌时,这是一个巨大的成功。

fs0: vmlinuz

这就是我如何从 uefi 提示符、ESP(即“fs0”)中使用文件名“vmlinuz”启动内核。

因为 root= 丢失,这也会引起恐慌。我很快就尝试了:

fs0: vmlinuz root=/dev/sda2

这给了我你最初描述的内核恐慌:

VFS:无法挂载 rootfs...

initrd=...cpio.gz从这里开始,您可以采取两条路径:通过添加为 KCL 选项(内核命令行)来使用内核“附带”的 initrd 。或者使用 Fedora 29 内核 --- 它是唯一可以挂载我的 sda 设备的内核。原因是:它内置了一些 Kconfig 选项,而所有其他发行版都将它们作为模块放在 initrd 中(sata、scsi、sd-mod)。

虽然我对快速安装 archlinux 感到非常满意,但我真的认为我“必须”自己编译内核,这样我就可以在没有 initrd 的情况下启动。内核应该能够自行挂载根文件系统。

你看:没有编译或 yocto,没有 grub,只需从发行版进入 ISO,我就可以做很多实验。这些是重要的启动选项:

initrd=...img

1996-2000 年的原始内核文档在某些地方存在误导性。但 Almesberger 明确定义了:他的 initrd“允许”启动分两个阶段进行。并且:rdinit=ramdisk 内的脚本可以将“真实”root 和 switch_root 挂载到其中。在某些情况下,需要进行两步启动。

我跟踪了内核源代码中的“VFS:”内核恐慌。函数“prepare_namespace”是核心。当给出 initrd= 时,会跳过内核挂载 root= 的这部分;来源中有一条评论“如果有 initrd,让它完成所有工作”。

root=/dev/xxyy

如果没有 initrd=,这会直接告诉内核应该“引导”到哪个(块)设备。有了 initrd,就可以用来 switch_root 了。 Aroot=/dev/ram0有特殊含义:它使初始 ram 磁盘从一开始就是真正的根。我猜这对于很多嵌入式系统很有用:rootfs 位于 cpio 文件中而不是分区上。

init=/sbin/init

这是内核在启动时所做的最后一件事:调用第一个进程。与 root= 一样,如果您给出 initrd=,则由 ramdisk 来解析该参数。请注意,在挂载 root= 后,内核只能理解“/”。

一旦你的 BIOS 切换到“Uefi shell”并且你的磁盘是 GPT 格式(或混合/保护性 MBR)并且你添加了一个小的(但不是太小的)ESP vfat 分区,你就可以启动内核和 initrd 了。

我现在的计划只是编译一个可以挂载我的标准SSD分区的内核,所以我不需要initrd。我不需要 yocto 或 grub 来进行一些色情内容“嵌入”。除非我想每月编译两次最新的内核源代码......但是嘿,我想编译一个内核,而不是创建我自己的发行版!

我就停在这里,希望大家能从我的文章中得到一些 Linux 启动的想法内核命令行冒险

答案2

我终于成功启动了我的 Yocto Image!

如果有人在启动时遇到同样的问题,这就是我的做法。

首先,我像往常一样进行了 grub 安装,并在 EFI 分区的 /boot/grub/ 中添加了 grub.cfg(对我来说是 /dev/sda1)。之后我将search --set=root --file /vmlinuz其添加set root=(blabla)到 grub.cfg 文件中。然后我将一个文件vmlinuz从 Fedora 30 复制到我的根分区 (/dev/sda2),因为 sam68 建议将其添加linux /vmlinuz /dev/sda2到我的 grub.cfg 中。我花了几天时间才达到这一点,所以我希望它可以帮助任何人!

相关内容