没有 rootfs 的引导内核(FIT 映像)

没有 rootfs 的引导内核(FIT 映像)

我正在使用的嵌入式 Linux 设备具有以下内核参数:

root=/dev/ram0

此外,内核映像与 initrd 和设备树捆绑在一起以形成扁平化图像树, 或者合身图像。

完全启动后,设备没有持久存储。也就是说,写入文件系统的任何内容都是完全不稳定的。考虑到root=传递给内核的参数,这并不奇怪。

我的问题是:这是如何运作的?

  • 我确实知道Uboot将内核复制到ram中并用命令执行它bootm,但是文件系统文件从哪里来?它们包含在 initrd 中吗?我对 initrd 的理解是它是一个临时构造。如果是这样,它将是 FIT 图像 blob 的偏移量。那么,仅仅通过传递如何root=/dev/ram0足以让内核知道其文件系统在哪里呢?

  • 内核是否执行内省并读取 FIT 映像的标头以确定组成组件的位置?

  • 考虑到 FIT 映像将与内核和设备树 blob 打包在一起,如何支持文件系统更改?

答案1

我确实知道 Uboot 将内核复制到 ram 中并使用 bootm 命令执行它,但是文件系统文件从哪里来?

在启动 fitImage 之前,您必须将其加载到 RAM 中。之后您可以使用 启动它bootm。例如,在拟合图像中,您可以为内核定义Load Address和。Entry Point

它们包含在 initrd 中吗?我对 initrd 的理解是它是一个临时构造。如果是这样,它将是 FIT 图像 blob 的偏移量。那么,如何仅传递 root=/dev/ram0 就足以让内核知道其文件系统在哪里呢?

文件系统的定义是什么取决于您的系统。有一些系统完全从 RAMDISK 运行,并且仅将配置存储到任何类型中NVRAM或闪光。

其他系统使用 RAMDisk 来检查在哪里可以找到根文件系统。例如扫描 USB 总线、SATA 或 SD 卡。当安装根文件系统时,引导过程将继续该分区。由于init需要从PID 1运行。一些需要技巧

内核是否执行内省并读取 FIT 映像的标头以确定组成组件的位置?

否,fitImage 由 u-boot 解析。 u-boot 如何传递 DTB 和 RAMDISK 所在的地址取决于所使用的平台 AFAIK。

考虑到 FIT 映像将与内核和设备树 blob 打包在一起,如何支持文件系统更改?

当需要定期更改文件系统时,您应该考虑使用更灵活的系统。但这取决于您使用的硬件。 SD 卡、NAND、NOR 或旋转磁盘。

答案2

查看内核源码:

  • mtdsplit_fit.c

        /* Search for the rootfs partition after the FIT image */
        ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size, mtd->size,
                                   &rootfs_offset, NULL);
        if (ret) {
                pr_info("no rootfs found after FIT image in \"%s\"\n",
                        mtd->name);
                return ret;
        }
    
  • mtdsplit.c:

    int mtd_find_rootfs_from(struct mtd_info *mtd,
                             size_t from,
                             size_t limit,
                             size_t *ret_offset,
                             enum mtdsplit_part_type *type)
    {
            size_t offset;
            int err;
    
            for (offset = from; offset < limit;
                 offset = mtd_next_eb(mtd, offset)) {
                    err = mtd_check_rootfs_magic(mtd, offset, type);
                    if (err)
                            continue;
    
                    *ret_offset = offset;
                    return 0;
            }
    
            return -ENODEV;
    }
    EXPORT_SYMBOL_GPL(mtd_find_rootfs_from);
    
    
    
    int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset,
                               enum mtdsplit_part_type *type)
    {
            u32 magic;
            size_t retlen;
            int ret;
    
            ret = mtd_read(mtd, offset, sizeof(magic), &retlen,
                           (unsigned char *) &magic);
            if (ret)
                    return ret;
    
            if (retlen != sizeof(magic))
                    return -EIO;
    
            if (le32_to_cpu(magic) == SQUASHFS_MAGIC) {
                    if (type)
                            *type = MTDSPLIT_PART_TYPE_SQUASHFS;
                    return 0;
            } else if (magic == 0x19852003) {
                    if (type)
                            *type = MTDSPLIT_PART_TYPE_JFFS2;
                    return 0;
            } else if (be32_to_cpu(magic) == UBI_EC_MAGIC) {
                    if (type)
                            *type = MTDSPLIT_PART_TYPE_UBI;
                    return 0;
            }
    
            return -EINVAL;
    }
    EXPORT_SYMBOL_GPL(mtd_check_rootfs_magic);
    

相关内容