3

I'm running an embedded board that is booted from an SDCard. The location of the rootfs gets passed to the kernel via kernel parameters:

Kernel command line: console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait panic=10

I've noticed that changing to a different kernel version changes the index to mmcblk1 which causes the device to not boot.

The kernel is built without a initramfs.

The output of udevadm for the two versions:

mmcblk1

$ udevadm info --name=/dev/mmcblk1 --attribute-walk
  looking at device '/devices/platform/soc/1c0f000.mmc/mmc_host/mmc1/mmc1:0001/block/mmcblk1':
    KERNEL=="mmcblk1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{alignment_offset}=="0"
    ATTR{capability}=="50"
    ATTR{discard_alignment}=="0"
    ATTR{ext_range}=="256"
    ATTR{force_ro}=="0"
    ATTR{inflight}=="       0        0"
    ATTR{range}=="8"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="7716864"
    ATTR{stat}=="    2203     1698   122077    22625      654      554    26088     8770        0    12855    31530"

  looking at parent device '/devices/platform/soc/1c0f000.mmc/mmc_host/mmc1/mmc1:0001':
    KERNELS=="mmc1:0001"
    SUBSYSTEMS=="mmc"
    DRIVERS=="mmcblk"
    ATTRS{cid}=="9f544930303030300000000201011a3b"
    ATTRS{csd}=="400e00325b5900001d6f7f800a4000a1"
    ATTRS{date}=="10/2017"
    ATTRS{dsr}=="0x404"
    ATTRS{erase_size}=="512"
    ATTRS{fwrev}=="0x0"
    ATTRS{hwrev}=="0x0"
    ATTRS{manfid}=="0x00009f"
    ATTRS{name}=="00000"
    ATTRS{ocr}=="00200000"
    ATTRS{oemid}=="0x5449"
    ATTRS{preferred_erase_size}=="4194304"
    ATTRS{scr}=="02b5800000000000"
    ATTRS{serial}=="0x00000201"
    ATTRS{ssr}=="000000000200000004049000080a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    ATTRS{type}=="SD"

  looking at parent device '/devices/platform/soc/1c0f000.mmc/mmc_host/mmc1':
    KERNELS=="mmc1"
    SUBSYSTEMS=="mmc_host"
    DRIVERS==""

mmcblk0

~# udevadm info --name=/dev/mmcblk0 --attribute-walk
  looking at device '/devices/platform/soc/1c0f000.mmc/mmc_host/mmc0/mmc0:0001/block/mmcblk0':
    KERNEL=="mmcblk0"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{alignment_offset}=="0"
    ATTR{capability}=="50"
    ATTR{discard_alignment}=="0"
    ATTR{ext_range}=="256"
    ATTR{force_ro}=="0"
    ATTR{inflight}=="       0        0"
    ATTR{range}=="8"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="7716864"
    ATTR{stat}=="    2156     1248   105313    35020       85      263      952     1530        0     8180    36530"

  looking at parent device '/devices/platform/soc/1c0f000.mmc/mmc_host/mmc0/mmc0:0001':
    KERNELS=="mmc0:0001"
    SUBSYSTEMS=="mmc"
    DRIVERS=="mmcblk"
    ATTRS{cid}=="9f5449303030303000000003ba011a5d"
    ATTRS{csd}=="400e00325b5900001d6f7f800a4000a1"
    ATTRS{date}=="10/2017"
    ATTRS{dsr}=="0x404"
    ATTRS{erase_size}=="512"
    ATTRS{fwrev}=="0x0"
    ATTRS{hwrev}=="0x0"
    ATTRS{manfid}=="0x00009f"
    ATTRS{name}=="00000"
    ATTRS{ocr}=="00200000"
    ATTRS{oemid}=="0x5449"
    ATTRS{preferred_erase_size}=="4194304"
    ATTRS{scr}=="02b5800000000000"
    ATTRS{serial}=="0x000003ba"
    ATTRS{ssr}=="000000000200000004049000080a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    ATTRS{type}=="SD"

  looking at parent device '/devices/platform/soc/1c0f000.mmc/mmc_host/mmc0':
    KERNELS=="mmc0"
    SUBSYSTEMS=="mmc_host"
    DRIVERS==""

~# udevadm info --query=property --name=/dev/mmcblk0
    DEVLINKS=/dev/disk/by-id/mmc-00000_0x000003ba /dev/disk/by-path/platform-1c0f000.mmc
    DEVNAME=/dev/mmcblk0
    DEVPATH=/devices/platform/soc/1c0f000.mmc/mmc_host/mmc0/mmc0:0001/block/mmcblk0
    DEVTYPE=disk
    ID_NAME=00000
    ID_PART_TABLE_TYPE=dos
    ID_PART_TABLE_UUID=27e953fe
    ID_PATH=platform-1c0f000.mmc
    ID_PATH_TAG=platform-1c0f000_mmc
    ID_SERIAL=0x000003ba
    MAJOR=179
    MINOR=0
    SUBSYSTEM=block
    TAGS=:systemd:
    USEC_INITIALIZED=4723799

Looking at /etc/udev I found no explicit rules that are addressing the naming for the mmcblk.

# tree /etc/udev
/etc/udev
├── hwdb.bin
├── hwdb.d
├── rules.d
└── udev.conf

The naming does seem to be related to the device tree. Changing different device trees with the same zImage results in different indexes.

Question

What is responsible for setting the index and is there a config to set it to a different starting index?

TheMeaningfulEngineer
  • 5,735
  • 15
  • 64
  • 113
  • Do you have udev in your initramfs? Maybe you can write a rule into your initramfs? – 炸鱼薯条德里克 Jul 30 '18 at 13:30
  • Could you post output of `udevadm info --query=property --name=/dev/mmcblk0`? Answer for your final question about "index" is here: https://doc.opensuse.org/documentation/leap/reference/html/book.opensuse.reference/cha.udev.html – Bob Jul 30 '18 at 14:08
  • Why does the device fail to boot when the path to the rootfs changes? Is there a hardcoded expectation of a particular parth? – Mark Stosberg Jul 30 '18 at 14:23
  • 2
    @MarkStosberg Yup. The rootfs is passed to the kernel via kernel parameters `root=/dev/mmcblk0p2` – TheMeaningfulEngineer Jul 30 '18 at 14:36
  • 1
    @MarkStosberg Read this: https://unix.stackexchange.com/questions/9944/how-does-a-kernel-mount-the-root-partition#18055 and this: https://wiki.gentoo.org/wiki/Initramfs/Guide#The_initial_root_disk – Bob Jul 30 '18 at 15:20

2 Answers2

4

This seems to be the kernel code responsible for making sense of root=/dev/mmcblk0p2.

Given that no initramfs is present, there is no udev daemon running to name the devices and /dev/mmcblk1 doesn't really exist yet anywhere.

The kernel then somehow converts that name into the responsible driver with the function dev_t name_to_dev_t(const char *name):

    ...
    if (strncmp(name, "/dev/", 5) != 0) {
        unsigned maj, min, offset;
        char dummy;

        if ((sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2) ||
            (sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset, &dummy) == 3)) {
            res = MKDEV(maj, min);
            if (maj != MAJOR(res) || min != MINOR(res))
                goto fail;
        } else {
            res = new_decode_dev(simple_strtoul(name, &p, 16));
            if (*p)
                goto fail;
        }
        goto done;
    }

A reference from a lkml discussion points that the changes in the naming could be caused by the ordering in the device tree:

Changes in device ordering can be provoked by the order in which entries in the DT file appear, and hence the order in which the host SD interfaces are probed by the kernel.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
TheMeaningfulEngineer
  • 5,735
  • 15
  • 64
  • 113
1

Ordering of devices in the kernel is not guaranteed anymore. It's for this reason that most distributions have switched to other ways of figuring out what the root filesystem is. You can do one of the following:

  • Use a labeled filesystem:

    tune2fs -L / /dev/mmcblkXpY
    

    (it's safe to do this while the filesystem is mounted). Now boot with root=LABEL=/

  • Use a UUID:

    blkid /dev/mmcblkXpY
    

    ... will tell you what the UUID of your filesystem is. Boot with root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Wouter Verhelst
  • 9,171
  • 18
  • 43
  • Ok, but this all seems to assume a system that booted up. In my case it's about what device to pass as the kernel parameter to the kernel. – TheMeaningfulEngineer Aug 02 '18 at 17:40
  • @TheMeaningfulEngineer - your problem is the lack of `initramfs` - that's why you can't boot the way Wouter suggests... – don_crissti Aug 02 '18 at 20:44
  • We are talking about embedded devices here, so there is no need to complicate the boot process. – RalfFriedl Aug 06 '18 at 06:14
  • @RalfFriedl -- you are mistaken. The kernel doesn't guarantee device ordering. It makes much more sense to use a root device name that does not assume any particular ordering than to use a device name that does. LABEL=/ is extremely easy to use, and also doesn't depend on a particular UUID being in use; I prefer using that on the embedded devices that I use over anything else. – Wouter Verhelst Aug 11 '18 at 11:58