Search code examples
yoctobitbake

Force FSCK on boot in yocto image


I would like to enforce a filesystem check on my bitbake'd image. If I understand correctly I need to add fsck=force and fsck.repair=yes to /proc/cmdline. Is this approach correct? What is the right way to do modify /proc/cmdline?

EDIT: I ran oe-pkgdata-util find-path /proc/cmdline which exited with ERROR: Unable to find any package producing path /proc/cmdline. Thus, I speculate it is generated during kernel compilation. Is that correct?


Solution

  • ;tldr add your stuff to bootargs variable in U-Boot

    First of all, yes, your approach is correct - you need to pass two arguments fsck=force and fsck.repair=yes as boot arguments to your kernel while booting. But you are looking in the wrong direction. All this stuff is about booting and Linux kernel, not actually about Yocto or bitbake.

    There are several ways to pass boot arguments to kernel, like

    • hardcode into kernel code (brute-force option, you'll have to dig sources:) )
    • use CONFIG_CMDLINE kernel config (docs say bootloader args would be appended to it)
    • pass arguments via bootloader (the most flexible and usable way)
    • pass arguments by .dtb-file (Device Tree Binary file, more of this here)
    • invent something else, as Linux kernel is a DIY swiss-army-knife

    Using CONFIG_CMDLINE is easy - just append your to this variable like

    CONFIG_CMDLINE=" loglevel=3 fsck=force fsck.repair=yes"
    

    more info about tweaking kernel configs in Yocto here.

    Best way is to use bootloader to pass arguments to your kernel. In Yocto you are likely using U-Boot as bootloader, so bootargs environment variable (in U-Boot environment, NOT in linux userspace environment) is what you need.

    First of all, try to search for file uEnv.txt. It may be found on main partition in the /boot folder, or on separate boot-partition. This file holds some additional configuration options for U-Boot. For example, there may be specified default console for kernel - option console=.... You can append your stuff somewhere there. Likely there would be specific option for adding boot arguments to the kernel. Inside U-Boot such option would be appended to bootargs during boot process.

    If you found uEnv.txt on your device, than it should be somewhere around in Yocto. Search for BSP-meta-layer.

    If there is no such file for your device, bad news - you'll have to dig some U-Boot code)) The command, that actually sets bootargs environment variable to appropriate value is this

    env set bootargs ${bootargs} fsck=force fsck.repair=yes
    

    U-Boot is packaged as single binary and written onto memory device (SDcard or whatever) by some offset. What is important here, during ordinary boot process you have no manual access to U-Boot - it is just loaded automagically, do some stuff and loads the kernel.

    You can however connect to your device's default debug console (with UART likely) and enter the command manually there, but this boot sequence wouldn't be reproducible - next time device is booted, this command wouldn't be applied.

    That's why you need to embed this command exactly into U-Boot source code - to apply command instantly, for every boot.

    Inside U-Boot sources look for your device's configuration file. This should be .h-file (C header) with your board name as part of it's name and variables BOOTENV_BOOTCOMMAND and/or BOOTENV inside it. This variables define boot script for U-Boot. That is, boot sequence for specific device is constant - there should be no need for any manual interactions during boot. That is, during every boot U-Boot is doing pretty the same things. Exactly this things are hardcoded in BOOTENV_BOOTCOMMAND and/or BOOTENV in the form of long C-string with boot script for U-Boot (just like bash-script).

    There you may add this command

    env set bootargs ${bootargs} fsck=force fsck.repair=yes
    

    or maybe you'll find bootargs definition itself, like bootargs=..., so add you arguments right there.

    Also consider userspace utility fsck. You may configure systemd to trigger it on system startup and after that periodically on schedule. This is not actually what you wanted, but maybe this also would be appropriate for your case.