2

An embedded Linux device I am working with has the following kernel parameter:

root=/dev/ram0

Additionally, the kernel image is bundled together with an initrd and device tree to make a flattened image tree, or FIT image.

When fully booted the device does not have persistent storage. That is, anything written to the file system is completely volatile. Considering the root= parameter passed to the kernel, this is not surprising.

My questions is: How does this work?

  • I do know that Uboot copies the kernel into ram and executes it with a bootm command, but where do the filesystem files come from? Are they contained within the initrd? My understanding of an initrd is that it is a temporary construct. If so, it would be an offset into FIT image blob. So, how is just passing root=/dev/ram0 sufficient for the kernel to know where its file system is?

  • Does the kernel perform introspection and read the FIT image's header to determine placement of constituent components?

  • How are file system changes supported inside a FIT image considering it will be packed together with both the kernel and device tree blob?

2 Answers 2

0

I do know that Uboot copies the kernel into ram and executes it with a bootm command, but where do the filesystem files come from?

Before you can boot your fitImage you have to load it into RAM. After this you can start it with bootm. Inside the fit image you can define the Load Address and Entry Point for the kernel for example.

Are they contained within the initrd? My understanding of an initrd is that it is a temporary construct. If so, it would be an offset into FIT image blob. So, how is just passing root=/dev/ram0 sufficient for the kernel to know where its file system is?

It depends on your system what the definition of filesystem is. There are a few systems running completely from a RAMDISK and just storing configuration into any kind of NVRAM or Flash.

Other systems use the RAMDisk to check where to find the root filesystem. For example to scan USB-Bus, SATA or SD-Cards. When the root filesystem is mounted the boot process continuous with this partition. Due to the fact that init needs to run from PID 1. Some tricks are needed.

Does the kernel perform introspection and read the FIT image's header to determine placement of constituent components?

No the fitImage is parsed by u-boot. How the u-boot passes the addresses where the DTB and RAMDISK is located at depends on the used Platform AFAIK.

How are file system changes supported inside a FIT image considering it will be packed together with both the kernel and device tree blob?

When changes to the filesystems are needed on a regular basis you should consider to use something more flexible. But this depends on the hardware you are using. SD-Card, NAND, NOR or spinning disks.

0

Looking at the kernel source code:

  • 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);
    
1
  • Welcome to the site, and thank you for your contribution. Unfortunately, simply showing the relevant source code does not really explain how the FIT boot process works ...
    – AdminBee
    Commented Jul 14, 2020 at 11:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .